Skip to content

Commit 9627e59

Browse files
tna_envelope_sync
1 parent 3d49a29 commit 9627e59

8 files changed

Lines changed: 226 additions & 169 deletions

File tree

src/compas_tno/analysis/analysis.py

Lines changed: 93 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@
99

1010
from compas.data import Data
1111
from compas_dem.models import SurfaceModel
12-
from compas_tno.diagrams import FormDiagram
12+
13+
from compas_tna.envelope import Envelope
14+
from compas_tna.diagrams import FormDiagram
15+
1316
from compas_tno.optimisers import Optimiser
1417
from compas_tno.problems import set_up_convex_optimisation
1518
from compas_tno.problems import set_up_general_optimisation
16-
from compas_tno.shapes import Shape
1719
from compas_tno.solvers import run_optimisation_CVXPY
1820
from compas_tno.solvers import run_optimisation_ipopt
1921
from compas_tno.solvers import run_optimisation_MATLAB
@@ -38,14 +40,14 @@ class Analysis(Data):
3840
3941
"""
4042

41-
form: FormDiagram
42-
shape: Shape
43+
formdiagram: FormDiagram
44+
envelope: Envelope
4345
optimiser: Optimiser
44-
model: SurfaceModel
4546

4647
def __init__(
4748
self,
48-
model: SurfaceModel,
49+
formdiagram: FormDiagram,
50+
envelope: Envelope,
4951
optimiser: Optimiser,
5052
settings: Optional[dict] = None,
5153
name: Optional[str] = None,
@@ -55,7 +57,8 @@ def __init__(
5557
super().__init__(name=name)
5658

5759
self.settings = settings or {}
58-
self.model = model
60+
self.formdiagram = formdiagram
61+
self.envelope = envelope
5962
self.optimiser = optimiser
6063

6164
def __str__(self):
@@ -65,17 +68,18 @@ def __str__(self):
6568
@property
6669
def __data__(self) -> dict:
6770
data = {
68-
"form": self.form,
71+
"formdiagram": self.formdiagram,
72+
"envelope": self.envelope,
6973
"optimiser": self.optimiser,
70-
"shape": self.shape,
7174
"settings": self.settings,
7275
}
7376
return data
7477

7578
@classmethod
7679
def create_minthk_analysis(
7780
cls,
78-
model: SurfaceModel,
81+
formdiagram: FormDiagram,
82+
envelope: Envelope,
7983
printout: bool = False,
8084
plot: bool = False,
8185
max_iter: int = 500,
@@ -118,12 +122,13 @@ def create_minthk_analysis(
118122
print("Minimum thickness analysis created")
119123
print(optimiser)
120124

121-
return cls(model, optimiser=optimiser)
125+
return cls(formdiagram, envelope, optimiser=optimiser)
122126

123127
@classmethod
124128
def create_bestfit_analysis(
125129
cls,
126-
model: SurfaceModel,
130+
formdiagram: FormDiagram,
131+
envelope: Envelope,
127132
printout: bool = False,
128133
plot: bool = False,
129134
max_iter: int = 500,
@@ -168,12 +173,13 @@ def create_bestfit_analysis(
168173
print("Minimum thickness analysis created")
169174
print(optimiser)
170175

171-
return cls(model, optimiser=optimiser)
176+
return cls(formdiagram, envelope, optimiser=optimiser)
172177

173178
@classmethod
174179
def create_minthrust_analysis(
175180
cls,
176-
model: SurfaceModel,
181+
formdiagram: FormDiagram,
182+
envelope: Envelope,
177183
printout: bool = False,
178184
plot: bool = False,
179185
max_iter: int = 500,
@@ -214,12 +220,13 @@ def create_minthrust_analysis(
214220
print("Minimum thrust analysis created")
215221
print(optimiser)
216222

217-
return cls(model, optimiser=optimiser)
223+
return cls(formdiagram, envelope, optimiser=optimiser)
218224

219225
@classmethod
220226
def create_maxthrust_analysis(
221227
cls,
222-
model: SurfaceModel,
228+
formdiagram: FormDiagram,
229+
envelope: Envelope,
223230
printout: bool = False,
224231
plot: bool = False,
225232
max_iter: int = 500,
@@ -260,13 +267,13 @@ def create_maxthrust_analysis(
260267
print("Maximium thrust analysis created")
261268
print(optimiser)
262269

263-
return cls(model, optimiser=optimiser)
270+
return cls(formdiagram, envelope, optimiser=optimiser)
264271

265272
@classmethod
266273
def create_max_load_analysis(
267274
cls,
268-
form: FormDiagram,
269-
shape: Shape,
275+
formdiagram: FormDiagram,
276+
envelope: Envelope,
270277
printout: bool = False,
271278
plot: bool = False,
272279
horizontal: bool = False,
@@ -336,12 +343,13 @@ def create_max_load_analysis(
336343
print("Max vertical load analysis created")
337344
# print(optimiser)
338345

339-
return cls(form, optimiser=optimiser, shape=shape)
346+
return cls(formdiagram, envelope, optimiser=optimiser)
340347

341348
@classmethod
342349
def create_compl_energy_analysis(
343350
cls,
344-
model: SurfaceModel,
351+
formdiagram: FormDiagram,
352+
envelope: Envelope,
345353
printout: bool = False,
346354
solver: str = "IPOPT",
347355
plot: bool = False,
@@ -390,12 +398,13 @@ def create_compl_energy_analysis(
390398
print("Complementary energy created")
391399
print(optimiser)
392400

393-
return cls(model, optimiser=optimiser)
401+
return cls(formdiagram, envelope, optimiser=optimiser)
394402

395403
@classmethod
396404
def create_quad_compl_energy_analysis(
397405
cls,
398-
model: SurfaceModel,
406+
formdiagram: FormDiagram,
407+
envelope: Envelope,
399408
printout: bool = False,
400409
solver: str = "IPOPT",
401410
plot: bool = False,
@@ -440,13 +449,13 @@ def create_quad_compl_energy_analysis(
440449
print("Complementary energy analysis created")
441450
print(optimiser)
442451

443-
return cls(model, optimiser=optimiser)
452+
return cls(formdiagram, envelope, optimiser=optimiser)
444453

445454
@classmethod
446455
def create_lp_analysis(
447456
cls,
448-
form: FormDiagram,
449-
shape: Shape = None,
457+
formdiagram: FormDiagram,
458+
envelope: Envelope,
450459
solver: str = "CVXPY",
451460
printout: bool = False,
452461
plot: bool = False,
@@ -482,7 +491,7 @@ def create_lp_analysis(
482491
print("Load path Analysis created")
483492
print(optimiser)
484493

485-
return cls(form, optimiser=optimiser, shape=shape)
494+
return cls(formdiagram, envelope, optimiser=optimiser)
486495

487496
# =============================================================================
488497
# Methods
@@ -515,42 +524,76 @@ def clear_previous_results(self):
515524
self.optimiser.clear_optimiser()
516525

517526
def apply_selfweight(self, normalize_loads=True):
518-
"""Invoke method to apply selfweight to the nodes of the form diagram based on the shape"""
519-
self.model.apply_selfweight(normalize=normalize_loads)
527+
"""Invoke method to apply selfweight to the nodes of the form diagram based on the envelope"""
528+
self.envelope.apply_selfweight_to_formdiagram(self.formdiagram, normalize=normalize_loads)
520529

521-
def apply_selfweight_from_pattern(self, pattern, plot=False):
522-
"""Apply selfweight to the nodes considering a different Form Diagram to locate loads.
530+
# def apply_selfweight_from_pattern(self, pattern, plot=False):
531+
# """Apply selfweight to the nodes considering a different Form Diagram to locate loads.
523532

