From b61818e7afdd04251ec5573f82cff6995af65991 Mon Sep 17 00:00:00 2001 From: Andrew Thelen Date: Tue, 25 Mar 2025 14:20:42 -0400 Subject: [PATCH 1/9] optional initial coordinates for mphys builder to initialize meld with --- funtofem/mphys/mphys_meld.py | 33 ++++++++++++++++++++ funtofem/mphys/mphys_meld_lfd.py | 53 +++++++++++++++++++++++++------- 2 files changed, 75 insertions(+), 11 deletions(-) diff --git a/funtofem/mphys/mphys_meld.py b/funtofem/mphys/mphys_meld.py index b5b9e375..f12c3039 100644 --- a/funtofem/mphys/mphys_meld.py +++ b/funtofem/mphys/mphys_meld.py @@ -26,6 +26,7 @@ def initialize(self): self.options.declare("aero_nnodes") self.options.declare("check_partials") self.options.declare("bodies", recordable=False) + self.options.declare("use_initial_coords") self.struct_ndof = None self.struct_nnodes = None @@ -63,6 +64,21 @@ def setup(self): desc="structural node displacements", tags=["mphys_coupling"], ) + if self.options["use_initial_coords"]: + self.add_input( + X_STRUCT0 + "_initial", + shape_by_conn=True, + distributed=True, + desc="baseline structural node coordinates with which to initialize MELD", + tags=["mphys_coordinates"], + ) + self.add_input( + X_AERO0 + "_initial", + shape_by_conn=True, + distributed=True, + desc="baseline aero surface node coordinates with which to initialize MELD", + tags=["mphys_coordinates"], + ) # outputs self.add_output( @@ -79,6 +95,20 @@ def setup(self): def compute(self, inputs, outputs): for body in self.bodies: + if not body.initialized_meld and self.options["use_initial_coords"]: + x_s0 = np.array( + inputs[X_STRUCT0 + "_initial"][body.struct_coord_indices], + dtype=TransferScheme.dtype, + ) + x_a0 = np.array( + inputs[X_AERO0 + "_initial"][body.aero_coord_indices], + dtype=TransferScheme.dtype, + ) + body.meld.setStructNodes(x_s0) + body.meld.setAeroNodes(x_a0) + body.meld.initialize() + body.initialized_meld = False + x_s0 = np.array( inputs[X_STRUCT0][body.struct_coord_indices], dtype=TransferScheme.dtype, @@ -556,6 +586,7 @@ def __init__( check_partials=False, linearized=False, body_tags=None, + use_initial_coords=False, ): self.aero_builder = aero_builder self.struct_builder = struct_builder @@ -565,6 +596,7 @@ def __init__( self.under_check_partials = check_partials self.linearized = linearized self.body_tags = body_tags if body_tags is not None else [] + self.use_initial_coords = use_initial_coords if len(self.body_tags) > 0: # make into lists, potentially for different bodies if not hasattr(self.n, "__len__"): @@ -641,6 +673,7 @@ def get_coupling_group_subsystem(self, scenario_name=None): aero_nnodes=self.nnodes_aero, check_partials=self.under_check_partials, bodies=self.bodies, + use_initial_coords=self.use_initial_coords, ) load_xfer = MeldLoadXfer( diff --git a/funtofem/mphys/mphys_meld_lfd.py b/funtofem/mphys/mphys_meld_lfd.py index db6a03cd..fc321ccf 100644 --- a/funtofem/mphys/mphys_meld_lfd.py +++ b/funtofem/mphys/mphys_meld_lfd.py @@ -8,6 +8,10 @@ from funtofem import TransferScheme +# Set MPhys variable names +X_STRUCT0 = MPhysVariables.Structures.COORDINATES +X_AERO0 = MPhysVariables.Aerodynamics.Surface.COORDINATES_INITIAL + class ModeTransfer(om.ExplicitComponent): def initialize(self): @@ -16,6 +20,7 @@ def initialize(self): self.options.declare("ndof_struct") self.options.declare("nnodes_aero") self.options.declare("meld") + self.options.declare("use_initial_coords") self.first_pass = True @@ -23,7 +28,7 @@ def setup(self): # self.set_check_partial_options(wrt='*',method='cs',directional=True) self.add_input( - "x_struct0", + X_STRUCT0, shape_by_conn=True, distributed=True, tags=["mphys_coordinates"], @@ -35,8 +40,23 @@ def setup(self): tags="mphys_coupling", ) self.add_input( - "x_aero0", shape_by_conn=True, distributed=True, tags=["mphys_coordinates"] + X_AERO0, shape_by_conn=True, distributed=True, tags=["mphys_coordinates"] ) + if self.options["use_initial_coords"]: + self.add_input( + X_STRUCT0 + "_initial", + shape_by_conn=True, + distributed=True, + desc="baseline structural node coordinates with which to initialize MELD", + tags=["mphys_coordinates"], + ) + self.add_input( + X_AERO0 + "_initial", + shape_by_conn=True, + distributed=True, + desc="baseline aero surface node coordinates with which to initialize MELD", + tags=["mphys_coordinates"], + ) nmodes = self.options["nmodes"] self.nnodes_aero = self.options["nnodes_aero"] @@ -53,9 +73,20 @@ def setup(self): def compute(self, inputs, outputs): meld = self.options["meld"] + + if self.first_pass and self.options["use_initial_coords"]: + aero_X = np.array(inputs[X_AERO0 + "_initial"], dtype=TransferScheme.dtype) + struct_X = np.array( + inputs[X_STRUCT0 + "_initial"], dtype=TransferScheme.dtype + ) + meld.setAeroNodes(aero_X) + meld.setStructNodes(struct_X) + meld.initialize() + self.first_pass = False + nmodes = self.options["nmodes"] - aero_X = np.array(inputs["x_aero0"], dtype=TransferScheme.dtype) - struct_X = np.array(inputs["x_struct0"], dtype=TransferScheme.dtype) + aero_X = np.array(inputs[X_AERO0], dtype=TransferScheme.dtype) + struct_X = np.array(inputs[X_STRUCT0], dtype=TransferScheme.dtype) aero_modes = np.zeros((aero_X.size, nmodes), dtype=TransferScheme.dtype) struct_modes = inputs["mode_shapes_struct"].reshape((-1, nmodes)) @@ -81,8 +112,8 @@ def compute(self, inputs, outputs): def compute_jacvec_product(self, inputs, d_inputs, d_outputs, mode): meld = self.options["meld"] nmodes = self.options["nmodes"] - x_s0 = np.array(inputs["x_struct0"], dtype=TransferScheme.dtype) - x_a0 = np.array(inputs["x_aero0"], dtype=TransferScheme.dtype) + x_s0 = np.array(inputs[X_STRUCT0], dtype=TransferScheme.dtype) + x_a0 = np.array(inputs[X_AERO0], dtype=TransferScheme.dtype) meld.setStructNodes(x_s0) meld.setAeroNodes(x_a0) @@ -128,19 +159,19 @@ def compute_jacvec_product(self, inputs, d_inputs, d_outputs, mode): ] -= np.array(prod[i::3], dtype=np.float64) # du_a/dx_a0^T * psi = - psi^T * dD/dx_a0 in F2F terminology - if "x_aero0" in d_inputs: + if X_AERO0 in d_inputs: prod = np.zeros( - d_inputs["x_aero0"].size, dtype=TransferScheme.dtype + d_inputs[X_AERO0].size, dtype=TransferScheme.dtype ) meld.applydDdxA0(du_a, prod) - d_inputs["x_aero0"] -= np.array(prod, dtype=float) + d_inputs[X_AERO0] -= np.array(prod, dtype=float) - if "x_struct0" in d_inputs: + if X_STRUCT0 in d_inputs: prod = np.zeros( self.nnodes_struct * 3, dtype=TransferScheme.dtype ) meld.applydDdxS0(du_a, prod) - d_inputs["x_struct0"] -= np.array(prod, dtype=float) + d_inputs[X_STRUCT0] -= np.array(prod, dtype=float) class MeldLfdBuilder(MeldBuilder): From 49b1a6ab59a015f4a40a884b393e4326f26840b5 Mon Sep 17 00:00:00 2001 From: Andrew Thelen Date: Tue, 25 Mar 2025 14:58:39 -0400 Subject: [PATCH 2/9] minor mods based on Kevin's original demo --- funtofem/mphys/mphys_meld.py | 55 ++++++++++++++++++++------------ funtofem/mphys/mphys_meld_lfd.py | 32 +++++++++++-------- 2 files changed, 52 insertions(+), 35 deletions(-) diff --git a/funtofem/mphys/mphys_meld.py b/funtofem/mphys/mphys_meld.py index f12c3039..2ac68981 100644 --- a/funtofem/mphys/mphys_meld.py +++ b/funtofem/mphys/mphys_meld.py @@ -26,7 +26,11 @@ def initialize(self): self.options.declare("aero_nnodes") self.options.declare("check_partials") self.options.declare("bodies", recordable=False) - self.options.declare("use_initial_coords") + self.options.declare( + "use_ref_coordinates", + types=bool, + desc="Use separate aero and struct reference coordinates for transfer scheme initialization (same variable name with '_ref' appended)", + ) self.struct_ndof = None self.struct_nnodes = None @@ -64,16 +68,16 @@ def setup(self): desc="structural node displacements", tags=["mphys_coupling"], ) - if self.options["use_initial_coords"]: + if self.options["use_ref_coordinates"]: self.add_input( - X_STRUCT0 + "_initial", + X_STRUCT0 + "_ref", shape_by_conn=True, distributed=True, desc="baseline structural node coordinates with which to initialize MELD", tags=["mphys_coordinates"], ) self.add_input( - X_AERO0 + "_initial", + X_AERO0 + "_ref", shape_by_conn=True, distributed=True, desc="baseline aero surface node coordinates with which to initialize MELD", @@ -93,21 +97,30 @@ def setup(self): # partials # self.declare_partials(U_AERO,[X_STRUCT0,X_AERO0,U_STRUCT]) + def _initialize_xfer(self, inputs, body): + if self.options["use_ref_coordinates"]: + x_s0 = np.array( + inputs[X_STRUCT0 + "_ref"][body.struct_coord_indices], + dtype=TransferScheme.dtype, + ) + x_a0 = np.array( + inputs[X_AERO0 + "_ref"][body.aero_coord_indices], + dtype=TransferScheme.dtype, + ) + else: + x_s0 = np.array( + inputs[X_STRUCT0][body.struct_coord_indices], + dtype=TransferScheme.dtype, + ) + x_a0 = np.array( + inputs[X_AERO0][body.aero_coord_indices], dtype=TransferScheme.dtype + ) + body.meld.setStructNodes(x_s0) + body.meld.setAeroNodes(x_a0) + body.meld.initialize() + def compute(self, inputs, outputs): for body in self.bodies: - if not body.initialized_meld and self.options["use_initial_coords"]: - x_s0 = np.array( - inputs[X_STRUCT0 + "_initial"][body.struct_coord_indices], - dtype=TransferScheme.dtype, - ) - x_a0 = np.array( - inputs[X_AERO0 + "_initial"][body.aero_coord_indices], - dtype=TransferScheme.dtype, - ) - body.meld.setStructNodes(x_s0) - body.meld.setAeroNodes(x_a0) - body.meld.initialize() - body.initialized_meld = False x_s0 = np.array( inputs[X_STRUCT0][body.struct_coord_indices], @@ -130,7 +143,7 @@ def compute(self, inputs, outputs): body.meld.setAeroNodes(x_a0) if not body.initialized_meld: - body.meld.initialize() + self._initialize_xfer(inputs, body) body.initialized_meld = True body.meld.transferDisps(u_s, u_a) @@ -586,7 +599,7 @@ def __init__( check_partials=False, linearized=False, body_tags=None, - use_initial_coords=False, + use_ref_coordinates=False, ): self.aero_builder = aero_builder self.struct_builder = struct_builder @@ -596,7 +609,7 @@ def __init__( self.under_check_partials = check_partials self.linearized = linearized self.body_tags = body_tags if body_tags is not None else [] - self.use_initial_coords = use_initial_coords + self.use_ref_coordinates = use_ref_coordinates if len(self.body_tags) > 0: # make into lists, potentially for different bodies if not hasattr(self.n, "__len__"): @@ -673,7 +686,7 @@ def get_coupling_group_subsystem(self, scenario_name=None): aero_nnodes=self.nnodes_aero, check_partials=self.under_check_partials, bodies=self.bodies, - use_initial_coords=self.use_initial_coords, + use_ref_coordinates=self.use_ref_coordinates, ) load_xfer = MeldLoadXfer( diff --git a/funtofem/mphys/mphys_meld_lfd.py b/funtofem/mphys/mphys_meld_lfd.py index fc321ccf..2569585c 100644 --- a/funtofem/mphys/mphys_meld_lfd.py +++ b/funtofem/mphys/mphys_meld_lfd.py @@ -20,7 +20,11 @@ def initialize(self): self.options.declare("ndof_struct") self.options.declare("nnodes_aero") self.options.declare("meld") - self.options.declare("use_initial_coords") + self.options.declare( + "use_ref_coordinates", + types=bool, + desc="Use separate aero and struct reference coordinates for transfer scheme initialization (same variable name with '_ref' appended)", + ) self.first_pass = True @@ -42,7 +46,7 @@ def setup(self): self.add_input( X_AERO0, shape_by_conn=True, distributed=True, tags=["mphys_coordinates"] ) - if self.options["use_initial_coords"]: + if self.options["use_ref_coordinates"]: self.add_input( X_STRUCT0 + "_initial", shape_by_conn=True, @@ -71,19 +75,19 @@ def setup(self): tags=["mphys_coupling"], ) + def _initialize_xfer(self, inputs, meld): + if self.options["use_ref_coordinates"]: + aero_X = np.array(inputs[X_AERO0 + "_ref"], dtype=TransferScheme.dtype) + struct_X = np.array(inputs[X_STRUCT0 + "_ref"], dtype=TransferScheme.dtype) + else: + aero_X = np.array(inputs[X_AERO0], dtype=TransferScheme.dtype) + struct_X = np.array(inputs[X_STRUCT0], dtype=TransferScheme.dtype) + meld.setStructNodes(struct_X) + meld.setAeroNodes(aero_X) + meld.initialize() + def compute(self, inputs, outputs): meld = self.options["meld"] - - if self.first_pass and self.options["use_initial_coords"]: - aero_X = np.array(inputs[X_AERO0 + "_initial"], dtype=TransferScheme.dtype) - struct_X = np.array( - inputs[X_STRUCT0 + "_initial"], dtype=TransferScheme.dtype - ) - meld.setAeroNodes(aero_X) - meld.setStructNodes(struct_X) - meld.initialize() - self.first_pass = False - nmodes = self.options["nmodes"] aero_X = np.array(inputs[X_AERO0], dtype=TransferScheme.dtype) struct_X = np.array(inputs[X_STRUCT0], dtype=TransferScheme.dtype) @@ -95,7 +99,7 @@ def compute(self, inputs, outputs): meld.setStructNodes(struct_X) if self.first_pass: - meld.initialize() + self._initialize_xfer(inputs, meld) self.first_pass = False struct_mode = np.zeros(self.nnodes_struct * 3, dtype=TransferScheme.dtype) From eaddc79cf0606cf50153c44824f866a5e3c9fe16 Mon Sep 17 00:00:00 2001 From: Andrew Thelen Date: Tue, 25 Mar 2025 15:15:49 -0400 Subject: [PATCH 3/9] forgot to change initial to ref in two places --- funtofem/mphys/mphys_meld_lfd.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/funtofem/mphys/mphys_meld_lfd.py b/funtofem/mphys/mphys_meld_lfd.py index 2569585c..56f67978 100644 --- a/funtofem/mphys/mphys_meld_lfd.py +++ b/funtofem/mphys/mphys_meld_lfd.py @@ -48,14 +48,14 @@ def setup(self): ) if self.options["use_ref_coordinates"]: self.add_input( - X_STRUCT0 + "_initial", + X_STRUCT0 + "_ref", shape_by_conn=True, distributed=True, desc="baseline structural node coordinates with which to initialize MELD", tags=["mphys_coordinates"], ) self.add_input( - X_AERO0 + "_initial", + X_AERO0 + "_ref", shape_by_conn=True, distributed=True, desc="baseline aero surface node coordinates with which to initialize MELD", From 1a10318027be021c031a752ed007cf953eed9e66 Mon Sep 17 00:00:00 2001 From: Andrew Thelen Date: Fri, 4 Apr 2025 11:47:25 -0400 Subject: [PATCH 4/9] fix for meld lfd builder --- funtofem/mphys/mphys_meld_lfd.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/funtofem/mphys/mphys_meld_lfd.py b/funtofem/mphys/mphys_meld_lfd.py index 56f67978..74794742 100644 --- a/funtofem/mphys/mphys_meld_lfd.py +++ b/funtofem/mphys/mphys_meld_lfd.py @@ -188,9 +188,10 @@ def __init__( n=200, beta=0.5, check_partials=False, + use_ref_coordinates=False, ): self.nmodes = nmodes - super().__init__(aero_builder, struct_builder, isym, n, beta, check_partials) + super().__init__(aero_builder, struct_builder, isym, n, beta, check_partials, False, None, use_ref_coordinates) def get_post_coupling_subsystem(self): return ModeTransfer( @@ -199,4 +200,5 @@ def get_post_coupling_subsystem(self): ndof_struct=self.ndof_struct, nnodes_aero=self.nnodes_aero, meld=self.meld, + use_ref_coordinates=self.use_ref_coordinates, ) From 59ce661144f9af6c9558efcd8a62c7afc9168c56 Mon Sep 17 00:00:00 2001 From: Andrew Thelen Date: Tue, 10 Jun 2025 09:30:56 -0400 Subject: [PATCH 5/9] run black --- funtofem/mphys/mphys_meld_lfd.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/funtofem/mphys/mphys_meld_lfd.py b/funtofem/mphys/mphys_meld_lfd.py index 74794742..e036b19d 100644 --- a/funtofem/mphys/mphys_meld_lfd.py +++ b/funtofem/mphys/mphys_meld_lfd.py @@ -191,7 +191,17 @@ def __init__( use_ref_coordinates=False, ): self.nmodes = nmodes - super().__init__(aero_builder, struct_builder, isym, n, beta, check_partials, False, None, use_ref_coordinates) + super().__init__( + aero_builder, + struct_builder, + isym, + n, + beta, + check_partials, + False, + None, + use_ref_coordinates, + ) def get_post_coupling_subsystem(self): return ModeTransfer( From cac83e7e8f00ac8f1e7a7e7aac8fb4187ccab936 Mon Sep 17 00:00:00 2001 From: Andrew Thelen Date: Tue, 10 Jun 2025 13:02:32 -0400 Subject: [PATCH 6/9] missing mphysvariables in mphys_meld_lfd --- funtofem/mphys/mphys_meld_lfd.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/funtofem/mphys/mphys_meld_lfd.py b/funtofem/mphys/mphys_meld_lfd.py index e036b19d..bc932896 100644 --- a/funtofem/mphys/mphys_meld_lfd.py +++ b/funtofem/mphys/mphys_meld_lfd.py @@ -4,10 +4,12 @@ import numpy as np import openmdao.api as om -from .mphys_meld import MeldBuilder +from mphys import MPhysVariables from funtofem import TransferScheme +from .mphys_meld import MeldBuilder + # Set MPhys variable names X_STRUCT0 = MPhysVariables.Structures.COORDINATES X_AERO0 = MPhysVariables.Aerodynamics.Surface.COORDINATES_INITIAL From b20bed95c989a11ef28fe57afa331194f71df28d Mon Sep 17 00:00:00 2001 From: Andrew Thelen Date: Tue, 12 Aug 2025 15:09:48 -0400 Subject: [PATCH 7/9] rename use_ref_coordinates to use_reference_coordinates; tweaks to lfd builder --- funtofem/mphys/mphys_meld.py | 12 ++++++------ funtofem/mphys/mphys_meld_lfd.py | 16 ++++++++-------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/funtofem/mphys/mphys_meld.py b/funtofem/mphys/mphys_meld.py index 2ac68981..c58bc4f8 100644 --- a/funtofem/mphys/mphys_meld.py +++ b/funtofem/mphys/mphys_meld.py @@ -27,7 +27,7 @@ def initialize(self): self.options.declare("check_partials") self.options.declare("bodies", recordable=False) self.options.declare( - "use_ref_coordinates", + "use_reference_coordinates", types=bool, desc="Use separate aero and struct reference coordinates for transfer scheme initialization (same variable name with '_ref' appended)", ) @@ -68,7 +68,7 @@ def setup(self): desc="structural node displacements", tags=["mphys_coupling"], ) - if self.options["use_ref_coordinates"]: + if self.options["use_reference_coordinates"]: self.add_input( X_STRUCT0 + "_ref", shape_by_conn=True, @@ -98,7 +98,7 @@ def setup(self): # self.declare_partials(U_AERO,[X_STRUCT0,X_AERO0,U_STRUCT]) def _initialize_xfer(self, inputs, body): - if self.options["use_ref_coordinates"]: + if self.options["use_reference_coordinates"]: x_s0 = np.array( inputs[X_STRUCT0 + "_ref"][body.struct_coord_indices], dtype=TransferScheme.dtype, @@ -599,7 +599,7 @@ def __init__( check_partials=False, linearized=False, body_tags=None, - use_ref_coordinates=False, + use_reference_coordinates=False, ): self.aero_builder = aero_builder self.struct_builder = struct_builder @@ -609,7 +609,7 @@ def __init__( self.under_check_partials = check_partials self.linearized = linearized self.body_tags = body_tags if body_tags is not None else [] - self.use_ref_coordinates = use_ref_coordinates + self.use_reference_coordinates = use_reference_coordinates if len(self.body_tags) > 0: # make into lists, potentially for different bodies if not hasattr(self.n, "__len__"): @@ -686,7 +686,7 @@ def get_coupling_group_subsystem(self, scenario_name=None): aero_nnodes=self.nnodes_aero, check_partials=self.under_check_partials, bodies=self.bodies, - use_ref_coordinates=self.use_ref_coordinates, + use_reference_coordinates=self.use_reference_coordinates, ) load_xfer = MeldLoadXfer( diff --git a/funtofem/mphys/mphys_meld_lfd.py b/funtofem/mphys/mphys_meld_lfd.py index bc932896..2d96342d 100644 --- a/funtofem/mphys/mphys_meld_lfd.py +++ b/funtofem/mphys/mphys_meld_lfd.py @@ -23,7 +23,7 @@ def initialize(self): self.options.declare("nnodes_aero") self.options.declare("meld") self.options.declare( - "use_ref_coordinates", + "use_reference_coordinates", types=bool, desc="Use separate aero and struct reference coordinates for transfer scheme initialization (same variable name with '_ref' appended)", ) @@ -48,7 +48,7 @@ def setup(self): self.add_input( X_AERO0, shape_by_conn=True, distributed=True, tags=["mphys_coordinates"] ) - if self.options["use_ref_coordinates"]: + if self.options["use_reference_coordinates"]: self.add_input( X_STRUCT0 + "_ref", shape_by_conn=True, @@ -78,7 +78,7 @@ def setup(self): ) def _initialize_xfer(self, inputs, meld): - if self.options["use_ref_coordinates"]: + if self.options["use_reference_coordinates"]: aero_X = np.array(inputs[X_AERO0 + "_ref"], dtype=TransferScheme.dtype) struct_X = np.array(inputs[X_STRUCT0 + "_ref"], dtype=TransferScheme.dtype) else: @@ -190,7 +190,7 @@ def __init__( n=200, beta=0.5, check_partials=False, - use_ref_coordinates=False, + use_reference_coordinates=False, ): self.nmodes = nmodes super().__init__( @@ -202,15 +202,15 @@ def __init__( check_partials, False, None, - use_ref_coordinates, + use_reference_coordinates, ) - def get_post_coupling_subsystem(self): + def get_post_coupling_subsystem(self, scenario_name=None): return ModeTransfer( nmodes=self.nmodes, nnodes_struct=self.nnodes_struct, ndof_struct=self.ndof_struct, nnodes_aero=self.nnodes_aero, - meld=self.meld, - use_ref_coordinates=self.use_ref_coordinates, + meld=self.bodies[0].meld, # TODO: implement multi-body mode transfer + use_reference_coordinates=self.use_reference_coordinates, ) From 9a3f99a090722d5b40c6616d26ce74d5ce383179 Mon Sep 17 00:00:00 2001 From: Andrew Thelen Date: Tue, 12 Aug 2025 15:11:55 -0400 Subject: [PATCH 8/9] lint format --- funtofem/mphys/mphys_meld_lfd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/funtofem/mphys/mphys_meld_lfd.py b/funtofem/mphys/mphys_meld_lfd.py index 2d96342d..602c5df8 100644 --- a/funtofem/mphys/mphys_meld_lfd.py +++ b/funtofem/mphys/mphys_meld_lfd.py @@ -211,6 +211,6 @@ def get_post_coupling_subsystem(self, scenario_name=None): nnodes_struct=self.nnodes_struct, ndof_struct=self.ndof_struct, nnodes_aero=self.nnodes_aero, - meld=self.bodies[0].meld, # TODO: implement multi-body mode transfer + meld=self.bodies[0].meld, # TODO: implement multi-body mode transfer use_reference_coordinates=self.use_reference_coordinates, ) From ef1a45b0af83aad0082462cdfd7d7bf8ceca2996 Mon Sep 17 00:00:00 2001 From: Andrew Thelen Date: Thu, 4 Jun 2026 13:09:30 -0400 Subject: [PATCH 9/9] add ase_mode option, for changing mode shapes name to mode_shapes_aero_motion, to be later combined with mode_shapes_aero_controls --- funtofem/mphys/mphys_meld_lfd.py | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/funtofem/mphys/mphys_meld_lfd.py b/funtofem/mphys/mphys_meld_lfd.py index 602c5df8..fec50df6 100644 --- a/funtofem/mphys/mphys_meld_lfd.py +++ b/funtofem/mphys/mphys_meld_lfd.py @@ -27,12 +27,22 @@ def initialize(self): types=bool, desc="Use separate aero and struct reference coordinates for transfer scheme initialization (same variable name with '_ref' appended)", ) + self.options.declare( + "ase_mode", + types=bool, + desc="Add _motion onto the end of mode_shapes_aero, so that they can later be combined with control surface modes", + ) self.first_pass = True def setup(self): # self.set_check_partial_options(wrt='*',method='cs',directional=True) + if self.options["ase_mode"]: + self.mode_shapes_aero_name = "mode_shapes_aero_motion" + else: + self.mode_shapes_aero_name = "mode_shapes_aero" + self.add_input( X_STRUCT0, shape_by_conn=True, @@ -71,7 +81,7 @@ def setup(self): aero_mode_size = (self.nnodes_aero * 3, nmodes) self.add_output( - "mode_shapes_aero", + self.mode_shapes_aero_name, shape=aero_mode_size, distributed=True, tags=["mphys_coupling"], @@ -113,7 +123,7 @@ def compute(self, inputs, outputs): meld.transferDisps(struct_mode, aero_mode) aero_modes[:, mode] = aero_mode - outputs["mode_shapes_aero"] = aero_modes.copy() + outputs[self.mode_shapes_aero_name] = aero_modes.copy() def compute_jacvec_product(self, inputs, d_inputs, d_outputs, mode): meld = self.options["meld"] @@ -131,7 +141,7 @@ def compute_jacvec_product(self, inputs, d_inputs, d_outputs, mode): u_a = np.zeros(self.nnodes_aero * 3, dtype=TransferScheme.dtype) meld.transferDisps(u_s, u_a) if mode == "fwd": - if "mode_shapes_aero" in d_outputs: + if self.mode_shapes_aero_name in d_outputs: if "mode_shapes_struct" in d_inputs: d_in = np.zeros( self.nnodes_struct * 3, dtype=TransferScheme.dtype @@ -144,13 +154,13 @@ def compute_jacvec_product(self, inputs, d_inputs, d_outputs, mode): self.nnodes_aero * 3, dtype=TransferScheme.dtype ) meld.applydDduS(d_in, prod) - d_outputs["mode_shapes_aero"][:, imode] -= np.array( + d_outputs[self.mode_shapes_aero_name][:, imode] -= np.array( prod, dtype=float ) if mode == "rev": - if "mode_shapes_aero" in d_outputs: + if self.mode_shapes_aero_name in d_outputs: du_a = np.array( - d_outputs["mode_shapes_aero"][:, imode], + d_outputs[self.mode_shapes_aero_name][:, imode], dtype=TransferScheme.dtype, ) if "mode_shapes_struct" in d_inputs: @@ -191,8 +201,10 @@ def __init__( beta=0.5, check_partials=False, use_reference_coordinates=False, + ase_mode=False, ): self.nmodes = nmodes + self.ase_mode = ase_mode super().__init__( aero_builder, struct_builder, @@ -213,4 +225,5 @@ def get_post_coupling_subsystem(self, scenario_name=None): nnodes_aero=self.nnodes_aero, meld=self.bodies[0].meld, # TODO: implement multi-body mode transfer use_reference_coordinates=self.use_reference_coordinates, + ase_mode=self.ase_mode, )