Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rigid coupled solver #120

Merged
merged 16 commits into from
Feb 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,372 changes: 692 additions & 680 deletions docs/source/content/example_notebooks/wind_turbine.ipynb

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions docs/source/includes/generators/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Dynamic Control Surface generators enable the user to prescribe a certain contro
./gridbox/index
./gustvelocityfield/index
./helicoidalwake/index
./modifystructure/index
./shearvelocityfield/index
./steadyvelocityfield/index
./straightwake/index
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
ChangeLumpedMass
----------------

.. autoclass:: sharpy.generators.modifystructure.ChangeLumpedMass
:members:
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
ChangedVariable
---------------

.. autoclass:: sharpy.generators.modifystructure.ChangedVariable
:members:
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
LumpedMassControl
-----------------

.. autoclass:: sharpy.generators.modifystructure.LumpedMassControl
:members:
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
ModifyStructure
---------------

.. autoclass:: sharpy.generators.modifystructure.ModifyStructure
:members:
7 changes: 7 additions & 0 deletions docs/source/includes/generators/modifystructure/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.. toctree::
:glob:

./ChangeLumpedMass
./ChangedVariable
./LumpedMassControl
./ModifyStructure
7 changes: 0 additions & 7 deletions docs/source/includes/postprocs/StabilityDerivatives.rst

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
RigidDynamicCoupledStep
-----------------------



.. autoclass:: sharpy.solvers.rigiddynamiccoupledstep.RigidDynamicCoupledStep
:members:
1 change: 1 addition & 0 deletions docs/source/includes/solvers/structural_solvers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ Structural Solvers
./structural/NonLinearDynamicPrescribedStep
./structural/NonLinearStatic
./structural/NonLinearStaticMultibody
./structural/RigidDynamicCoupledStep
./structural/RigidDynamicPrescribedStep
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
get_transformation_matrix
-------------------------

.. automodule:: sharpy.utils.algebra.get_transformation_matrix
1 change: 1 addition & 0 deletions docs/source/includes/utils/algebra/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Note:
./deuler_dt_NED
./euler2quat
./euler2rot
./get_transformation_matrix
./get_triad
./mat2quat
./multiply_matrices
Expand Down
2 changes: 1 addition & 1 deletion lib/UVLM
Submodule UVLM updated 0 files
2 changes: 1 addition & 1 deletion lib/xbeam
105 changes: 62 additions & 43 deletions sharpy/postproc/savedata.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
import h5py
import copy
import sharpy
import sharpy.utils.cout_utils as cout
from sharpy.utils.solver_interface import solver, BaseSolver
Expand Down Expand Up @@ -112,31 +113,33 @@ def __init__(self):
self.ClassesToSave = (sharpy.presharpy.presharpy.PreSharpy,)

def initialise(self, data, custom_settings=None, caller=None):

# Add these anyway - therefore if you add your own skip_attr you don't have to retype all of these
self.settings_default['skip_attr'].append(['fortran',
'airfoils',
'airfoil_db',
'settings_types',
'ct_dynamic_forces_list',
'ct_forces_list',
'ct_gamma_dot_list',
'ct_gamma_list',
'ct_gamma_star_list',
'ct_normals_list',
'ct_u_ext_list',
'ct_u_ext_star_list',
'ct_zeta_dot_list',
'ct_zeta_list',
'ct_zeta_star_list',
'dynamic_input'])
Comment on lines -115 to -132
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to confirm, these are no longer necessary because when ClassesToSave in the save_timestep() method is used these are not included?

I assume that is the case given the usual remove_cpointers but just to make sure

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I remove these lines of code because settings_default['skip_attr'] is already defined in the class attributes. These lines are just redundant.

I created the save_timestep method for clarity.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue is that if you give a list of attributes to skip as a setting, the settings_default are not used and all of those "rubbish" attributes are included.

So, actually, the original SaveData was incorrect, line 117 in the snippet above should be self.**settings**['skip_attr'].append([<all these attributes>]). That way, you can include your own values to settings['skip_attr'] and those ct_ attributes are included regardless.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. We should use "extend" instead of "append" to avoid nesting lists.
Thanks

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahhh indeed it is extend rather than append. Thanks for spotting that!

self.data = data
if custom_settings is None:
self.settings = data.settings[self.solver_id]
else:
self.settings = custom_settings

settings.to_custom_types(self.settings,
self.settings_types, self.settings_default, options=self.settings_options)

