From 4de277b044300b802803a152283df6ed8e74bfec Mon Sep 17 00:00:00 2001 From: Justin Gray Date: Tue, 31 Mar 2020 21:55:20 -0400 Subject: [PATCH 1/8] added error check in connect statement --- pyxdsm/XDSM.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyxdsm/XDSM.py b/pyxdsm/XDSM.py index f94a23f..06d15a5 100644 --- a/pyxdsm/XDSM.py +++ b/pyxdsm/XDSM.py @@ -131,6 +131,9 @@ def add_output(self, name, label, label_width=4, style='DataIO', stack=False, si def connect(self, src, target, label, label_width=4, style='DataInter', stack=False, faded=False): if src == target: raise ValueError('Can not connect component to itself') + if not isinstance(label_width, int): + raise ValueError('label_width argument must be an integer') + self.connections.append(Connection(src, target, label, label_width, style, stack, faded)) def add_process(self, systems, arrow=True): From 879cf9ba6ceacc4ea99e8b7dd33e2e7dd173b30c Mon Sep 17 00:00:00 2001 From: Justin Gray Date: Wed, 1 Apr 2020 14:36:28 -0400 Subject: [PATCH 2/8] better error checking and a small fix for the spec stuff --- examples/kitchen_sink.pdf | Bin 47723 -> 47763 bytes examples/mat_eqn_example.pdf | Bin 20147 -> 19394 bytes examples/mdf.pdf | Bin 51059 -> 44006 bytes pyxdsm/XDSM.py | 6 ++++-- pyxdsm/tests/test_xdsm.py | 1 + 5 files changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/kitchen_sink.pdf b/examples/kitchen_sink.pdf index 5f151730083bb2216ce76d0855477dd6f336345f..8a47f0ffcf2755af060135d13c73c2b89f308009 100644 GIT binary patch delta 5245 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 Dm526! delta 5178 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 diff --git a/examples/mat_eqn_example.pdf b/examples/mat_eqn_example.pdf index 22ecbf9b5ad01f13a7a1cd3f806914758a4ea5fc..f5da5b61dca5e5db1dfa5e7ebb888cae3efe721a 100644 GIT binary patch delta 1088 zcmdlym+{ba#to|MlcRNcH=pL1sKRKv*+I`#TE#-aKp{UVi_6A_OFy6}KczG|wMapu zASEp%HA2@=&%{8_&~ox0ZxtgW0|R4YLm*{rXsT;qqHbWIuF0kEo1fy6Sdyxs;bLWE zfTm<}kdJ{M#3UVsu+*aB%=|nBV?9F?LsLs5GgDn7Ju{dM3K~G`6nrwvQWcC03@tPj zvI`PRGKy0Z70RIc%=C=)3^XT4dCMyMCuIefAPhX6_+Sj7;)+Qq~@iU zWGI*#TPjTc%b`&}HTZVlWdniQ@8M^ZIks*SwiaI*m3e!T-W%7@-8vqD@^`Mxc6()} zSQ!5F{Y+0WkJCyI6sJ9}dM1-@!Vw_Au5fVjkB5>C{PWZsePo+m;su&Q9&pPWtokVB zq@gV4xWr}x(`!?YGlEJfiv=HlzpuqzlUH>5$C5kNyUTf5IJPF#)F;mV6p+5n@y@lv zZ1Yyh>Fyq^R!sgp&iX9&UF{dU5+_To=4_dyueZWJ;c{%GzV_ru88K#-XLHtmKe52{ zzWm*smpz+3dSrUkE!cb94ov1ao<6z=ExEYzwAHt(v@B|HHmlCtaESawlJP zeR^t_^pA5kiBBGXy?Qw3V_wnj2~2;jCoisuJ+wnKZvhLBjqVH9B#x~P5A|mEv~VY# znKR?nDY2hoXHTTh3D7W`AoAzInRO@hzW+SOv@PE1_m_s$p8Cp_f%}e#MF&r|%HL7{ zFniud-tB)r=9;?%C9M2Xt^Xz5YqP(3`RBf%A6BaO-)kK8a$fPMK5fbW10KI?-4>lc zQD-~jE~ofkEAcm_5xcLcsGl-2>&^YY=Ciw1qTlVy|6Y3rn)fv*y4^B=c67p_!|u7@7n12Z5BQ7tConZqx>H8);d-O9*t gB8V*tGZczT5{pVIih%w$v@|d`<5E?1^>^a}0RLgEx&QzG delta 1928 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 I4_aaV0BOf|jsO4v delta 9227 zcmeHN&2Jn@6;~2K%RmGY9|wZ8rIl9eXyxv%ul_)mCEMf4MjI#5OtkAT@}VfVQ*6WzJe5@DZ z%Q@O{z;u2d2)I;|fb=PWKPVNQwbfG~Zf=tQiCF+PM3r8Hm-2T&GRpuZvu(=^_-^Ot zV>BaS5=@Y?8bnOWG`4Mp#=Ft&cR z1hxhpmVt{~%k0ggBSv&28Xd_SK?lL8;zSQn`Rmw$;q{A-9Y0zSJ7{o8?tOBH0zNWz zd--H3CfszQMz@zC-{>Y83YmjbNAyUcFFtDFz`a59}`cDoV7g~YeZd_qHw z3Ct)jFWc`gaY)jWrih@s)3=Sda(^vk*ZMQ!e$9->}+Swb&3#Y z8fJRj8r3X9?AENx3=4Q!R*Uer3^K~K3YzaG6$tZW5U{8!MPUBw3Z$5vI|ax)P@T*w z5En5PFbU=u_Pe_;6+^|YS)bklZWJP{f=ktKFfd;@HmX-=)9i*^A2-V2dr9$n`?yiM z>UXOXN1YqthI&i}EW9CZ{2Fjp;f685&0WT^IJx}eH|~EOXwbVC+QvLadyLGkTe*>iRk zt++>-WXUQN;`yY0=&q-{RgsIEG+f$VSZ2`i$?h!Z@9uGl!0p65E2at8s32-1h)Wc_Iem&phS=GXd zs=DXlI1(-i(xS*FW4Hv;uW+~Us8^&#rY{`2q~&)&IFk$^%5%JifLR^N30zl{ZAo~^ ztwUjquyjE=;y50?pdG5v6m3@gi?t_QRKyh=_ltLW|}tk zE&K~L$6SY*QZk{5CrY*=Vjd&r8HS-3k=m1^C=tUkGKugR;#@N(3gSwbl0zb(S4lyE zQ5;EPhD1E{CXM2MxmJzGxD7l+p~@9>JJfU~^h^2V!UMl4 z3sYg-6fqD>kI(29lKq<+dx5Rhn>4m#Uu$cHhJRDWUSMl`Y!vM3$KU(uJ8I^}E#E{# z3^na+I+%>kihN>1&(ri2?xcU-+23mKzQ42A>(Kx@PSW9&2s2_^hsE`fl65FWNs@qT z$OK~I)^va|F-&0KPI~r1HX0t6uds^Jo$C~P9~bG#Xs|UNo@4~r_loTFBND|ef4`gr zs0AL!=>+dq*ZimcGk=huo~C~0kNi`A?C1WOe}*ymBs(fhYl6%96Tk33^*?`TWbKS# z1)&4yedlIYh$~M2@}PEUzse-f_uB356KxU@bfHD0u?P)9xLFSAN|V6#KiKQPm?Vyt znj{}*e(`Bu(^Dq`SIzM1t-T+-UAui=rRM(D2ha9iXf+=%+xjH3ibl~j_Fe(R7Av|= znce*uaIj?e+kVG?9H^GA6Bn6gxh!*z-jD`ASwSH@GffC#uad?!jnMe3*~a}EIs+u&ed$Iu zU9TaHvA!cs3|nKRQ3T(tag5+IC((8D&1}=~k-9A46b;KL@N_E+fp#g0u5xN-!Dv;N z1P>%raCrDKSr9<(ha>zzsZTCl_gkXG99EyYlR_5Fhj13zMke!T5$R@p_)vLxKFB6y zZEy79i)^2q9Uj3y>(qlY4UI1U`TI4GQAR~1#rpw$F9_ZPXWYvV+juxxYyXS|3_qF9 zhFm`SL!b<^b;FD>FY!V~DOoGoK78o-@5LlLYC%mdT5#d4f0U6>N;tF}k&+fm34Vn? zGM>?*1+)ZdP~$rT;d40vuRb|o6yivO7I6ScgO(sp>NF}O;I2UnT>)`@_%Rv-DDXFv zn(+wSv`zy7VNW!z(imt~JC|k^acP!cMPn)n08{lvI1TI~l?hSA=E6Lb^K)YaO`RXi zofA+9vo4;oszpS&aA9leN@_{x7X}b4SQxk)VXC(I7nzbXPJZr zhM$^g7bH?x(AY(2%;rEyV<}t{qJfzV;daBA+RkM%PMRLU!TL2zqy4!E<|GstCK?O{ z6?j#FzuA_=63!6~8Yt2fMnK8sShbj>P}ome8w&r2&FJ$CgNonH^MdF=33==B_$Y_F z1rw?tw@H6vH|X%KL_|AuTZ%0ji*~fj!%oC_XNzvN#U@!jMBi{si*!=xU?#qk#84x= K`|j?uPU}A_;w-`d diff --git a/pyxdsm/XDSM.py b/pyxdsm/XDSM.py index 5f2c34d..4120c9e 100644 --- a/pyxdsm/XDSM.py +++ b/pyxdsm/XDSM.py @@ -89,7 +89,8 @@ def _label_to_spec(label, spec): if isinstance(label, str): label = [label,] for var in label: - spec.add(var) + if var: + spec.add(var) System = namedtuple('System', 'node_name style label stack faded label_width spec_name') @@ -263,7 +264,8 @@ def connect(self, src, target, label, label_width=None, style='DataInter', stack """ if src == target: raise ValueError('Can not connect component to itself') - if not isinstance(label_width, int): + + if (not isinstance(label_width, int)) and (not label_width is None): raise ValueError('label_width argument must be an integer') self.connections.append(Connection(src, target, label, label_width, style, stack, faded)) diff --git a/pyxdsm/tests/test_xdsm.py b/pyxdsm/tests/test_xdsm.py index 82b3bc8..b9d382f 100644 --- a/pyxdsm/tests/test_xdsm.py +++ b/pyxdsm/tests/test_xdsm.py @@ -31,6 +31,7 @@ def test_examples(self): Unlike the other tests, this one requires LaTeX to be available. ''' os.chdir(os.path.join(os.path.dirname(os.path.abspath(__file__)), '../examples')) + filenames = ['kitchen_sink', 'mdf'] for f in filenames: os.system('python {}.py'.format(f)) From 29b5abe6e3b6f486247b2c0fcbeba24b0a5c83aa Mon Sep 17 00:00:00 2001 From: Justin Gray Date: Wed, 1 Apr 2020 14:42:53 -0400 Subject: [PATCH 3/8] added test --- examples/kitchen_sink.pdf | Bin 47763 -> 47763 bytes examples/mat_eqn_example.pdf | Bin 19394 -> 19394 bytes examples/mdf.pdf | Bin 44006 -> 44006 bytes pyxdsm/tests/test_xdsm.py | 13 +++++++++++++ 4 files changed, 13 insertions(+) diff --git a/examples/kitchen_sink.pdf b/examples/kitchen_sink.pdf index 8a47f0ffcf2755af060135d13c73c2b89f308009..c54e59a14aa2f5005f06910eeae807c8be0e5234 100644 GIT binary patch delta 130 zcmbRIm1*)6jQ88k(3G8XM~xn5Y{VsB3cR`{t*(B$lKqXt-Dz85kKDz?E!1 zv#E#8$<@Wh)X~7y#K^?b*vZh?z}48<+{DGw$=t}o(Z$%=PQk{JfRf3xcK!qaQ1>H` delta 130 zcmbRIm1*)!o$=6g#tkm+93}>ah9)M4#*=;ArQw{-`R@75&aM__M#h##E-t19CYGkgMwSMa ZMnJ;U%*Djg&BD#lPQiwdlF5qR3jy$O8mj;R delta 108 zcmX>!o$=6g#tkm+9LC0mMn(q4hLe5VrQw{-`R@75&W46grfw$YW=2M?W{w6%28PZq Z25x4?h9*GuPC!vR1sg(2CM$X`1OV!b8g&2w diff --git a/examples/mdf.pdf b/examples/mdf.pdf index 149cf8fa7f901cd9bdda1dd7a187df0e7575e1f9..fccfa26a0412d6804b47e010bb9e75ef763d79e1 100644 GIT binary patch delta 108 zcmaEMo$1+irVSEHI7|!-4NXi8jVCKCk%n_NJ1@y*b9OW`H8C?cvUD*uG bH8gg0bTcq?u{3otG`CZ*A*5vT$5meedv+bV diff --git a/pyxdsm/tests/test_xdsm.py b/pyxdsm/tests/test_xdsm.py index b9d382f..b723705 100644 --- a/pyxdsm/tests/test_xdsm.py +++ b/pyxdsm/tests/test_xdsm.py @@ -46,6 +46,19 @@ def test_examples(self): # change back to previous directory os.chdir(self.tempdir) + + 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_options(self): filename = 'xdsm_test_options' From 251090e8d6672d05f36ffa67a34024e921c43cd4 Mon Sep 17 00:00:00 2001 From: Justin Gray Date: Wed, 1 Apr 2020 14:43:42 -0400 Subject: [PATCH 4/8] how did I do that? --- examples/mat_eqn_example.pdf | Bin 19394 -> 19394 bytes examples/mdf.pdf | Bin 44006 -> 44006 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/examples/mat_eqn_example.pdf b/examples/mat_eqn_example.pdf index 97af225af02b1d6d37249353223229ab54e74248..e2bd28e8fe3f738274e43593772e537e6b737f68 100644 GIT binary patch delta 97 zcmX>!o$=6g#tmNX%*IA0lYQM4K=kGU_k3n2V^a$!Q!{g80}BIFb3<1%BU58DQ)5#z W7c(P6Q!`gP1shiaN+v6MF9ZPZn;1X< delta 97 zcmX>!o$=6g#tmNX%!bCMlYQM4K=kGU_k3n23o|2QOCuK-Qv(xAQ)44b14|a6q8xqz delta 98 zcmaEMo$1+irVVmSm<^3hCMzyc0MVOWmSnLxI~tjqn3)?{x|kZ8yE!`=nmZetnVFj# Wo4Xj8I-6KH+bP%(QZo7Ds;>Z Date: Wed, 1 Apr 2020 17:42:06 -0400 Subject: [PATCH 5/8] added better doc string --- pyxdsm/XDSM.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/pyxdsm/XDSM.py b/pyxdsm/XDSM.py index 4120c9e..a80e6a1 100644 --- a/pyxdsm/XDSM.py +++ b/pyxdsm/XDSM.py @@ -548,7 +548,18 @@ def write(self, file_name, build=True, cleanup=True, quiet=False): def write_sys_specs(self, folder_name): """ - Write i/o spec files for components to specified folder + Write I/O spec json files for systems to specified folder + + An I/O spec of a system is the collection of all variables going into and out of it. + That includes any variables being passed between systems, as well as all inputs and outputs. + This information is useful for comparing implementations (such as components and groups in OpenMDAO) + to the XDSM diagrams. + + The json spec files can be used to write testing utilities that compare the inputs/outputs of an implementation + to the XDSM, and thus allow you to verify that your codes match the XDSM diagram precisely. + This technique is especially useful when large engineering teams are collaborating on + model development. It allows them to use the XDSM as a shared contract between team members + so everyone can be sure that their codes will sync up. Parameters ---------- From fc43621983b861189b247f1d967ee181a8b36631 Mon Sep 17 00:00:00 2001 From: Justin Gray Date: Wed, 27 May 2020 20:23:56 -0400 Subject: [PATCH 6/8] fixed bug in stacked systems --- pyxdsm/XDSM.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyxdsm/XDSM.py b/pyxdsm/XDSM.py index a80e6a1..b771e58 100644 --- a/pyxdsm/XDSM.py +++ b/pyxdsm/XDSM.py @@ -325,7 +325,7 @@ def _build_node_grid(self): style += ',faded' label = _parse_label(comp.label, comp.label_width) - node = node_str.format(style=comp.style, node_name=comp.node_name, node_label=label) + node = node_str.format(style=style, node_name=comp.node_name, node_label=label) grid[i_row, j_col] = node row_idx_map[comp.node_name] = i_row From 9e643827efd49eb9286e3f3de9ef0cda1d8c0d00 Mon Sep 17 00:00:00 2001 From: Justin Gray Date: Wed, 27 May 2020 20:35:48 -0400 Subject: [PATCH 7/8] added test --- pyxdsm/tests/test_xdsm.py | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/pyxdsm/tests/test_xdsm.py b/pyxdsm/tests/test_xdsm.py index b723705..72ee24f 100644 --- a/pyxdsm/tests/test_xdsm.py +++ b/pyxdsm/tests/test_xdsm.py @@ -3,6 +3,13 @@ from pyxdsm.XDSM import XDSM, __file__ from numpy.distutils.exec_command import find_executable + +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('%')] + class TestXDSM(unittest.TestCase): def setUp(self): @@ -102,6 +109,24 @@ def test_options(self): 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_stacked_system(self): + + x = XDSM() + + x.add_system('test', 'Optimization', 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_tikz_content(self): # Check if TiKZ file was created. # Compare the content of the sample below and the newly created TiKZ file. @@ -222,12 +247,6 @@ def test_tikz_content(self): \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) From 9f22bc04be3de3b674f0036d558137472443d38c Mon Sep 17 00:00:00 2001 From: "Justin S. Gray" Date: Mon, 31 Aug 2020 14:08:14 -0400 Subject: [PATCH 8/8] adding constants for the diagram styles --- README.md | 18 +++++++----------- examples/kitchen_sink.pdf | Bin 47763 -> 47843 bytes examples/kitchen_sink.py | 3 ++- examples/mat_eqn_example.pdf | Bin 19394 -> 19394 bytes examples/mdf.pdf | Bin 44006 -> 44006 bytes examples/mdf.py | 18 +++++++----------- pyxdsm/XDSM.py | 10 ++++++++++ pyxdsm/tests/test_xdsm.py | 32 ++++++++++++++++---------------- 8 files changed, 42 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 9675e79..27c5300 100644 --- a/README.md +++ b/README.md @@ -41,20 +41,16 @@ You need to install these libraries for pyXDSM to work. See the [install guide]( ## How do I use it? Here is a simple example. There are some other more advanced things you can do as well. Check out the [examples folder](https://github.com/mdolab/pyXDSM/blob/master/examples) ```python -from pyxdsm.XDSM import XDSM - -opt = 'Optimization' -solver = 'MDA' -func = 'Function' +from pyxdsm.XDSM import XDSM, OPT, SOLVER, FUNC x = XDSM() -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.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') diff --git a/examples/kitchen_sink.pdf b/examples/kitchen_sink.pdf index c54e59a14aa2f5005f06910eeae807c8be0e5234..4380930dcf03631ce810a43c1558876290214a1e 100644 GIT binary patch delta 4885 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 HMNdWwbqH9{ delta 4771 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 delta 162 zcmX>!o$=6g#tqW$Ooo<|W!=>|O$-bTO-zi9OeXufOCj+J+`}~uEfq9EQX>?6GRsmG zj0_AdG!?Q75=%0QQxg@+Qj3Z+^YawU^o;ckHh*w`$K>Q{Y--_TYG!V1U}0ctZs=-e cWNK_?YHVueVrFD$YUXOEU_(I3WCia<063K@_y7O^ diff --git a/examples/mdf.pdf b/examples/mdf.pdf index 7106eb89fb57d409a3d48f46b558bb0f57bf4567..765f55822d0a15f1c27deccb9f4b733f438bc4b9 100644 GIT binary patch delta 163 zcmaEMo$1+irVZ~GGZ`67{p*kH2a5-B8}%aU+SLrVpXkkkkTpUkpU z1tSAP3r&UWg2a-H;?zWivecsD%=|nBGd*KHgUv^lykd1Wba68