engforge 0.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. engforge/__init__.py +26 -0
  2. engforge/_testing_components.py +864 -0
  3. engforge/analysis.py +257 -0
  4. engforge/attr_dynamics.py +222 -0
  5. engforge/attr_plotting.py +811 -0
  6. engforge/attr_signals.py +116 -0
  7. engforge/attr_slots.py +211 -0
  8. engforge/attr_solver.py +443 -0
  9. engforge/attributes.py +326 -0
  10. engforge/common.py +76 -0
  11. engforge/component_collections.py +276 -0
  12. engforge/components.py +55 -0
  13. engforge/configuration.py +673 -0
  14. engforge/dataframe.py +185 -0
  15. engforge/datastores/__init__.py +116 -0
  16. engforge/datastores/data.py +519 -0
  17. engforge/datastores/gdocs.py +2650 -0
  18. engforge/datastores/reporting.py +935 -0
  19. engforge/datastores/secrets.py +549 -0
  20. engforge/dynamics.py +662 -0
  21. engforge/eng/__init__.py +0 -0
  22. engforge/eng/costs.py +1459 -0
  23. engforge/eng/fluid_material.py +279 -0
  24. engforge/eng/geometry.py +1060 -0
  25. engforge/eng/pipes.py +1211 -0
  26. engforge/eng/prediction.py +366 -0
  27. engforge/eng/solid_materials.py +445 -0
  28. engforge/eng/structure.py +2228 -0
  29. engforge/eng/structure_beams.py +821 -0
  30. engforge/eng/thermodynamics.py +271 -0
  31. engforge/engforge_attributes.py +380 -0
  32. engforge/env_var.py +214 -0
  33. engforge/locations.py +18 -0
  34. engforge/logging.py +290 -0
  35. engforge/patterns.py +449 -0
  36. engforge/problem_context.py +2251 -0
  37. engforge/properties.py +501 -0
  38. engforge/reporting.py +595 -0
  39. engforge/solveable.py +964 -0
  40. engforge/solver.py +316 -0
  41. engforge/solver_utils.py +726 -0
  42. engforge/system.py +143 -0
  43. engforge/system_reference.py +299 -0
  44. engforge/tabulation.py +288 -0
  45. engforge/test/__init__.py +2 -0
  46. engforge/test/_pre_test_structures.py +221 -0
  47. engforge/test/report_testing.py +158 -0
  48. engforge/test/test_airfilter.py +91 -0
  49. engforge/test/test_analysis.py +3 -0
  50. engforge/test/test_comp_iter.py +196 -0
  51. engforge/test/test_composition.py +139 -0
  52. engforge/test/test_costs.py +338 -0
  53. engforge/test/test_dynamics.py +109 -0
  54. engforge/test/test_dynamics_spaces.py +39 -0
  55. engforge/test/test_four_bar.py +97 -0
  56. engforge/test/test_modules.py +72 -0
  57. engforge/test/test_performance.py +93 -0
  58. engforge/test/test_pipes.py +49 -0
  59. engforge/test/test_problem.py +411 -0
  60. engforge/test/test_problem_deepscoping.py +68 -0
  61. engforge/test/test_slider_crank.py +51 -0
  62. engforge/test/test_solver.py +343 -0
  63. engforge/test/test_tabulation.py +233 -0
  64. engforge/typing.py +92 -0
  65. engforge-0.3.0.dist-info/METADATA +392 -0
  66. engforge-0.3.0.dist-info/RECORD +69 -0
  67. engforge-0.3.0.dist-info/WHEEL +5 -0
  68. engforge-0.3.0.dist-info/licenses/LICENSE +7 -0
  69. engforge-0.3.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,93 @@