# Add these anyway - therefore if you add your own skip_attr you don't have to retype all of these
self.settings['skip_attr'].extend(['fortran',
'airfoils',
'airfoil_db',
'settings_types',
'ct_dynamic_forces_list',
'ct_forces_list',
'ct_gamma_dot_list',
'ct_gamma_list',
'ct_gamma_star_list',
'ct_normals_list',
'ct_u_ext_list',
'ct_u_ext_star_list',
'ct_zeta_dot_list',
'ct_zeta_list',
'ct_zeta_star_list',
'dynamic_input'])

self.ts_max = self.data.ts + 1

# create folder for containing files if necessary
Expand Down Expand Up @@ -196,35 +199,28 @@ def run(self, online=False):
hdfile = h5py.File(self.filename, 'a')

if (online and file_exists):
if self.settings['save_aero']:
h5utils.add_as_grp(self.data.aero.timestep_info[self.data.ts],
hdfile['data']['aero']['timestep_info'],
grpname=("%05d" % self.data.ts),
ClassesToSave=(sharpy.utils.datastructures.AeroTimeStepInfo,),
SkipAttr=self.settings['skip_attr'],
compress_float=self.settings['compress_float'])
if self.settings['save_struct']:
if self.data.structure.timestep_info[self.data.ts].in_global_AFoR:
tstep = self.data.structure.timestep_info[self.data.ts]
else:
tstep = self.data.structure.timestep_info[self.data.ts].copy()
tstep.whole_structure_to_global_AFoR(self.data.structure)

h5utils.add_as_grp(tstep,
hdfile['data']['structure']['timestep_info'],
grpname=("%05d" % self.data.ts),
ClassesToSave=(sharpy.utils.datastructures.StructTimeStepInfo,),
SkipAttr=self.settings['skip_attr'],
compress_float=self.settings['compress_float'])
self.save_timestep(self.data, self.settings, self.data.ts, hdfile)
else:
skip_attr_init = copy.deepcopy(self.settings['skip_attr'])
skip_attr_init.append('timestep_info')

h5utils.add_as_grp(self.data, hdfile, grpname='data',
ClassesToSave=self.ClassesToSave, SkipAttr=skip_attr_init,
compress_float=self.settings['compress_float'])

if self.settings['save_struct']:
h5utils.add_as_grp(list(),
hdfile['data']['structure'],
grpname='timestep_info')
if self.settings['save_aero']:
h5utils.add_as_grp(list(),
hdfile['data']['aero'],
grpname='timestep_info')

for it in range(len(self.data.structure.timestep_info)):
tstep_p = self.data.structure.timestep_info[it]
if tstep_p is not None:
if not tstep_p.in_global_AFoR:
tstep_p.whole_structure_to_global_AFoR(self.data.structure)
h5utils.add_as_grp(self.data, hdfile, grpname='data',
ClassesToSave=self.ClassesToSave, SkipAttr=self.settings['skip_attr'],
compress_float=self.settings['compress_float'])
self.save_timestep(self.data, self.settings, it, hdfile)

hdfile.close()

Expand Down Expand Up @@ -295,3 +291,26 @@ def run(self, online=False):
savemat(matfilename, savedict)

return self.data

@staticmethod
def save_timestep(data, settings, ts, hdfile):
if settings['save_aero']:
h5utils.add_as_grp(data.aero.timestep_info[ts],
hdfile['data']['aero']['timestep_info'],
grpname=("%05d" % ts),
ClassesToSave=(sharpy.utils.datastructures.AeroTimeStepInfo,),
SkipAttr=settings['skip_attr'],
compress_float=settings['compress_float'])
if settings['save_struct']:
if data.structure.timestep_info[ts].in_global_AFoR:
tstep = data.structure.timestep_info[ts]
else:
tstep = data.structure.timestep_info[data.ts].copy()
tstep.whole_structure_to_global_AFoR(data.structure)

h5utils.add_as_grp(tstep,
hdfile['data']['structure']['timestep_info'],
grpname=("%05d" % ts),
ClassesToSave=(sharpy.utils.datastructures.StructTimeStepInfo,),
SkipAttr=settings['skip_attr'],
compress_float=settings['compress_float'])
2 changes: 1 addition & 1 deletion sharpy/postproc/writevariablestime.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ def initialise(self, data, custom_settings=None, caller=None):