524-
Warnings
525-
--------
526-
The base pattern has to coincide with nodes from the original form diagram.
533+
# Warnings
534+
# --------
535+
# The base pattern has to coincide with nodes from the original form diagram.
527536

528-
"""
529-
self.form.apply_selfweight_from_pattern(pattern, plot=plot)
537+
# """
538+
# self.form.apply_selfweight_from_pattern(pattern, plot=plot)
539+
540+
def apply_hor_multiplier(self, multiplier=1.0, component="x"):
541+
"""Apply a multiplier on the selfweight to the nodes of the form diagram based on the envelope
542+
543+
Parameters
544+
----------
545+
multiplier : float, optional
546+
Value of the horizontal multiplier, by default ``1.0``.
547+
component : str, optional
548+
Direction to apply the loads, ``x`` or ``y``, by default ``x``.
549+
550+
Returns
551+
-------
552+
None
553+
The FormDiagram is modified in place.
530554
531-
def apply_hor_multiplier(self, multiplier, component):
532-
"""Apply a multiplier on the selfweight to the nodes of the form diagram based"""
555+
"""
556+
arg = "p" + component
533557

534-
self.form.apply_horizontal_multiplier(lambd=multiplier, direction=component)
558+
for key in self.formdiagram.vertices():
559+
pz = self.formdiagram.vertex_attribute(key, "pz")
560+
self.formdiagram.vertex_attribute(key, arg, -1 * pz * multiplier) # considers that swt (pz) is negative
535561