1
+ # TODO:
2
+ # 1. ensure total evaluation time is not in Refs
3
+ # 2. minimize call redundancy (how)
4
+ # 3. validate caching performance and safe reset of values
5
+
6
+ from engforge._testing_components import *
7
+ from engforge.logging import LoggingMixin
8
+ from cProfile import Profile
9
+ from pstats import Stats
10
+ import unittest
11
+ import time
12
+
13
+
14
+ class PerfTest(LoggingMixin):
15
+ pass
16
+
17
+
18
+ log = PerfTest()
19
+
20
+
21
+ def eval_steady_state(dxdt=0):
22
+ """test that the ss answer is equal to the result with damping"""
23
+ sm = SpringMass()
24
+ sm.run(dxdt=dxdt, combos="time")
25
+ df = sm.dataframe
26
+
27
+
28
+ def eval_transient(endtime=10, dt=0.001, run_solver=False):
29
+ """test that the ss answer is equal to the result with damping"""
30
+ sm = SpringMass()
31
+ df = sm.simulate(dt=dt, endtime=endtime, run_solver=run_solver)
32
+
33
+
34
+ class TestPerformance(unittest.TestCase):
35
+ def test_steady_state(self):
36
+ with Profile() as pr:
37
+ start = time.time()
38
+ eval_steady_state()
39
+
40
+ stats = Stats(pr)
41
+ stats.sort_stats("tottime").print_stats(10)
42
+
43
+ end = time.time()
44
+ self.assertLessEqual((end - start), 1.0)
45
+
46
+ def test_transient(self):
47
+ endtime = 10
48
+ with Profile() as pr:
49
+ start = time.time()
50
+ eval_transient(endtime=endtime, dt=0.001, run_solver=False)
51
+
52
+ stats = Stats(pr)
53
+ stats.sort_stats("tottime").print_stats(10)
54
+ end = time.time()
55
+ self.assertLessEqual((end - start), endtime)
56
+
57
+
58
+ if __name__ == "__main__":
59
+ import sys
60
+ import argparse
61
+
62
+ parser = argparse.ArgumentParser()
63
+ parser.add_argument(
64
+ "-ss",
65
+ "--steady-state",
66
+ action="store_true",
67
+ dest="steady_state",
68
+ help="run the steady state test",
69
+ )
70
+ parser.add_argument(
71
+ "-tr",
72
+ "--transient",
73
+ action="store_true",
74
+ dest="transient",
75
+ help="run the transient test",
76
+ )
77
+ parser.add_argument(
78
+ "-a", "--all", action="store_true", dest="all", help="run all tests"
79
+ )
80
+ parser.add_argument("-b", "--base", action="store_true", help="run all tests")
81
+
82
+ args = parser.parse_args()
83
+
84
+ run_all = True if not sys.argv else args.all
85
+
86
+ if not args.base:
87
+ log.info(f"running all: {run_all} | {sys.argv}")
88
+ if args.steady_state or run_all:
89
+ log.info(f"running steady state test")
90
+ eval_steady_state()
91
+ if args.transient or run_all:
92
+ log.info(f"running transient integration test")
93
+ eval_transient()
@@ -0,0 +1,49 @@
1
+ from engforge.eng.pipes import *
2
+ from engforge.eng.fluid_material import *
3
+
4
+ import unittest
5
+
6
+
7
+ class TestPipes(unittest.TestCase):
8
+ def test_pipe_analysis(self):
9
+ n1 = FlowInput(x=0, y=0, z=0, flow_in=-0.1)
10
+ n2 = PipeNode(x=10, y=0, z=0)
11
+ n3 = PipeNode(x=0, y=10, z=0)
12
+ n4 = PipeNode(x=10, y=10, z=0)
13
+ n5 = FlowInput(x=20, y=10, z=0, flow_in=0.1)
14
+
15
+ n2z = PipeNode(x=10, y=0, z=5, name="n2z")
16
+ n3z = PipeNode(x=0, y=10, z=5, name="n3z")
17
+ n4z = PipeNode(x=10, y=10, z=5, name="n4z")
18
+ n4zo = FlowInput(x=0, y=0, z=0, flow_in=-0.5)
19
+
20
+ n2za = PipeNode(x=10, y=0, z=10)
21
+ n3za = PipeNode(x=0, y=10, z=10)
22
+ n4za = PipeNode(x=10, y=10, z=10)
23
+ n2zoa = FlowInput(x=10, y=5, z=15, flow_in=0.6)
24
+
25
+ pipe1 = Pipe(v=random.random(), D=0.1 * random.random(), node_s=n1, node_e=n2)
26
+ pipe2 = Pipe(v=random.random(), D=0.1 * random.random(), node_s=n1, node_e=n3)
27
+ pipe3 = Pipe(v=random.random(), D=0.1, node_s=n2, node_e=n4)
28
+ pipe4 = Pipe(v=random.random(), D=0.1 * random.random(), node_s=n3, node_e=n4)
29
+ pipe5 = Pipe(v=random.random(), D=0.1 * random.random(), node_s=n4, node_e=n5)
30
+
31
+ pipe5 = Pipe(v=random.random(), D=0.1 * random.random(), node_s=n2z, node_e=n2)
32
+ pipe6 = Pipe(v=random.random(), D=0.1 * random.random(), node_s=n3, node_e=n3z)
33
+ pipe7 = Pipe(v=random.random(), D=0.1 * random.random(), node_s=n4, node_e=n4z)
34
+ pipe8 = Pipe(v=random.random(), D=0.1 * random.random(), node_s=n2, node_e=n4z)
35
+ pipe9 = Pipe(
36
+ v=random.random(), D=0.1 * random.random(), node_s=n4zo, node_e=n4z
37
+ )
38
+ pipe10 = Pipe(
39
+ v=random.random(), D=0.1 * random.random(), node_s=n3z, node_e=n2z
40
+ )
41
+
42
+ # pipe10 = Pipe(v=random.random(),D=0.1*random.random(),node_s=n3za,node_e=n4)
43
+ # pipe11 = Pipe(v=random.random(),D=0.1*random.random(),node_s=n2za,node_e=n2zoa)
44
+ # pipe12 = Pipe(v=random.random(),D=0.1*random.random(),node_s=n4za,node_e=n3z)
45
+ # pipe13 = Pipe(v=random.random(),D=0.1*random.random(),node_s=n3,node_e=n2za)
46
+ # pipe13 = Pipe(v=random.random(),D=0.1*random.random(),node_s=n1,node_e=n4z)
47
+
48
+ ps = PipeSystem(in_node=n1)
49
+ ps.draw()
@@ -0,0 +1,411 @@
1
+ import unittest
2
+ from engforge.problem_context import *
3
+ from engforge.system import System, forge
4
+ from engforge._testing_components import *
5
+ import random
6
+
7
+
8
+ @forge(auto_attribs=True)
9
+ class SimpleContext(System):
10
+ one: int = 1
11
+ two: int = 2
12
+
13
+ def set_rand(self):
14
+ self.one = random.random()
15
+ self.two = random.random()
16
+
17
+ def __str__(self):
18
+ return f"{self.one}_{self.two}"
19
+
20
+
21
+ chk = lambda d, k: set(d.get(k)) if k in d else set()
22
+
23
+
24
+ class TestSession(unittest.TestCase):
25
+ """Test lifecycle of a problem and IO of the context"""
26
+
27
+ def test_system_last_context(self):
28
+ sm = SpringMass(Fa=0, u=5)
29
+ sm.run(dxdt=0, combos="time")
30
+ ssid = sm.last_context.session_id
31
+ sm.run(dxdt=0, combos="time")
32
+ trid = sm.last_context.session_id
33
+ self.assertNotEqual(ssid, trid, "Session ID should change after a run")
34
+
35
+ def test_system_change_context(self):
36
+ sm = SpringMass(Fa=0, u=5)
37
+ sm.run(dxdt=0, combos="time")
38
+ ssid = sm.last_context.session_id
39
+ trsm, df = sm.simulate(dt=0.01, endtime=0.1, return_all=True)
40
+ trid = trsm.last_context.session_id
41
+ self.assertNotEqual(ssid, trid, "Session ID should change after a run")
42
+
43
+ def test_slide_crank_empty(self):
44
+ sm = SliderCrank(Tg=0)
45
+ pbx = ProblemExec(sm, {"combos": "", "slv_vars": "", "dxdt": None})
46
+ atx = pbx.ref_attrs
47
+ self.assertEqual(chk(atx, "solver.var"), set())
48
+ self.assertEqual(chk(atx, "solver.obj"), set())
49
+ self.assertEqual(chk(atx, "solver.ineq"), set())
50
+ self.assertEqual(chk(atx, "solver.eq"), set())
51
+ self.assertEqual(chk(atx, "dynamics.output"), set())
52
+ self.assertEqual(chk(atx, "dynamics.rate"), set())
53
+ self.assertEqual(chk(atx, "dynamics.state"), set())
54
+ self.assertEqual(chk(atx, "dynamics.input"), set())
55
+
56
+ cons = pbx.constraints
57
+ self.assertEqual(cons["constraints"], [])
58
+ self.assertEqual(len(cons["bounds"]), len(atx["solver.var"]))
59
+
60
+ def test_slide_crank_dflt(self):
61
+ sm = SliderCrank(Tg=0)
62
+ pbx = ProblemExec(sm, {"dxdt": None})
63
+ atx = pbx.ref_attrs
64
+ self.assertEqual(chk(atx, "solver.var"), set())
65
+ self.assertEqual(chk(atx, "solver.obj"), set())
66
+ self.assertEqual(chk(atx, "solver.ineq"), set())
67
+ self.assertEqual(chk(atx, "solver.eq"), set())
68
+ self.assertEqual(chk(atx, "dynamics.output"), set())
69
+ self.assertEqual(chk(atx, "dynamics.rate"), set())
70
+ self.assertEqual(chk(atx, "dynamics.state"), set())
71
+ self.assertEqual(chk(atx, "dynamics.input"), set())
72
+
73
+ cons = pbx.constraints
74
+ self.assertEqual(len(cons["constraints"]), 0)
75
+ self.assertEqual(len(cons["bounds"]), 0)
76
+
77
+ def test_slide_crank_dxdt_true(self):
78
+ sm = SliderCrank(Tg=0)
79
+ pbx = ProblemExec(sm, {"dxdt": True})
80
+ atx = pbx.ref_attrs
81
+ self.assertEqual(chk(atx, "solver.var"), set())
82
+ self.assertEqual(chk(atx, "solver.obj"), set())
83
+ self.assertEqual(chk(atx, "solver.ineq"), set())
84
+ self.assertEqual(chk(atx, "solver.eq"), set())
85
+ self.assertEqual(chk(atx, "dynamics.output"), set())
86
+ self.assertEqual(chk(atx, "dynamics.rate"), set(("omega", "theta")))
87
+ self.assertEqual(chk(atx, "dynamics.state"), set(("omega", "theta")))
88
+ self.assertEqual(chk(atx, "dynamics.input"), set(("Tg",)))
89
+
90
+ cons = pbx.constraints
91
+ self.assertEqual(cons["constraints"], [])
92
+ self.assertEqual(len(cons["bounds"]), len(atx["solver.var"]))
93
+
94
+ def test_slide_crank_dxdt_zero(self):
95
+ sm = SliderCrank(Tg=0)
96
+ pbx = ProblemExec(sm, {"dxdt": 0})
97
+ atx = pbx.ref_attrs
98
+ self.assertEqual(chk(atx, "solver.var"), set())
99
+ self.assertEqual(chk(atx, "solver.obj"), set())
100
+ self.assertEqual(chk(atx, "solver.ineq"), set())
101
+ self.assertEqual(chk(atx, "solver.eq"), set())
102
+ self.assertEqual(chk(atx, "dynamics.output"), set())
103
+ self.assertEqual(chk(atx, "dynamics.rate"), set(("omega", "theta")))
104
+ self.assertEqual(chk(atx, "dynamics.state"), set(("omega", "theta")))
105
+ self.assertEqual(chk(atx, "dynamics.input"), set(("Tg",)))
106
+
107
+ cons = pbx.constraints
108
+ self.assertEqual(len(cons["constraints"]), 2)
109
+ self.assertEqual(len(cons["bounds"]), 2)
110
+
111
+ def test_slide_crank_design(self):
112
+ sm = SliderCrank(Tg=0)
113
+ pbx = ProblemExec(sm, {"combos": "design,cost", "dxdt": None})
114
+ atx = pbx.ref_attrs
115
+ self.assertEqual(
116
+ chk(atx, "solver.var"),
117
+ set(("Lo", "Rc", "Ro", "x_offset", "y_offset")),
118
+ )
119
+ self.assertEqual(chk(atx, "solver.obj"), set(("cost_slv",)))
120
+ self.assertEqual(
121
+ chk(atx, "solver.ineq"),
122
+ set(("crank_pos_slv", "gear_pos_slv", "motor_pos_slv")),
123
+ )
124
+ self.assertEqual(chk(atx, "solver.eq"), set(()))
125
+ self.assertEqual(chk(atx, "dynamics.output"), set())
126
+ self.assertEqual(chk(atx, "dynamics.rate"), set())
127
+ self.assertEqual(chk(atx, "dynamics.state"), set())
128
+ self.assertEqual(chk(atx, "dynamics.input"), set())
129
+
130
+ cons = pbx.constraints
131
+ self.assertEqual(len(cons["constraints"]), 4)
132
+ self.assertEqual(len(cons["bounds"]), 5)
133
+
134
+ def test_slide_crank_design_one_match(self):
135
+ sm = SliderCrank(Tg=0)
136
+ pbx = ProblemExec(sm, {"combos": "design", "dxdt": None, "both_match": False})
137
+ atx = pbx.ref_attrs
138
+ self.assertEqual(
139
+ chk(atx, "solver.var"),
140
+ set(("Lo", "Rc", "Ro", "x_offset", "y_offset", "X_spring_center")),
141
+ )
142
+ self.assertEqual(chk(atx, "solver.obj"), set(("cost_slv", "sym_slv")))
143
+ self.assertEqual(
144
+ chk(atx, "solver.ineq"),
145
+ set(("crank_pos_slv", "gear_pos_slv", "motor_pos_slv", "size")),
146
+ )
147
+ self.assertEqual(chk(atx, "solver.eq"), set(("gear_speed_slv", "range_slv")))
148
+ self.assertEqual(chk(atx, "dynamics.output"), set())
149
+ self.assertEqual(chk(atx, "dynamics.rate"), set())
150
+ self.assertEqual(chk(atx, "dynamics.state"), set())
151
+ self.assertEqual(chk(atx, "dynamics.input"), set())
152
+
153
+ cons = pbx.constraints
154
+ self.assertEqual(len(cons["constraints"]), 7)
155
+ self.assertEqual(len(cons["bounds"]), 6)
156
+
157
+ def test_slide_crank_design_slv_design(self):
158
+ sm = SliderCrank(Tg=0)
159
+ pbx = ProblemExec(sm, {"combos": "design", "slv_vars": "*slv", "dxdt": None})
160
+ atx = pbx.ref_attrs
161
+ self.assertEqual(chk(atx, "solver.var"), set())
162
+ self.assertEqual(chk(atx, "solver.obj"), set(()))
163
+ self.assertEqual(
164
+ chk(atx, "solver.ineq"),
165
+ set(("crank_pos_slv", "gear_pos_slv", "motor_pos_slv")),
166
+ )
167
+ self.assertEqual(chk(atx, "solver.eq"), set(()))
168
+ self.assertEqual(chk(atx, "dynamics.output"), set())
169
+ self.assertEqual(chk(atx, "dynamics.rate"), set())
170
+ self.assertEqual(chk(atx, "dynamics.state"), set())
171
+ self.assertEqual(chk(atx, "dynamics.input"), set())
172
+
173
+ cons = pbx.constraints
174
+ self.assertEqual(len(cons["constraints"]), 3)
175
+ self.assertEqual(len(cons["bounds"]), 0)
176
+
177
+ def test_slide_crank_design_slv(self):
178
+ sm = SliderCrank(Tg=0)
179
+ pbx = ProblemExec(
180
+ sm,
181
+ {
182
+ "combos": "design,cost,speed_goal,range_goal",
183
+ "ign_combos": "max*",
184
+ "slv_vars": "*slv",
185
+ "dxdt": None,
186
+ },
187
+ )
188
+ atx = pbx.ref_attrs
189
+ self.assertEqual(chk(atx, "solver.var"), set())
190
+ self.assertEqual(chk(atx, "solver.obj"), set(("cost_slv",)))
191
+ self.assertEqual(
192
+ chk(atx, "solver.ineq"),
193
+ set(("crank_pos_slv", "gear_pos_slv", "motor_pos_slv")),
194
+ )
195
+ self.assertEqual(chk(atx, "solver.eq"), set(("gear_speed_slv", "range_slv")))
196
+ self.assertEqual(chk(atx, "dynamics.output"), set())
197
+ self.assertEqual(chk(atx, "dynamics.rate"), set())
198
+ self.assertEqual(chk(atx, "dynamics.state"), set())
199
+ self.assertEqual(chk(atx, "dynamics.input"), set())
200
+
201
+ cons = pbx.constraints
202
+ self.assertEqual(len(cons["constraints"]), 5)
203
+ self.assertEqual(len(cons["bounds"]), len(atx["solver.var"]))
204
+
205
+ def test_slide_crank_design_slv_one_match(self):
206
+ sm = SliderCrank(Tg=0)
207
+ pbx = ProblemExec(
208
+ sm,
209
+ {
210
+ "combos": "design",
211
+ "ign_combos": "max*",
212
+ "slv_vars": "*slv",
213
+ "dxdt": None,
214
+ "both_match": False,
215
+ },
216
+ )
217
+ atx = pbx.ref_attrs
218
+ self.assertEqual(
219
+ chk(atx, "solver.var"),
220
+ set(("Lo", "Rc", "Ro", "x_offset", "y_offset")),
221
+ )
222
+ self.assertEqual(chk(atx, "solver.obj"), set(("cost_slv", "sym_slv")))
223
+ self.assertEqual(
224
+ chk(atx, "solver.ineq"),
225
+ set(("crank_pos_slv", "gear_pos_slv", "motor_pos_slv")),
226
+ )
227
+ self.assertEqual(chk(atx, "solver.eq"), set(("gear_speed_slv", "range_slv")))
228
+ self.assertEqual(chk(atx, "dynamics.output"), set())
229
+ self.assertEqual(chk(atx, "dynamics.rate"), set())
230
+ self.assertEqual(chk(atx, "dynamics.state"), set())
231
+ self.assertEqual(chk(atx, "dynamics.input"), set())
232
+
233
+ cons = pbx.constraints
234
+ self.assertEqual(len(cons["constraints"]), 6)
235
+ self.assertEqual(len(cons["bounds"]), len(atx["solver.var"]))
236
+
237
+ def test_slide_crank_add_var(self):
238
+ sc = SliderCrank()
239
+ out = sc.run(
240
+ combos="design,speed_goal,range_goal",
241
+ slv_vars="*",
242
+ revert_last=False,
243
+ add_vars="*gear*",
244
+ both_match=False,
245
+ )
246
+ # self.assertEqual(len(out['gear_speed_slv']),0)
247
+ print(out)
248
+
249
+
250
+ class TestContextExits(unittest.TestCase):
251
+ def tearDown(self) -> None:
252
+ self.assertFalse(
253
+ hasattr(ProblemExec.class_cache, "session"), msg="not cleaned!"
254
+ )
255
+
256
+ def test_error_exit(self):
257
+ tst = SimpleContext()
258
+
259
+ class TestError(Exception):
260
+ pass
261
+
262
+ with self.assertRaises(TestError): # we should get an error
263
+ with ProblemExec(tst) as pb1:
264
+ tst.set_rand()
265
+ with ProblemExec(tst, level_name="2") as pb2:
266
+ tst.set_rand()
267
+ with ProblemExec(tst) as pb3:
268
+ tst.set_rand()
269
+ raise TestError(
270
+ "pocket-sand"
271
+ ) # TODO: INSERT KING OF THE HILL REFERENCE
272
+ self.assertFalse(hasattr(ProblemExec.class_cache, "session"))
273
+
274
+ def test_context_singularity(self):
275
+ tst = SimpleContext()
276
+
277
+ with ProblemExec(tst) as pb1:
278
+ self.assertEqual(pb1, tst.last_context)
279
+ self.assertTrue(pb1.entered)
280
+ self.assertFalse(pb1.exited)
281
+ with ProblemExec(tst, level_name="2") as pb2:
282
+ self.assertIs(pb1, pb2)
283
+ self.assertTrue(pb1.entered)
284
+ self.assertFalse(pb1.exited)
285
+ with ProblemExec(tst) as pb3:
286
+ self.assertIs(pb1, pb3)
287
+ self.assertTrue(pb3.entered)
288
+ self.assertFalse(pb3.exited)
289
+ pb3.exit_to_level("top", revert=True)
290
+ raise Exception("Wrong Level")
291
+ raise Exception("Wrong Level")
292
+ raise Exception("Wrong Level")
293
+ self.assertEqual(pb1, tst.last_context)
294
+ self.assertTrue(pb1.entered)
295
+ self.assertTrue(pb1.exited)
296
+
297
+ def test_exit_top(self):
298
+ tst = SimpleContext()
299
+
300
+ with ProblemExec(tst) as pb1:
301
+ tst.set_rand()
302
+ with ProblemExec(tst, level_name="2") as pb2:
303
+ tst.set_rand()
304
+ with ProblemExec(tst) as pb3:
305
+ tst.set_rand()
306
+ pb3.exit_to_level("top", revert=True)
307
+ raise Exception("Wrong Level")
308
+ raise Exception("Wrong Level")
309
+ raise Exception("Wrong Level")
310
+ self.assertEqual(tst.one, 1)
311
+ self.assertEqual(tst.two, 2)
312
+
313
+ def test_exit_top_with_state(self):
314
+ tst = SimpleContext()
315
+
316
+ with ProblemExec(tst, level_name="super") as pb1:
317
+ tst.set_rand()
318
+ with ProblemExec(tst, level_name="2") as pb2:
319
+ tst.set_rand()
320
+ with ProblemExec(tst) as pb3:
321
+ tst.set_rand()
322
+ final_one = tst.one
323
+ final_two = tst.two
324
+ pb3.exit_to_level("top", revert=False)
325
+ raise Exception("Wrong Level")
326
+ raise Exception("Wrong Level")
327
+ raise Exception("Wrong Level")
328
+ self.assertEqual(tst.one, final_one)
329
+ self.assertEqual(tst.two, final_two)
330
+
331
+ def test_exit_2_with_state(self):
332
+ tst = SimpleContext()
333
+
334
+ with ProblemExec(tst) as pb1:
335
+ tst.set_rand()
336
+ with ProblemExec(tst, level_name="2") as pb2:
337
+ tst.set_rand()
338
+ with ProblemExec(tst) as pb3:
339
+ tst.set_rand()
340
+ final_one = tst.one
341
+ final_two = tst.two
342
+ pb3.exit_to_level("2", revert=False)
343
+ raise Exception("Wrong Level")
344
+ self.assertEqual(tst.one, final_one)
345
+ self.assertEqual(tst.two, final_two)
346
+ self.assertEqual(tst.one, 1)
347
+ self.assertEqual(tst.two, 2)
348
+
349
+ def test_exit_2_wo_state(self):
350
+ tst = SimpleContext()
351
+ with ProblemExec(tst) as pb1:
352
+ tst.set_rand()
353
+ final_one = tst.one
354
+ final_two = tst.two
355
+ with ProblemExec(tst, level_name="2") as pb2:
356
+ tst.set_rand()
357
+ with ProblemExec(tst) as pb3:
358
+ tst.set_rand()
359
+ pb3.exit_to_level("2", revert=True)
360
+ raise Exception("Wrong Level")
361
+ self.assertEqual(tst.one, final_one)
362
+ self.assertEqual(tst.two, final_two)
363
+ self.assertEqual(tst.one, 1)
364
+ self.assertEqual(tst.two, 2)
365
+
366
+ def test_exit_with_state(self):
367
+ tst = SimpleContext()
368
+
369
+ with ProblemExec(tst) as pb1:
370
+ tst.set_rand()
371
+ mid_one = tst.one
372
+ mid_two = tst.two
373
+ with ProblemExec(tst, level_name="2") as pb2:
374
+ tst.set_rand()
375
+ final_one = tst.one
376
+ final_two = tst.two
377
+ with ProblemExec(tst) as pb3:
378
+ tst.set_rand()
379
+ final_one = tst.one
380
+ final_two = tst.two
381
+ pb3.exit_with_state()
382
+ raise Exception("Wrong Level")
383
+ self.assertEqual(tst.one, final_one)
384
+ self.assertEqual(tst.two, final_two)
385
+ self.assertEqual(tst.one, mid_one)
386
+ self.assertEqual(tst.two, mid_two)
387
+ self.assertEqual(tst.one, 1)
388
+ self.assertEqual(tst.two, 2)
389
+
390
+ def test_exit_and_revert(self):
391
+ tst = SimpleContext()
392
+
393
+ with ProblemExec(tst) as pb1:
394
+ tst.set_rand()
395
+ mid_one = tst.one
396
+ mid_two = tst.two
397
+ with ProblemExec(tst, level_name="2") as pb2:
398
+ tst.set_rand()
399
+ final_one = tst.one
400
+ final_two = tst.two
401
+ with ProblemExec(tst) as pb3:
402
+ tst.set_rand()
403
+
404
+ pb3.exit_and_revert()
405
+ raise Exception("Wrong Level")
406
+ self.assertEqual(tst.one, final_one)
407
+ self.assertEqual(tst.two, final_two)
408
+ self.assertEqual(tst.one, mid_one)
409
+ self.assertEqual(tst.two, mid_two)
410
+ self.assertEqual(tst.one, 1)
411
+ self.assertEqual(tst.two, 2)
@@ -0,0 +1,68 @@
1
+ from engforge import *
2
+
3
+ import unittest
4
+ import attrs
5
+ import random
6
+
7
+
8
+ def test_obj(sys, prob):
9
+ # print('obj',sys, prob)
10
+ comp = sys
11
+ assert comp is not prob.system, f"{comp} is problems system, in sub comp"
12
+ return comp.val - comp.comp_val
13
+
14
+
15
+ def test_con(sys, prob):
16
+ # print('con',sys, prob)
17
+ comp = sys
18
+ assert comp is not prob.system, f"{comp} is problems system, in sub comp"
19
+ return -1
20
+
21
+
22
+ def test_zero(sys, prob):
23
+ # print('zero',sys, prob)
24
+ comp = sys
25
+ assert comp is not prob.system, f"{comp} is problems system, in sub comp"
26
+ return 0
27
+
28
+
29
+ @forge
30
+ class TestComp(Component):
31
+ val = attrs.field(factory=random.random, type=float)
32
+ val_var = Solver.declare_var("val")
33
+
34
+ comp_val = attrs.field(default=0, type=float)
35
+ slv_var = Solver.declare_var("comp_val")
36
+ slv_var.add_var_constraint(1.0, kind="max")
37
+ slv_var.add_var_constraint(test_con, kind="min")
38
+
39
+ var_obj = Solver.objective(test_obj)
40
+ var_ineq = Solver.con_ineq(test_zero)
41
+ var_2ineq = Solver.con_ineq(test_zero, test_zero)
42
+ var_eq = Solver.con_eq(test_zero)
43
+ var_2eq = Solver.con_eq(test_zero, test_zero)
44
+
45
+
46
+ @forge
47
+ class DeepComp(TestComp):
48
+ comp = Slot.define(TestComp, default_ok=False, none_ok=True)
49
+
50
+
51
+ @forge
52
+ class DeepSys(System):
53
+ comp = Slot.define(DeepComp)
54
+
55
+
56
+ class TestDeep(unittest.TestCase):
57
+ def test_one_deep(self):
58
+ comp = DeepComp(comp=None)
59
+ sys = DeepSys(comp=comp)
60
+
61
+ sys.run(combos="default", slv_vars="*")
62
+
63
+
64
+ if __name__ == "__main__":
65
+ comp = DeepComp(comp=None)
66
+ sys = DeepSys(comp=comp)
67
+ # sys.change_all_log_lvl(1)
68
+ sys.run(combos="default", slv_vars="*")
@@ -0,0 +1,51 @@
1
+ import unittest
2
+ import numpy as np
3
+
4
+ from engforge._testing_components import *
5
+
6
+
7
+ class TestSliderCrank(unittest.TestCase):
8
+ def test_optimization(self):
9
+ sc = SliderCrank()
10
+
11
+ out = sc.run(combos="design", slv_vars="*")
12
+
13
+ def test_design_multiobj(self):
14
+ sc = SliderCrank()
15
+
16
+ out = sc.run(
17
+ combos="design,*goal,*sym",
18
+ slv_vars="*",
19
+ k_spring=10,
20
+ revert_last=False,
21
+ revert_every=False,
22
+ )
23
+
24
+ out = out["output"][0]
25
+ Yobj = set(out["Yobj"])
26
+ self.assertEqual(set(("sym_slv",)), Yobj)
27
+
28
+ self.assertAlmostEqual(sc.dx_goal, 0.0, places=3)
29
+ self.assertAlmostEqual(sc.ds_goal, 0.0, places=3)
30
+
31
+
32
+ # BUG:
33
+ # ======================================================================
34
+ # FAIL: test_design_objs (test_slider_crank.TestSliderCrank)
35
+ # ----------------------------------------------------------------------
36
+ # Traceback (most recent call last):
37
+ # File "/mnt/c/Users/Sup/Ottermatics Dropbox/Ottermatics/engforge/engforge/test/test_slider_crank.py", line 34, in test_design_objs
38
+ # self.assertEqual(set(('sym_slv',)),Yobj)
39
+ # AssertionError: Items in the second set but not the first:
40
+ # 'cost_slv'
41
+ # def test_design_objs(self):
42
+ # sc = SliderCrank()
43
+ #
44
+ # out = sc.run(combos='design,*goal,*sym,*cost',slv_vars='*',k_spring=10,revert_last=False,revert_every=False)
45
+ #
46
+ # out = out['output'][0]
47
+ # Yobj = set(out['Yobj'])
48
+ # self.assertEqual(set(('sym_slv',)),Yobj)
49
+ #
50
+ # self.assertAlmostEqual(sc.dx_goal,0.0,places=3)
51
+ # self.assertAlmostEqual(sc.ds_goal,0.0,places=3)