# Initialise velocity generator
self.caller = caller
if not self.caller is None:
if ((not self.caller is None) and (not len(self.settings['vel_field_variables']) == 0)):
if self.caller.solver_classification.lower() == 'aero':
# For aerodynamic solvers
self.velocity_generator = self.caller.velocity_generator
Expand Down
98 changes: 98 additions & 0 deletions sharpy/solvers/rigiddynamiccoupledstep.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import ctypes as ct
import numpy as np

import sharpy.structure.utils.xbeamlib as xbeamlib
from sharpy.utils.settings import str2bool
from sharpy.utils.solver_interface import solver, BaseSolver, solver_from_string
import sharpy.utils.settings as settings
import sharpy.utils.algebra as algebra
import sharpy.utils.cout_utils as cout


_BaseStructural = solver_from_string('_BaseStructural')

@solver
class RigidDynamicCoupledStep(_BaseStructural):
"""
Structural solver used for the dynamic simulation of free-flying rigid structures.

This solver provides an interface to the structural library (``xbeam``) and updates the structural parameters
for every k-th step in the FSI iteration.

This solver can be called as part of a standalone structural simulation or as the structural solver of a coupled
aeroelastic simulation.

"""
solver_id = 'RigidDynamicCoupledStep'
solver_classification = 'structural'

settings_types = _BaseStructural.settings_types.copy()
settings_default = _BaseStructural.settings_default.copy()
settings_description = _BaseStructural.settings_description.copy()

settings_types['balancing'] = 'bool'
settings_default['balancing'] = False

settings_types['relaxation_factor'] = 'float'
settings_default['relaxation_factor'] = 0.3
settings_description['relaxation factor'] = 'Relaxation factor'

settings_table = settings.SettingsTable()
__doc__ += settings_table.generate(settings_types, settings_default, settings_description)

def __init__(self):
self.data = None
self.settings = None

def initialise(self, data, custom_settings=None):
self.data = data
if custom_settings is None:
self.settings = data.settings[self.solver_id]
else:
self.settings = custom_settings
settings.to_custom_types(self.settings, self.settings_types, self.settings_default)

# load info from dyn dictionary
self.data.structure.add_unsteady_information(self.data.structure.dyn_dict, self.settings['num_steps'].value)

# generate q, dqdt and dqddt
xbeamlib.xbeam_solv_disp2state(self.data.structure, self.data.structure.timestep_info[-1])

def run(self, structural_step, previous_structural_step=None, dt=None):
if dt is None:
dt = self.settings['dt']

xbeamlib.xbeam_step_coupledrigid(self.data.structure,
self.settings,
self.data.ts,
structural_step,
dt=dt)
self.extract_resultants(structural_step)
self.data.structure.integrate_position(structural_step, dt)

return self.data

def add_step(self):
self.data.structure.next_step()

def next_step(self):
pass

def extract_resultants(self, step=None):
if step is None:
step = self.data.structure.timestep_info[-1]
applied_forces = self.data.structure.nodal_b_for_2_a_for(step.steady_applied_forces + step.unsteady_applied_forces,
step)

applied_forces_copy = applied_forces.copy()
gravity_forces_copy = step.gravity_forces.copy()
for i_node in range(self.data.structure.num_node):
applied_forces_copy[i_node, 3:6] += algebra.cross3(step.pos[i_node, :],
applied_forces_copy[i_node, 0:3])
gravity_forces_copy[i_node, 3:6] += algebra.cross3(step.pos[i_node, :],
gravity_forces_copy[i_node, 0:3])

totals = np.sum(applied_forces_copy + gravity_forces_copy, axis=0)
step.total_forces = np.sum(applied_forces_copy, axis=0)
step.total_gravity_forces = np.sum(gravity_forces_copy, axis=0)
return totals[0:3], totals[3:6]
8 changes: 0 additions & 8 deletions sharpy/structure/models/beamstructures.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,6 @@ def calculate_length(self):
# TODO implement length based on integration
self.length = np.linalg.norm(self.coordinates_def[0, :] - self.coordinates_def[1, :])

def preferent_direction(self):
index = np.argmax(np.abs(self.tangent_vector_def[0, :]))
direction = np.zeros((3,))
direction[index] = 1
return direction

def add_attributes(self, dictionary):
for key, value in dictionary.items():
setattr(self, key, value)
Expand Down Expand Up @@ -140,5 +134,3 @@ def deformed_triad(self, psi=None):
return algebra.crv2triad_vec(self.psi_def)
else:
return algebra.crv2triad_vec(psi)


Loading