536562
def apply_envelope(self):
537-
"""Invoke method to apply ub and lb to the nodes based on the shape's intrados and extrados"""
563+
"""Invoke method to apply ub and lb to the nodes based on the envelope's intrados and extrados"""
564+
565+
self.envelope.apply_bounds_to_formdiagram(self.formdiagram)
566+
567+
def apply_bounds_on_q(self, qmin=-1e4, qmax=1e-8) -> None:
568+
"""Apply bounds on the magnitude of the edges'force densities.
538569
539-
self.model.apply_envelope()
570+
Parameters
571+
----------
572+
qmin : float, optional
573+
The minimum allowed force density ``qmin``, by default -1e+4
574+
qmax : float, optional
575+
The maximum allowed force density ``qmax``, by default 1e-8
540576
541-
def apply_bounds_on_q(self, qmax=0.0, qmin=-10000.0):
542-
"""Invoke method to apply bounds on the force densities of the pattern (qmax, qmin)"""
577+
Returns
578+
-------
579+
None
580+
The formdiagram is updated in place in the attributes.
543581
544-
self.form.apply_bounds_on_q(qmax=qmax, qmin=qmin)
582+
"""
583+
if isinstance(qmin, list):
584+
for i, edge in enumerate(self.formdiagram.edges_where({"_is_edge": True})):
585+
self.formdiagram.edge_attribute(edge, "qmin", qmin[i])
586+
self.formdiagram.edge_attribute(edge, "qmax", qmax[i])
587+
else:
588+
for i, edge in enumerate(self.formdiagram.edges_where({"_is_edge": True})):
589+
self.formdiagram.edge_attribute(edge, "qmin", qmin)
590+
self.formdiagram.edge_attribute(edge, "qmax", qmax)
545591

546592
def apply_target(self):
547593
"""Apply target to the nodes based on the shape's target surface"""
548-
for key in self.form.vertices():
549-
x, y, _ = self.form.vertex_coordinates(key)
550-
self.form.vertex_attribute(key, "target", value=self.shape.get_middle(x, y))
551-
552-
# Go over nodes and find node = key and apply the pointed load pz += magnitude
553594

595+
self.envelope.apply_target_heights_to_formdiagram(self.formdiagram)
596+
554597
def apply_envelope_on_xy(self, c=0.5):
555598
"""_summary_
556599
@@ -568,7 +611,7 @@ def apply_cracks(self, key, position):
568611

569612
def apply_reaction_bounds(self, assume_shape=None):
570613
"""Apply limit thk to be respected by the anchor points"""
571-
self.form.apply_bounds_reactions(self.shape, assume_shape)
614+
self.envelope.apply_reaction_bounds_to_formdiagram(self.formdiagram)
572615

573616
def set_up_optimiser(self):
574617
"""With the data from the elements of the problem compute the matrices for the optimisation"""

0 commit comments

Comments
 (0)