-
Notifications
You must be signed in to change notification settings - Fork 25
/
Copy pathfake_aerodynamics.py
110 lines (82 loc) · 3.5 KB
/
fake_aerodynamics.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
from funtofem.solver_interface import *
from funtofem import TransferScheme
import numpy as np
class FakeAerodynamics(SolverInterface):
def __init__(self, comm, model, flow_dt=1.0):
self.c = -100.0
# Create fake aero_mesh, semi-ellipse centered at (0.5, 0.0)
model.bodies[0].aero_nnodes = 101
model.bodies[0].aero_X = np.zeros(
3 * model.bodies[0].aero_nnodes, dtype=TransferScheme.dtype
)
a = 0.5
b = 0.1
theta = np.linspace(0.0, np.pi, model.bodies[0].aero_nnodes)
x = 0.5 - a * np.cos(theta)
y = np.zeros(model.bodies[0].aero_nnodes)
z = 0.0 + b * np.sin(theta)
model.bodies[0].aero_X[0::3] = x[:]
model.bodies[0].aero_X[1::3] = y[:]
model.bodies[0].aero_X[2::3] = z[:]
# Unsteady scenarios
self.force_hist = {}
for scenario in model.scenarios:
self.force_hist[scenario.id] = {}
self.psi_A = None
self.fixed_step = 2
self.fixed_step_psi_A = None
return
def initialize(self, scenario, bodies, first_pass=False):
self.sum_states = 0.0
return 0
def get_functions(self, scenario, bodies):
for function in scenario.functions:
if (
function.analysis_type == "aerodynamic"
and "displacement" in function.name
):
function.value = self.sum_states
def iterate(self, scenario, bodies, step):
# qval = scenario.variables['aerodynamic'][6].value
# Get the aerodynamic node displacements
Ua = bodies[0].aero_disps
# Set the aerodynamic loads as a function of the displacements
bodies[0].aero_loads = (
-self.c * Ua
) # + qval*np.ones(Ua.shape, dtype=TransferScheme.dtype)
# Add aerodynamic displacements to function
if step == self.fixed_step:
self.sum_states += np.sum(Ua)
# Save this steps forces for the adjoint
self.force_hist[scenario.id][step] = {}
self.force_hist[scenario.id][step][bodies[0].id] = bodies[0].aero_loads.copy()
return 0
def set_states(self, scenario, bodies, step):
bodies[0].aero_loads = self.force_hist[scenario.id][step][bodies[0].id]
def intialize_adjoint(self, scenario, bodies):
pass
return 0
def iterate_adjoint(self, scenario, bodies, step):
for body in bodies:
self.psi_A = -body.dLdfa.copy()
body.dGdua[:, 0] = self.c * self.psi_A.flatten()
if step == self.fixed_step:
self.fixed_step_psi_A = self.psi_A.copy()
for ifunc, func in enumerate(scenario.functions):
if (
func.analysis_type == "aerodynamic"
and "displacement" in func.name
):
body.dGdua[:, ifunc] += 1.0
return 0
def get_function_gradients(self, scenario, bodies, offset):
for func, function in enumerate(scenario.functions):
for body in bodies:
for vartype in scenario.variables:
if vartype == "aerodynamic":
for i, var in enumerate(scenario.variables[vartype]):
if var.active and "force" in var.name:
scenario.derivatives[vartype][offset + func][i] = (
-np.sum(self.fixed_step_psi_A)
)
return 0