def main(): # pragma: no cover p = Problem() p.model = LaunchVehicleLinearTangentODE(num_nodes=1) p.setup() p.run_model() var_map = { 'rho': r'$\rho$', 'x': r'$x$', 'y': r'$y$', 'vx': r'$v_x$', 'vy': r'$v_y$', 'm': r'$m$', 'mdot': r'$\dot{m}$', 'Isp': r'$I_{sp}$', 'thrust': r'$F_{T}$', 'ydot': r'$\dot{y}$', 'xdot': r'$\dot{x}$', 'vxdot': r'$\dot{v}_x$', 'vydot': r'$\dot{v}_y$', 'theta': r'$\theta$', 'a_ctrl': r'$a$', 'b_ctrl': r'$b$', 'time': r'$time$' } xdsm = XDSM() xdsm.from_openmdao_group(p.model, var_map=var_map) xdsm.write('ssto_linear_tangent_xdsm', build=True, cleanup=True)
def main(): p = Problem() p.model = LaunchVehicleODE(num_nodes=1) p.setup() p.run_model() var_map = { 'rho': r'$\rho$', 'x': r'$x$', 'y': r'$y$', 'vx': r'$v_x$', 'vy': r'$v_y$', 'm': r'$m$', 'mdot': r'$\dot{m}$', 'Isp': r'$I_{sp}$', 'thrust': r'$F_{T}$', 'ydot': r'$\dot{y}$', 'xdot': r'$\dot{x}$', 'vxdot': r'$\dot{v}_x$', 'vydot': r'$\dot{v}_y$', 'theta': r'$\theta$' } xdsm = XDSM() xdsm.from_openmdao_group(p.model, var_map=var_map) xdsm.write('ssto_xdsm', build=True, cleanup=True)
def test_connect(self): x = XDSM(use_sfmath=False) x.add_system("D1", FUNC, "D_1", label_width=2) x.add_system("D2", FUNC, "D_2", stack=False) try: x.connect("D1", "D2", r"\mathcal{R}(y_1)", "foobar") except ValueError as err: self.assertEquals(str(err), "label_width argument must be an integer") else: self.fail("Expected ValueError")
def test_connect(self): x = XDSM(use_sfmath=False) x.add_system('D1', 'Function', 'D_1', label_width=2) x.add_system('D2', 'Function', 'D_2', stack=False) try: x.connect('D1', 'D2', r'\mathcal{R}(y_1)', 'foobar') except ValueError as err: self.assertEquals(str(err), 'label_width argument must be an integer') else: self.fail('Expected ValueError')
def test_stacked_system(self): x = XDSM() x.add_system("test", OPT, r"\text{test}", stack=True) file_name = "stacked_test" x.write(file_name) tikz_file = file_name + ".tikz" with open(tikz_file, "r") as f: tikz = f.read() self.assertIn(r"\node [Optimization,stack]", tikz)
def test_write_outdir(self): fname = "test" for abspath in [True, False]: subdir = tempfile.mkdtemp(dir=self.tempdir) outdir = subdir if abspath else os.path.basename(subdir) x = XDSM() x.add_system("x", FUNC, "x") x.write(fname, outdir=outdir) for ext in [".tex", ".tikz", ".pdf"]: self.assertTrue( os.path.isfile(os.path.join(subdir, fname + ext))) # no files outside the subdirs self.assertFalse( any(os.path.isfile(fp) for fp in os.listdir(self.tempdir)))
def test_options(self): filename = "xdsm_test_options" spec_dir = filename + "_specs" # Change `use_sfmath` to False to use computer modern x = XDSM(use_sfmath=False) x.add_system("opt", OPT, r"\text{Optimizer}") x.add_system("solver", SOLVER, r"\text{Newton}") x.add_system("D1", FUNC, "D_1", label_width=2) x.add_system("D2", FUNC, "D_2", stack=False) x.add_system("F", FUNC, "F", faded=True) x.add_system("G", FUNC, "G", spec_name="G_spec") x.connect("opt", "D1", "x, z") x.connect("opt", "D2", "z") x.connect("opt", "F", "x, z") x.connect("solver", "D1", "y_2") x.connect("solver", "D2", "y_1") x.connect("D1", "solver", r"\mathcal{R}(y_1)") x.connect("solver", "F", "y_1, y_2") x.connect("D2", "solver", r"\mathcal{R}(y_2)") x.connect("solver", "G", "y_1, y_2") x.connect("F", "opt", "f") x.connect("G", "opt", "g") x.add_output("opt", "x^*, z^*", side="right") x.add_output("D1", "y_1^*", side="left", stack=True) x.add_output("D2", "y_2^*", side="left") x.add_output("F", "f^*", side="left") x.add_output("G", "g^*") x.write(filename) x.write_sys_specs(spec_dir) # Test if files where created self.assertTrue(os.path.isfile(filename + ".tikz")) self.assertTrue(os.path.isfile(filename + ".tex")) self.assertTrue(os.path.isdir(spec_dir)) self.assertTrue(os.path.isfile(os.path.join(spec_dir, "F.json"))) self.assertTrue(os.path.isfile(os.path.join(spec_dir, "G_spec.json")))
def test_options(self): filename = 'xdsm_test_options' spec_dir = filename + '_specs' # Change `use_sfmath` to False to use computer modern x = XDSM(use_sfmath=False) x.add_system('opt', 'Optimization', r'\text{Optimizer}') x.add_system('solver', 'MDA', r'\text{Newton}') x.add_system('D1', 'Function', 'D_1', text_width=2.0) x.add_system('D2', 'Function', 'D_2', stack=False) x.add_system('F', 'Function', 'F', faded=True) x.add_system('G', 'Function', 'G', spec_name="G_spec") x.connect('opt', 'D1', 'x, z') x.connect('opt', 'D2', 'z') x.connect('opt', 'F', 'x, z') x.connect('solver', 'D1', 'y_2') x.connect('solver', 'D2', 'y_1') x.connect('D1', 'solver', r'\mathcal{R}(y_1)') x.connect('solver', 'F', 'y_1, y_2') x.connect('D2', 'solver', r'\mathcal{R}(y_2)') x.connect('solver', 'G', 'y_1, y_2') x.connect('F', 'opt', 'f') x.connect('G', 'opt', 'g') x.add_output('opt', 'x^*, z^*', side='right') x.add_output('D1', 'y_1^*', side='left', stack=True) x.add_output('D2', 'y_2^*', side='left') x.add_output('F', 'f^*', side='left') x.add_output('G', 'g^*') x.write(filename) x.write_sys_specs(spec_dir) # Test if files where created self.assertTrue(os.path.isfile(filename + '.tikz')) self.assertTrue(os.path.isfile(filename + '.tex')) self.assertTrue(os.path.isdir(spec_dir)) self.assertTrue(os.path.isfile(os.path.join(spec_dir, 'F.json'))) self.assertTrue(os.path.isfile(os.path.join(spec_dir, 'G_spec.json')))
def test_tikz_content(self): # Check if TiKZ file was created. # Compare the content of the sample below and the newly created TiKZ file. sample_txt = r""" %%% Preamble Requirements %%% % \usepackage{geometry} % \usepackage{amsfonts} % \usepackage{amsmath} % \usepackage{amssymb} % \usepackage{tikz} % Optional packages such as sfmath set through python interface % \usepackage{sfmath} % \usetikzlibrary{arrows,chains,positioning,scopes,shapes.geometric,shapes.misc,shadows} %%% End Preamble Requirements %%% \input{"path/to/diagram_styles"} \begin{tikzpicture} \matrix[MatrixSetup]{ %Row 0 \node [DataIO] (left_output_opt) {$x^*, z^*$};& \node [Optimization] (opt) {$\text{Optimizer}$};& & \node [DataInter] (opt-D1) {$x, z$};& \node [DataInter] (opt-D2) {$z$};& \node [DataInter] (opt-F) {$x, z$};& \\ %Row 1 & & \node [MDA] (solver) {$\text{Newton}$};& \node [DataInter] (solver-D1) {$y_2$};& \node [DataInter] (solver-D2) {$y_1$};& \node [DataInter] (solver-F) {$y_1, y_2$};& \node [DataInter] (solver-G) {$y_1, y_2$};\\ %Row 2 \node [DataIO] (left_output_D1) {$y_1^*$};& & \node [DataInter] (D1-solver) {$\mathcal{R}(y_1)$};& \node [Function] (D1) {$D_1$};& & & \\ %Row 3 \node [DataIO] (left_output_D2) {$y_2^*$};& & \node [DataInter] (D2-solver) {$\mathcal{R}(y_2)$};& & \node [Function] (D2) {$D_2$};& & \\ %Row 4 \node [DataIO] (left_output_F) {$f^*$};& \node [DataInter] (F-opt) {$f$};& & & & \node [Function] (F) {$F$};& \\ %Row 5 \node [DataIO] (left_output_G) {$g^*$};& \node [DataInter] (G-opt) {$g$};& & & & & \node [Function] (G) {$G$};\\ %Row 6 & & & & & & \\ }; % XDSM process chains \begin{pgfonlayer}{data} \path % Horizontal edges (opt) edge [DataLine] (opt-D1) (opt) edge [DataLine] (opt-D2) (opt) edge [DataLine] (opt-F) (solver) edge [DataLine] (solver-D1) (solver) edge [DataLine] (solver-D2) (D1) edge [DataLine] (D1-solver) (solver) edge [DataLine] (solver-F) (D2) edge [DataLine] (D2-solver) (solver) edge [DataLine] (solver-G) (F) edge [DataLine] (F-opt) (G) edge [DataLine] (G-opt) (opt) edge [DataLine] (left_output_opt) (D1) edge [DataLine] (left_output_D1) (D2) edge [DataLine] (left_output_D2) (F) edge [DataLine] (left_output_F) (G) edge [DataLine] (left_output_G) % Vertical edges (opt-D1) edge [DataLine] (D1) (opt-D2) edge [DataLine] (D2) (opt-F) edge [DataLine] (F) (solver-D1) edge [DataLine] (D1) (solver-D2) edge [DataLine] (D2) (D1-solver) edge [DataLine] (solver) (solver-F) edge [DataLine] (F) (D2-solver) edge [DataLine] (solver) (solver-G) edge [DataLine] (G) (F-opt) edge [DataLine] (opt) (G-opt) edge [DataLine] (opt); \end{pgfonlayer} \end{tikzpicture}""" filename = "xdsm_test_tikz" x = XDSM(use_sfmath=True) x.add_system("opt", OPT, r"\text{Optimizer}") x.add_system("solver", SOLVER, r"\text{Newton}") x.add_system("D1", FUNC, "D_1") x.add_system("D2", FUNC, "D_2") x.add_system("F", FUNC, "F") x.add_system("G", FUNC, "G") x.connect("opt", "D1", "x, z") x.connect("opt", "D2", "z") x.connect("opt", "F", "x, z") x.connect("solver", "D1", "y_2") x.connect("solver", "D2", "y_1") x.connect("D1", "solver", r"\mathcal{R}(y_1)") x.connect("solver", "F", "y_1, y_2") x.connect("D2", "solver", r"\mathcal{R}(y_2)") x.connect("solver", "G", "y_1, y_2") x.connect("F", "opt", "f") x.connect("G", "opt", "g") x.add_output("opt", "x^*, z^*", side="left") x.add_output("D1", "y_1^*", side="left") x.add_output("D2", "y_2^*", side="left") x.add_output("F", "f^*", side="left") x.add_output("G", "g^*", side="left") x.write(filename) # Check if file was created tikz_file = filename + ".tikz" self.assertTrue(os.path.isfile(tikz_file)) sample_lines = sample_txt.split("\n") sample_lines = filter_lines(sample_lines) with open(tikz_file, "r") as f: new_lines = filter_lines(f.readlines()) sample_no_match = [] # Sample text new_no_match = [] # New text for new_line, sample_line in zip(new_lines, sample_lines): if new_line.startswith(r"\input{"): continue if new_line != sample_line: # else everything is okay # This can be because of the different ordering of lines or because of an error. sample_no_match.append(new_line) new_no_match.append(sample_line) # Sort both sets of suspicious lines sample_no_match.sort() new_no_match.sort() for sample_line, new_line in zip(sample_no_match, new_no_match): # Now the lines should match, if only the ordering was different self.assertEqual(new_line, sample_line) # To be sure, check the length, otherwise a missing last line could get unnoticed because of using zip self.assertEqual(len(new_lines), len(sample_lines))
from pyxdsm.XDSM import XDSM # opt = 'Optimization' solver = 'MDA' ecomp = 'Analysis' icomp = 'ImplicitAnalysis' group = 'Metamodel' func = 'Function' x = XDSM() #x.add_system('const', comp, r'\text{Constants}') x.add_system('DYMOS', opt, [r'\text{DYMOS}']) x.add_system('ambient', ecomp, [r'\text{Ambient}']) # x.add_system('USATM', comp, [r'\text{US Atm 1976}']) # x.add_system('mach_comp', comp, [r'\text{MACH}']) x.add_system('prop_comp', icomp, [r'\text{Propeller}', r'\text{(OpenBEMT)}']) x.add_system('e_comp', icomp, [r'\text{Electrical}', r'\text{(Zappy)}']) x.add_system('engine_comp', icomp, [r'\text{Turboshaft}', r'\text{(pyCycle)}']) # x.add_system('cool_comp', comp, [r'\text{Thermal}']) x.add_system('solver', solver, [r'\text{Solver}']) x.add_system('aero_comp', icomp, [r'\text{Wing Aerodynamics}', r'\text{(OpenAeroStruct)}']) x.add_system('flight_dynamics', ecomp, [r'\text{Flight Dynamics}']) # AKA prebalance x.add_system('balance', icomp, [r'\text{Balance}']) # x.add_system('drag_comp', comp, [r'\text{Aero Drag}']) x.add_system('EOM_comp', ecomp, [r'\text{State Rates}']) # x.add_system('', comp, r'\text{}')
def test_tikz_content(self): # Check if TiKZ file was created. # Compare the content of the sample below and the newly created TiKZ file. tikz_txt = r""" %%% Preamble Requirements %%% % \usepackage{geometry} % \usepackage{amsfonts} % \usepackage{amsmath} % \usepackage{amssymb} % \usepackage{tikz} % Optional packages such as sfmath set through python interface % \usepackage{sfmath} % \usetikzlibrary{arrows,chains,positioning,scopes,shapes.geometric,shapes.misc,shadows} %%% End Preamble Requirements %%% \input{"D:/Documents/GitHub/mypyXDSM/pyXDSM/pyxdsm/diagram_styles"} \begin{tikzpicture} \matrix[MatrixSetup]{ %Row 0 \node [DataIO] (left_output_opt) {$x^*, z^*$};& \node [Optimization] (opt) {$\text{Optimizer}$};& & \node [DataInter] (opt-D1) {$x, z$};& \node [DataInter] (opt-D2) {$z$};& \node [DataInter] (opt-F) {$x, z$};& \\ %Row 1 & & \node [MDA] (solver) {$\text{Newton}$};& \node [DataInter] (solver-D1) {$y_2$};& \node [DataInter] (solver-D2) {$y_1$};& \node [DataInter] (solver-F) {$y_1, y_2$};& \node [DataInter] (solver-G) {$y_1, y_2$};\\ %Row 2 \node [DataIO] (left_output_D1) {$y_1^*$};& & \node [DataInter] (D1-solver) {$\mathcal{R}(y_1)$};& \node [Function] (D1) {$D_1$};& & & \\ %Row 3 \node [DataIO] (left_output_D2) {$y_2^*$};& & \node [DataInter] (D2-solver) {$\mathcal{R}(y_2)$};& & \node [Function] (D2) {$D_2$};& & \\ %Row 4 \node [DataIO] (left_output_F) {$f^*$};& \node [DataInter] (F-opt) {$f$};& & & & \node [Function] (F) {$F$};& \\ %Row 5 \node [DataIO] (left_output_G) {$g^*$};& \node [DataInter] (G-opt) {$g$};& & & & & \node [Function] (G) {$G$};\\ %Row 6 & & & & & & \\ }; % XDSM process chains \begin{pgfonlayer}{data} \path % Horizontal edges (opt) edge [DataLine] (opt-D1) (opt) edge [DataLine] (opt-D2) (opt) edge [DataLine] (opt-F) (solver) edge [DataLine] (solver-D1) (solver) edge [DataLine] (solver-D2) (D1) edge [DataLine] (D1-solver) (solver) edge [DataLine] (solver-F) (D2) edge [DataLine] (D2-solver) (solver) edge [DataLine] (solver-G) (F) edge [DataLine] (F-opt) (G) edge [DataLine] (G-opt) (opt) edge [DataLine] (left_output_opt) (D1) edge [DataLine] (left_output_D1) (D2) edge [DataLine] (left_output_D2) (F) edge [DataLine] (left_output_F) (G) edge [DataLine] (left_output_G) % Vertical edges (opt-D1) edge [DataLine] (D1) (opt-D2) edge [DataLine] (D2) (opt-F) edge [DataLine] (F) (solver-D1) edge [DataLine] (D1) (solver-D2) edge [DataLine] (D2) (D1-solver) edge [DataLine] (solver) (solver-F) edge [DataLine] (F) (D2-solver) edge [DataLine] (solver) (solver-G) edge [DataLine] (G) (F-opt) edge [DataLine] (opt) (G-opt) edge [DataLine] (opt); \end{pgfonlayer} \end{tikzpicture}""" def filter_lines(lns): # Empty lines are excluded. # Leading and trailing whitespaces are removed # Comments are removed. return [ ln.strip() for ln in lns if ln.strip() and not ln.strip().startswith('%') ] filename = 'xdsm_test_tikz' x = XDSM(use_sfmath=True) x.add_system('opt', 'Optimization', r'\text{Optimizer}') x.add_system('solver', 'MDA', r'\text{Newton}') x.add_system('D1', 'Function', 'D_1') x.add_system('D2', 'Function', 'D_2') x.add_system('F', 'Function', 'F') x.add_system('G', 'Function', 'G') x.connect('opt', 'D1', 'x, z') x.connect('opt', 'D2', 'z') x.connect('opt', 'F', 'x, z') x.connect('solver', 'D1', 'y_2') x.connect('solver', 'D2', 'y_1') x.connect('D1', 'solver', r'\mathcal{R}(y_1)') x.connect('solver', 'F', 'y_1, y_2') x.connect('D2', 'solver', r'\mathcal{R}(y_2)') x.connect('solver', 'G', 'y_1, y_2') x.connect('F', 'opt', 'f') x.connect('G', 'opt', 'g') x.add_output('opt', 'x^*, z^*', side='left') x.add_output('D1', 'y_1^*', side='left') x.add_output('D2', 'y_2^*', side='left') x.add_output('F', 'f^*', side='left') x.add_output('G', 'g^*', side='left') x.write(filename) # Check if file was created tikz_file = filename + '.tikz' self.assertTrue(os.path.isfile(tikz_file)) tikz_lines = tikz_txt.split('\n') tikz_lines = filter_lines(tikz_lines) with open(tikz_file, "r") as f: lines = filter_lines(f.readlines()) sample_no_match = [] # Sample text new_no_match = [] # New text for line1, line2 in zip(lines, tikz_lines): if line1 != line2: # else everything is okay # This can be because of the different ordering of lines or because of an error. sample_no_match.append(line1) new_no_match.append(line2) # Sort both sets of suspicious lines sample_no_match.sort() new_no_match.sort() for line1, line2 in zip(sample_no_match, new_no_match): # Now the lines should match, if only the ordering was different self.assertEqual(line1, line2) # To be sure, check the length, otherwise a missing last line could get unnoticed because of using zip self.assertEqual(len(lines), len(tikz_lines))
from pyxdsm.XDSM import XDSM, OPT, SOLVER, FUNC # Change `use_sfmath` to False to use computer modern x = XDSM(use_sfmath=True) x.add_system("opt", OPT, r"\text{Optimizer}") x.add_system("solver", SOLVER, r"\text{Newton}") x.add_system("D1", FUNC, "D_1") x.add_system("D2", FUNC, "D_2") x.add_system("F", FUNC, "F") x.add_system("G", FUNC, "G") x.connect("opt", "D1", "x, z") x.connect("opt", "D2", "z") x.connect("opt", "F", "x, z") x.connect("solver", "D1", "y_2") x.connect("solver", "D2", "y_1") x.connect("D1", "solver", r"\mathcal{R}(y_1)") x.connect("solver", "F", "y_1, y_2") x.connect("D2", "solver", r"\mathcal{R}(y_2)") x.connect("solver", "G", "y_1, y_2") x.connect("F", "opt", "f") x.connect("G", "opt", "g") x.add_output("opt", "x^*, z^*", side="left") x.add_output("D1", "y_1^*", side="left") x.add_output("D2", "y_2^*", side="left") x.add_output("F", "f^*", side="left") x.add_output("G", "g^*", side="left") x.write("mdf")
from pyxdsm.XDSM import XDSM, OPT, SUBOPT, SOLVER, DOE, IFUNC, FUNC, GROUP, IGROUP, METAMODEL x = XDSM(use_sfmath=False) x.add_system('OPT', OPT, r"\text{Optimizer}") x.add_system('ODE', GROUP, r"\text{ODE or DAE}") x.connect('ODE', 'OPT', ["J", r"\bar{g}_0", r"\bar{g}_f", r"\bar{p}"], label_width=4) x.connect('OPT', 'ODE', ["t", r"\bar{x}", r"\bar{u}", r"\bar{d}"], label_width=4) x.write('opt_control') x = XDSM(use_sfmath=False) x.add_system('OPT_static', OPT, r"\text{Static Optimizer}") x.add_system('static', GROUP, r"\text{Static System Model}") x.add_system('OPT_dynamic', OPT, r"\text{Dynamic Optimizer}") x.add_system('dynamic', GROUP, r"\text{ODE or DAE}") x.connect('dynamic', 'OPT_dynamic', [r"J_\text{dynamic}", r"\bar{g}_0", r"\bar{g}_f", r"\bar{p}"], label_width=4) x.connect('OPT_dynamic', 'dynamic', ["t", r"\bar{x}", r"\bar{u}"], label_width=3) x.connect('static', 'OPT_static', [r"J_\text{static}", r"g_\text{static}"], label_width=3) x.connect('OPT_static', 'static', [r"\bar{d}"], label_width=3) x.connect('OPT_static', 'OPT_dynamic', [r'\text{static optimization}', r'\text{outputs}']) x.connect('OPT_dynamic', 'OPT_static', [r'\text{dynamic optimization}', r'\text{outputs}'])