From e7c114fab23b56e3f30f91380840526bb42ff166 Mon Sep 17 00:00:00 2001 From: imcovangent <I.vanGent@tudelft.nl> Date: Mon, 20 Jun 2016 15:43:36 +0200 Subject: [PATCH] resolves #5 (creation of XDSM) resolves #16 (creation of XDSM with MDF and Gauss-Seidel) --- .gitignore | 1 + .idea/workspace.xml | 170 +++++++------- pyKADMOS/MDOproblem.py | 282 ++++++++++++++--------- pyKADMOS/MDOproblem.pyc | Bin 21444 -> 23711 bytes pyKADMOS/MDOstatic.py | 46 +++- pyKADMOS/MDOstatic.pyc | Bin 16689 -> 17499 bytes pyKADMOS/MDOvisualization.py | 103 ++++++--- pyKADMOS/MDOvisualization.pyc | Bin 14417 -> 16626 bytes pyKADMOS/PyXDSM/.gitignore | 7 - pyKADMOS/PyXDSM/Example/IDF.py | 54 ----- pyKADMOS/PyXDSM/ReadMe.md | 43 ---- pyKADMOS/PyXDSM/XDSM/XDSM.py | 283 ------------------------ pyKADMOS/PyXDSM/XDSM/__init__.py | 0 pyKADMOS/PyXDSM/XDSM/diagram_border.tex | 10 - pyKADMOS/PyXDSM/XDSM/diagram_styles.tex | 109 --------- pyKADMOS/XDSM_writer/diagram_styles.tex | 1 + pyKADMOS/sellarProblem.py | 11 +- pyKADMOS/testXDSM.log | 29 +-- pyKADMOS/testXDSM.pdf | Bin 31166 -> 55483 bytes pyKADMOS/testXDSM.tex | 155 +++++++++---- 20 files changed, 488 insertions(+), 816 deletions(-) create mode 100644 .gitignore delete mode 100755 pyKADMOS/PyXDSM/.gitignore delete mode 100755 pyKADMOS/PyXDSM/Example/IDF.py delete mode 100755 pyKADMOS/PyXDSM/ReadMe.md delete mode 100755 pyKADMOS/PyXDSM/XDSM/XDSM.py delete mode 100755 pyKADMOS/PyXDSM/XDSM/__init__.py delete mode 100755 pyKADMOS/PyXDSM/XDSM/diagram_border.tex delete mode 100755 pyKADMOS/PyXDSM/XDSM/diagram_styles.tex diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..62c893550 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea/ \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml index a87a04dfa..b2a7cf622 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -5,24 +5,22 @@ </component> <component name="ChangeListManager"> <list default="true" id="d3e74292-1e1a-4cba-81b3-9c9d67f586ca" name="Default" comment=""> - <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/pyKADMOS/testXDSM.pdf" /> - <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/pyKADMOS/XDSM_writer/.gitignore" /> - <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/pyKADMOS/XDSM_writer/IDF.tex" /> - <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/pyKADMOS/XDSM_writer/IDF_example.py" /> - <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/pyKADMOS/XDSM_writer/XDSM.py" /> - <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/pyKADMOS/XDSM_writer/__init__.py" /> - <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/pyKADMOS/XDSM_writer/diagram_border.tex" /> - <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/pyKADMOS/XDSM_writer/diagram_styles.tex" /> - <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/pyKADMOS/testXDSM.aux" /> - <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/pyKADMOS/testXDSM.log" /> - <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/pyKADMOS/testXDSM.tex" /> + <change type="DELETED" beforePath="$PROJECT_DIR$/pyKADMOS/PyXDSM/.gitignore" afterPath="" /> + <change type="DELETED" beforePath="$PROJECT_DIR$/pyKADMOS/PyXDSM/Example/IDF.py" afterPath="" /> + <change type="DELETED" beforePath="$PROJECT_DIR$/pyKADMOS/PyXDSM/ReadMe.md" afterPath="" /> + <change type="DELETED" beforePath="$PROJECT_DIR$/pyKADMOS/PyXDSM/XDSM/XDSM.py" afterPath="" /> + <change type="DELETED" beforePath="$PROJECT_DIR$/pyKADMOS/PyXDSM/XDSM/__init__.py" afterPath="" /> + <change type="DELETED" beforePath="$PROJECT_DIR$/pyKADMOS/PyXDSM/XDSM/diagram_border.tex" afterPath="" /> + <change type="DELETED" beforePath="$PROJECT_DIR$/pyKADMOS/PyXDSM/XDSM/diagram_styles.tex" afterPath="" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyKADMOS/testXDSM.pdf" afterPath="$PROJECT_DIR$/pyKADMOS/testXDSM.pdf" /> <change type="MODIFICATION" beforePath="$PROJECT_DIR$/.idea/workspace.xml" afterPath="$PROJECT_DIR$/.idea/workspace.xml" /> <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyKADMOS/MDOproblem.py" afterPath="$PROJECT_DIR$/pyKADMOS/MDOproblem.py" /> <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyKADMOS/MDOstatic.py" afterPath="$PROJECT_DIR$/pyKADMOS/MDOstatic.py" /> <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyKADMOS/MDOvisualization.py" afterPath="$PROJECT_DIR$/pyKADMOS/MDOvisualization.py" /> - <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyKADMOS/PyXDSM/Example/IDF.py" afterPath="$PROJECT_DIR$/pyKADMOS/PyXDSM/Example/IDF.py" /> - <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyKADMOS/PyXDSM/XDSM/XDSM.py" afterPath="$PROJECT_DIR$/pyKADMOS/PyXDSM/XDSM/XDSM.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyKADMOS/XDSM_writer/diagram_styles.tex" afterPath="$PROJECT_DIR$/pyKADMOS/XDSM_writer/diagram_styles.tex" /> <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyKADMOS/sellarProblem.py" afterPath="$PROJECT_DIR$/pyKADMOS/sellarProblem.py" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyKADMOS/testXDSM.log" afterPath="$PROJECT_DIR$/pyKADMOS/testXDSM.log" /> + <change type="MODIFICATION" beforePath="$PROJECT_DIR$/pyKADMOS/testXDSM.tex" afterPath="$PROJECT_DIR$/pyKADMOS/testXDSM.tex" /> </list> <ignored path="KADMOS.iws" /> <ignored path=".idea/workspace.xml" /> @@ -48,7 +46,7 @@ <SUITE FILE_PATH="coverage/KADMOS$Doc_MDOproblem_class.coverage" NAME="doc MDOproblem class Coverage Results" MODIFIED="1465810428149" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="" /> <SUITE FILE_PATH="coverage/KADMOS$CPACSdummyProblem.coverage" NAME="CPACSdummyProblem Coverage Results" MODIFIED="1465915292787" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/pyKADMOS" /> <SUITE FILE_PATH="coverage/KADMOS$bigMathProblem.coverage" NAME="bigMathProblem Coverage Results" MODIFIED="1463418247627" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/pyKADMOS" /> - <SUITE FILE_PATH="coverage/KADMOS$sellarProblem.coverage" NAME="sellarProblem Coverage Results" MODIFIED="1466114812664" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/pyKADMOS" /> + <SUITE FILE_PATH="coverage/KADMOS$sellarProblem.coverage" NAME="sellarProblem Coverage Results" MODIFIED="1466430091776" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/pyKADMOS" /> <SUITE FILE_PATH="coverage/KADMOS$test_pymetis.coverage" NAME="test_pymetis Coverage Results" MODIFIED="1463842497510" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/pyKADMOS" /> </component> <component name="CreatePatchCommitExecutor"> @@ -63,8 +61,8 @@ <file leaf-file-name="MDOproblem.py" pinned="false" current-in-tab="false"> <entry file="file://$PROJECT_DIR$/pyKADMOS/MDOproblem.py"> <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="-1290"> - <caret line="497" column="23" selection-start-line="497" selection-start-column="8" selection-end-line="497" selection-end-column="23" /> + <state relative-caret-position="249"> + <caret line="717" column="36" selection-start-line="717" selection-start-column="36" selection-end-line="717" selection-end-column="36" /> <folding> <element signature="e#0#11#0" expanded="true" /> </folding> @@ -72,21 +70,11 @@ </provider> </entry> </file> - <file leaf-file-name="IDF_example.py" pinned="false" current-in-tab="false"> - <entry file="file://$PROJECT_DIR$/pyKADMOS/XDSM_writer/IDF_example.py"> - <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="447"> - <caret line="41" column="62" selection-start-line="40" selection-start-column="4" selection-end-line="41" selection-end-column="62" /> - <folding /> - </state> - </provider> - </entry> - </file> - <file leaf-file-name="MDOvisualization.py" pinned="false" current-in-tab="true"> + <file leaf-file-name="MDOvisualization.py" pinned="false" current-in-tab="false"> <entry file="file://$PROJECT_DIR$/pyKADMOS/MDOvisualization.py"> <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="387"> - <caret line="277" column="0" selection-start-line="277" selection-start-column="0" selection-end-line="277" selection-end-column="0" /> + <state relative-caret-position="849"> + <caret line="356" column="61" selection-start-line="356" selection-start-column="61" selection-end-line="356" selection-end-column="61" /> <folding> <element signature="e#0#31#0" expanded="true" /> </folding> @@ -94,21 +82,23 @@ </provider> </entry> </file> - <file leaf-file-name="XDSM.py" pinned="false" current-in-tab="false"> - <entry file="file://$PROJECT_DIR$/pyKADMOS/XDSM_writer/XDSM.py"> + <file leaf-file-name="MDOstatic.py" pinned="false" current-in-tab="false"> + <entry file="file://$PROJECT_DIR$/pyKADMOS/MDOstatic.py"> <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="885"> - <caret line="59" column="8" selection-start-line="59" selection-start-column="8" selection-end-line="59" selection-end-column="8" /> - <folding /> + <state relative-caret-position="894"> + <caret line="464" column="62" selection-start-line="464" selection-start-column="62" selection-end-line="464" selection-end-column="62" /> + <folding> + <element signature="e#39#52#0" expanded="true" /> + </folding> </state> </provider> </entry> </file> - <file leaf-file-name="sellarProblem.py" pinned="false" current-in-tab="false"> + <file leaf-file-name="sellarProblem.py" pinned="false" current-in-tab="true"> <entry file="file://$PROJECT_DIR$/pyKADMOS/sellarProblem.py"> <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="585"> - <caret line="100" column="21" selection-start-line="100" selection-start-column="21" selection-end-line="100" selection-end-column="21" /> + <state relative-caret-position="840"> + <caret line="56" column="38" selection-start-line="56" selection-start-column="38" selection-end-line="56" selection-end-column="38" /> <folding> <element signature="e#0#13#0" expanded="true" /> </folding> @@ -131,9 +121,6 @@ <component name="IdeDocumentHistory"> <option name="CHANGED_PATHS"> <list> - <option value="$PROJECT_DIR$/pyKADMOS/KB_CPACS_dummy/CON_FD-info.json" /> - <option value="$PROJECT_DIR$/pyKADMOS/KB_CPACS_dummy/CON_FD-input.xml" /> - <option value="$PROJECT_DIR$/pyKADMOS/KB_CPACS_dummy/OBJ-info.json" /> <option value="$PROJECT_DIR$/pyKADMOS/KB_CPACS_dummy/OBJ-output.xml" /> <option value="$PROJECT_DIR$/pyKADMOS/KB_CPACS_dummy/CON_FD-output.xml" /> <option value="$PROJECT_DIR$/pyKADMOS/KB_CPACS_dummy/EMISSION-input.xml" /> @@ -178,10 +165,13 @@ <option value="$PROJECT_DIR$/pyKADMOS/XDSM-master/XDSM/XDSM.py" /> <option value="$PROJECT_DIR$/pyKADMOS/XDSM-master/XDSM/IDF_example.py" /> <option value="$PROJECT_DIR$/pyKADMOS/XDSM/IDF_example.py" /> - <option value="$PROJECT_DIR$/pyKADMOS/MDOstatic.py" /> + <option value="$PROJECT_DIR$/pyKADMOS/XDSM_writer/IDF_example.py" /> + <option value="$PROJECT_DIR$/pyKADMOS/testXDSM.tex" /> + <option value="$PROJECT_DIR$/pyKADMOS/XDSM_writer/diagram_styles.tex" /> + <option value="$PROJECT_DIR$/pyKADMOS/MDOvisualization.py" /> <option value="$PROJECT_DIR$/pyKADMOS/MDOproblem.py" /> <option value="$PROJECT_DIR$/pyKADMOS/sellarProblem.py" /> - <option value="$PROJECT_DIR$/pyKADMOS/MDOvisualization.py" /> + <option value="$PROJECT_DIR$/pyKADMOS/MDOstatic.py" /> </list> </option> </component> @@ -192,8 +182,8 @@ <sorting>DEFINITION_ORDER</sorting> </component> <component name="ProjectFrameBounds"> - <option name="width" value="1280" /> - <option name="height" value="800" /> + <option name="width" value="1920" /> + <option name="height" value="1080" /> </component> <component name="ProjectInspectionProfilesVisibleTreeState"> <entry key="Project Default"> @@ -239,10 +229,6 @@ <foldersAlwaysOnTop value="true" /> </navigator> <panes> - <pane id="ProjectPane"> - <subPane /> - </pane> - <pane id="Scratches" /> <pane id="Scope"> <subPane subId="Project Files"> <PATH> @@ -282,13 +268,17 @@ <option name="myItemId" value="" /> <option name="myItemType" value="" /> </PATH_ELEMENT> - <PATH_ELEMENT USER_OBJECT="PyXDSM"> + <PATH_ELEMENT USER_OBJECT="XDSM_writer"> <option name="myItemId" value="" /> <option name="myItemType" value="" /> </PATH_ELEMENT> </PATH> </subPane> </pane> + <pane id="ProjectPane"> + <subPane /> + </pane> + <pane id="Scratches" /> </panes> </component> <component name="PropertiesComponent"> @@ -730,16 +720,16 @@ </todo-panel> </component> <component name="ToolWindowManager"> - <frame x="0" y="0" width="1280" height="800" extended-state="0" /> + <frame x="0" y="0" width="1920" height="1080" extended-state="0" /> <editor active="true" /> <layout> - <window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.1558966" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" /> + <window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.14323749" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" /> <window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32876712" sideWeight="0.49676898" order="6" side_tool="false" content_ui="tabs" /> <window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4328524" sideWeight="0.4394184" order="7" side_tool="true" content_ui="tabs" /> <window_info id="Database" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" /> - <window_info id="Python Console" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32328767" sideWeight="0.4628433" order="7" side_tool="false" content_ui="tabs" /> + <window_info id="Python Console" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32240438" sideWeight="0.4628433" order="7" side_tool="false" content_ui="tabs" /> <window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32876712" sideWeight="0.49676898" order="7" side_tool="false" content_ui="tabs" /> - <window_info id="Run" active="false" anchor="bottom" auto_hide="true" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.43150684" sideWeight="0.56058156" order="2" side_tool="false" content_ui="tabs" /> + <window_info id="Run" active="true" anchor="bottom" auto_hide="true" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.31620553" sideWeight="0.56058156" order="2" side_tool="false" content_ui="tabs" /> <window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.13844515" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" /> <window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32608697" sideWeight="0.49192247" order="7" side_tool="false" content_ui="tabs" /> <window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="true" content_ui="tabs" /> @@ -791,20 +781,6 @@ <watches-manager /> </component> <component name="editorHistoryManager"> - <entry file="file://$PROJECT_DIR$/pyKADMOS/KB_CPACS_dummy/CON_EM-output.xml"> - <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="75"> - <caret line="5" column="13" selection-start-line="5" selection-start-column="13" selection-end-line="5" selection-end-column="13" /> - </state> - </provider> - </entry> - <entry file="file://$PROJECT_DIR$/pyKADMOS/KB_CPACS_dummy/CON_EM-input.xml"> - <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="0"> - <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" /> - </state> - </provider> - </entry> <entry file="file://$PROJECT_DIR$/pyKADMOS/KB_CPACS_dummy/CON_EM-info.json"> <provider selected="true" editor-type-id="text-editor"> <state relative-caret-position="60"> @@ -1039,79 +1015,87 @@ <entry file="file://$PROJECT_DIR$/pyKADMOS/XDSM-master/XDSM/__init__.py" /> <entry file="file://$PROJECT_DIR$/pyKADMOS/XDSM-master/XDSM/IDF_example.py" /> <entry file="file://$PROJECT_DIR$/pyKADMOS/XDSM-master/XDSM/XDSM.py" /> - <entry file="file://$PROJECT_DIR$/pyKADMOS/PyXDSM/ReadMe.md"> + <entry file="file://$PROJECT_DIR$/pyKADMOS/PyXDSM/ReadMe.md" /> + <entry file="file://$PROJECT_DIR$/pyKADMOS/XDSM_writer/diagram_border.tex"> <provider selected="true" editor-type-id="text-editor"> <state relative-caret-position="0"> <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/pyKADMOS/XDSM_writer/diagram_border.tex"> + <entry file="file://$PROJECT_DIR$/pyKADMOS/XDSM_writer/IDF.log"> <provider selected="true" editor-type-id="text-editor"> <state relative-caret-position="0"> <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/pyKADMOS/XDSM_writer/diagram_styles.tex"> + <entry file="file://$PROJECT_DIR$/pyKADMOS/XDSM_writer/IDF_example.py"> <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="165"> - <caret line="11" column="18" selection-start-line="11" selection-start-column="18" selection-end-line="11" selection-end-column="18" /> + <state relative-caret-position="405"> + <caret line="27" column="16" selection-start-line="27" selection-start-column="16" selection-end-line="27" selection-end-column="16" /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/pyKADMOS/XDSM_writer/XDSM.py"> + <entry file="file://$PROJECT_DIR$/pyKADMOS/testXDSM.tex"> <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="885"> - <caret line="59" column="8" selection-start-line="59" selection-start-column="8" selection-end-line="59" selection-end-column="8" /> - <folding /> + <state relative-caret-position="212"> + <caret line="152" column="20" selection-start-line="152" selection-start-column="20" selection-end-line="152" selection-end-column="20" /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/pyKADMOS/sellarProblem.py"> + <entry file="file://$PROJECT_DIR$/pyKADMOS/XDSM_writer/XDSM.py"> <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="585"> - <caret line="100" column="21" selection-start-line="100" selection-start-column="21" selection-end-line="100" selection-end-column="21" /> - <folding> - <element signature="e#0#13#0" expanded="true" /> - </folding> + <state relative-caret-position="909"> + <caret line="281" column="34" selection-start-line="281" selection-start-column="34" selection-end-line="281" selection-end-column="34" /> + <folding /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/pyKADMOS/XDSM_writer/IDF_example.py"> + <entry file="file://$PROJECT_DIR$/pyKADMOS/XDSM_writer/diagram_styles.tex"> <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="447"> - <caret line="41" column="62" selection-start-line="40" selection-start-column="4" selection-end-line="41" selection-end-column="62" /> + <state relative-caret-position="300"> + <caret line="23" column="0" selection-start-line="23" selection-start-column="0" selection-end-line="23" selection-end-column="0" /> <folding /> </state> </provider> </entry> <entry file="file://$PROJECT_DIR$/pyKADMOS/MDOstatic.py"> <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="2427"> - <caret line="250" column="9" selection-start-line="250" selection-start-column="9" selection-end-line="250" selection-end-column="9" /> + <state relative-caret-position="894"> + <caret line="464" column="62" selection-start-line="464" selection-start-column="62" selection-end-line="464" selection-end-column="62" /> <folding> <element signature="e#39#52#0" expanded="true" /> </folding> </state> </provider> </entry> + <entry file="file://$PROJECT_DIR$/pyKADMOS/MDOvisualization.py"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="849"> + <caret line="356" column="61" selection-start-line="356" selection-start-column="61" selection-end-line="356" selection-end-column="61" /> + <folding> + <element signature="e#0#31#0" expanded="true" /> + </folding> + </state> + </provider> + </entry> <entry file="file://$PROJECT_DIR$/pyKADMOS/MDOproblem.py"> <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="-1290"> - <caret line="497" column="23" selection-start-line="497" selection-start-column="8" selection-end-line="497" selection-end-column="23" /> + <state relative-caret-position="249"> + <caret line="717" column="36" selection-start-line="717" selection-start-column="36" selection-end-line="717" selection-end-column="36" /> <folding> <element signature="e#0#11#0" expanded="true" /> </folding> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/pyKADMOS/MDOvisualization.py"> + <entry file="file://$PROJECT_DIR$/pyKADMOS/sellarProblem.py"> <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="387"> - <caret line="277" column="0" selection-start-line="277" selection-start-column="0" selection-end-line="277" selection-end-column="0" /> + <state relative-caret-position="840"> + <caret line="56" column="38" selection-start-line="56" selection-start-column="38" selection-end-line="56" selection-end-column="38" /> <folding> - <element signature="e#0#31#0" expanded="true" /> + <element signature="e#0#13#0" expanded="true" /> </folding> </state> </provider> diff --git a/pyKADMOS/MDOproblem.py b/pyKADMOS/MDOproblem.py index a73396df4..b03bb0406 100644 --- a/pyKADMOS/MDOproblem.py +++ b/pyKADMOS/MDOproblem.py @@ -508,29 +508,27 @@ class MDOproblem: :return: dictionary with the PSG process flow and the PSG data flow :rtype: dict """ - - PSG = dict.fromkeys(['data flow', 'process flow']) - - #------------------# - # PSG process flow # - #------------------# - + # ------------------# + # FPG+input check # + # ------------------# # Find all function nodes - function_nodes = set(find_all_nodes(FPG, attr_cond=['category','==','function'])) + function_nodes = set(find_all_nodes(FPG, attr_cond=['category', '==', 'function'])) # Select design variables, parameters, constraint and objective functions des_var_nodes = find_all_nodes(FPG, attr_cond=['PSG role', '==', 'design variable']) assert len(des_var_nodes) > 0, "No design variables are specified. Use the 'PSG role' attribute for this." - parameter_nodes = list(set(find_all_nodes(FPG, category='variable', subcategory='all inputs')).\ - difference(set(des_var_nodes))) + parameter_nodes = list(set(find_all_nodes(FPG, category='variable', subcategory='all inputs')). \ + difference(set(des_var_nodes))) constraint_nodes = find_all_nodes(FPG, attr_cond=['PSG role', '==', 'constraint']) - assert len(constraint_nodes) > 0,"No constraint variables are specified. Use the 'PSG role' attribute for this." + assert len( + constraint_nodes) > 0, "No constraint variables are specified. Use the 'PSG role' attribute for this." objective_node = find_all_nodes(FPG, attr_cond=['PSG role', '==', 'objective']) assert len(objective_node) == 1, "%d design variables are specified. Only one objective node is allowed." \ "Use the 'PSG role' attribute for this." % len(objective_node) + optimizer_nodes_in = objective_node + constraint_nodes constraint_functions = list() - for idx,node in enumerate(objective_node+constraint_nodes): + for idx, node in enumerate(objective_node + constraint_nodes): assert FPG.node[node]['indegree'] == 1, "Invalid indegree of %d, while it should be 1." \ % FPG.node[node]['indegree'] assert FPG.node[node]['outdegree'] == 0, "Invalid outdegree of %d, while it should be 0." \ @@ -539,12 +537,8 @@ class MDOproblem: objective_function = FPG.in_edges(node)[0][0] else: constraint_functions.append(FPG.in_edges(node)[0][0]) + optimizer_functions = [objective_function] + constraint_functions - print function_nodes - print objective_function - print constraint_functions - print des_var_nodes - print parameter_nodes # Select analysis order functions for node in analysis_order: @@ -552,17 +546,22 @@ class MDOproblem: "One of the names ('%s') in the analysis_order input is invalid." % node # Remove the objective function and constraint functions from the set - MDA_analysis_nodes = function_nodes.difference(set([objective_function]+constraint_functions)) + MDA_analysis_nodes = function_nodes.difference(set(optimizer_functions)) # Check if any functions are left between analysis nodes and analysis order? assert len(MDA_analysis_nodes.difference(set(analysis_order))) == 0, \ "There are undefined functions present in the FPG, namely %s! These should be added to the analysis order" \ " or become objective/constraints functions." % MDA_analysis_nodes.difference(set(analysis_order)) + #------------------# + # PSG process flow # + #------------------# # Set up PSG process graph PSG_process = nx.DiGraph() PSG_process.graph['architecture'] = 'MDF' - PSG_process.graph['number_of_diagonal_blocks'] = 2 + len(analysis_order) + 1 + len(constraint_functions) + PSG_process.graph['number_of_diagonal_blocks'] = 3 + len(analysis_order) + 1 + len(constraint_functions) + PSG_process.graph['number_of_MDA_analyses'] = len(analysis_order) + PSG_process.graph['number_of_OPT_functions'] = 1 + len(constraint_functions) # Add MDA block PSG_process.add_node('MDA', @@ -571,18 +570,21 @@ class MDOproblem: shape='8', label='MDA', level=None, - diagonal_position=1) + diagonal_position=2, + process_step=2, + converger_step=3+len(analysis_order)) # Connect MDA + analyses - from_node = 'MDA' if MDA_type == 'Gauss-Seidel': + from_node = 'MDA' for idx, node in enumerate(analysis_order): - PSG_process.add_node(node,FPG.node[node],diagonal_position=2+idx) + PSG_process.add_node(node,FPG.node[node],diagonal_position=3+idx) PSG_process.node[node]['category'] = 'architecture element' PSG_process.node[node]['subcategory'] = 'MDA analysis' - PSG_process.add_edge(from_node, node) + PSG_process.node[node]['process_step'] = idx+3 + PSG_process.add_edge(from_node, node, process_step=idx+3) from_node = node - PSG_process.add_edge(from_node,'MDA') + PSG_process.add_edge(from_node,'MDA',process_step=idx+4) # Add optimization block PSG_process.add_node('Optimizer', @@ -591,105 +593,173 @@ class MDOproblem: shape='8', label='OPT', level=None, - diagonal_position=0) + diagonal_position=1, + process_step=1, + converger_step=3+len(analysis_order)+2) # Connect optimization with MDA - PSG_process.add_edge('Optimizer', 'MDA') + PSG_process.add_edge('Optimizer', 'MDA', process_step=2) # Connect MDA with functions and functions with optimizer - for idx, node in enumerate(constraint_functions+[objective_function]): - PSG_process.add_node(node, FPG.node[node],diagonal_position=2+len(analysis_order)+idx) + for idx, node in enumerate(optimizer_functions): + PSG_process.add_node(node, FPG.node[node],diagonal_position=3+len(analysis_order)+idx) PSG_process.node[node]['category'] = 'architecture element' PSG_process.node[node]['subcategory'] = 'optimizer function' - PSG_process.add_edge('MDA',node) - PSG_process.add_edge(node,'Optimizer') + PSG_process.node[node]['process_step'] = 4+len(analysis_order) + PSG_process.add_edge('MDA',node, process_step=4+len(analysis_order)) + PSG_process.add_edge(node,'Optimizer', process_step=5+len(analysis_order)) - # Add input variables x^(0) - for node in des_var_nodes: - new_node = '/PSG/design_variables/initial_guesses/' + FPG.node[node]['label'] + '^0' - PSG_process.add_node(new_node, - category='architecture element', - subcategory='initial guess design variable', - shape='o', - label=FPG.node[node]['label']+'(0)', - level=4) - PSG_process.add_edge(new_node,'Optimizer') - - # Add output variables x^* - for node in des_var_nodes: - new_node = '/PSG/design_variables/final_value/' + FPG.node[node]['label'] + '^*' - PSG_process.add_node(new_node, - category='architecture element', - subcategory='final design variable', - shape='o', - label=FPG.node[node]['label']+'(0)', - level=4) - PSG_process.add_edge('Optimizer',new_node) - - print '' - print 'NODES' - for node, data in PSG_process.nodes_iter(data=True): - print node - if 'diagonal_position' in data: - print data['diagonal_position'] - - print '' - print 'EDGES' - for edge in PSG_process.edges_iter(data=True): - print edge - - PSG['process flow'] = PSG_process + # Add Initiator block + PSG_process.add_node('Initiator', + category='architecture element', + subcategory='initiator', + shape='8', + label='INI', + level=None, + diagonal_position=0, + process_step = 0, + converger_step = 6+len(constraint_functions)) + # Connect initiator with optimizer + PSG_process.add_edge('Initiator', 'Optimizer', process_step=1) + PSG_process.add_edge('Optimizer', 'Initiator', process_step=6+len(constraint_functions)) # ------------------# # PSG data flow # # ------------------# - - # Find all function nodes - - - # Select constraint and objective functions - - - # Select analysis order functions - - - # Check if any functions are left? - + # Set up PSG process graph + PSG_data = FPG.copy() + PSG_data.graph['architecture'] = 'MDF' + PSG_data.graph['number_of_diagonal_blocks'] = 2 + len(analysis_order) + 1 + len(constraint_functions) + PSG_data.graph['number_of_MDA_analyses'] = len(analysis_order) + PSG_data.graph['number_of_OPT_functions'] = 1 + len(constraint_functions) # Add MDA block + PSG_data.add_node('MDA', + category='architecture element', + subcategory='MDA', + shape='8', + label='MDA', + level=None, + diagonal_position=2) + + # Add Initiator block + PSG_data.add_node('Initiator', + category='architecture element', + subcategory='initiator', + shape='8', + label='INI', + level=None, + diagonal_position=0) - - # Adjust data flow according to MDA (add variable copies and rearrange edges) - - - # Add design variable inputs for MDA analyses - - - # Add starting coupling variables values - - + # Loop over MDA analyses, add copy variables and adjust edges + if MDA_type == 'Gauss-Seidel': + for idx, analysis in enumerate(analysis_order): + PSG_data.node[analysis]['category'] = 'architecture element' + PSG_data.node[analysis]['subcategory'] = 'MDA analysis' + PSG_data.node[analysis]['diagonal_position'] = 3+idx + + # Check incoming edges + in_edges = FPG.in_edges(analysis) + for edge in in_edges: + # Check if edge is an input + in_node = edge[0] + if not set([in_node]).intersection(set(find_all_nodes(FPG,subcategory='all inputs'))): + if set([in_node]).intersection(set(find_all_nodes(FPG, subcategory='all problematic nodes'))): + raise IOError("A problematic node is still present in the FPG.") + elif set([in_node]).intersection(set(find_all_nodes(FPG, subcategory='all couplings'))): + # Check if the node is coupled to a future analysis + coupled_functions = map((lambda x: x[0]), FPG.in_edges(in_node)) + if set(coupled_functions).intersection(set(analysis_order[idx:])): + # Add variable copy node between MDA and function + new_node = '/PSG/coupling_variables/MDA/' + FPG.node[in_node]['label'] + str('^c') + PSG_data.add_node(new_node, + category='architecture element', + subcategory='MDA coupling variable', + shape='o', + label=FPG.node[in_node]['label'] + '^c', + level=3) + PSG_data.add_edge('MDA',new_node) + PSG_data.add_edge(new_node, analysis) + PSG_data.remove_edge(in_node,edge[1]) + # Add edge between the coupling variable and the MDA + PSG_data.add_edge(in_node,'MDA') + # Add initial guess MDA coupling variable + new_node = '/PSG/coupling_variables/MDA/' + FPG.node[in_node]['label'] + str('^{c0}') + PSG_data.add_node(new_node, + category='architecture element', + subcategory='initial guess MDA coupling variable', + shape='o', + label=FPG.node[in_node]['label'] + '^{c0}', + level=3) + PSG_data.add_edge(new_node, 'MDA') + PSG_data.add_edge('Initiator', new_node) + # Check outcoming edges + out_edges = FPG.out_edges(analysis) + for edge in out_edges: + # Check if edge is a coupling variable + out_node = edge[1] + if set([out_node]).intersection(set(find_all_nodes(FPG, subcategory='all couplings'))): + # Add final coupling variable node and connect to analysis function and initiator + new_node = '/PSG/coupling_variables/MDA/' + FPG.node[out_node]['label'] + str('^*') + PSG_data.add_node(new_node, + category='architecture element', + subcategory='final MDA coupling variable', + shape='o', + label=FPG.node[out_node]['label'] + '^*', + level=3) + PSG_data.add_edge(analysis,new_node) + PSG_data.add_edge(new_node,'Initiator') + + # Recategorize design variables and connect to optimizer and initiator # Add optimization block + PSG_data.add_node('Optimizer', + category='architecture element', + subcategory='optimizer', + shape='8', + label='OPT', + level=None, + diagonal_position=1) + for node in des_var_nodes: + # Connect design variables to optimizer + PSG_data.add_edge('Optimizer',node) - # Connect optimization block to design variables - - - # Add design variable starting values to opt block - - - # Add final design variable outputs to opt block - - - # Add functions plus variable nodes - - - # Connect function outputs to the optimizer - - - # Add final coupling variable output y^* - - - return PSG + # Add input variables x^(0) and connect to optimizer + new_node = '/PSG/design_variables/initial_guesses/' + FPG.node[node]['label'] + '^0' + PSG_data.add_node(new_node, + category='architecture element', + subcategory='initial guess design variable', + shape='o', + label=FPG.node[node]['label'] + '^0', + level=3) + PSG_data.add_edge(new_node, 'Optimizer') + PSG_data.add_edge('Initiator', new_node) + + # Add output variables x^* and connect to optimizer and initiator + new_node = '/PSG/design_variables/final_value/' + FPG.node[node]['label'] + '^*' + PSG_data.add_node(new_node, + category='architecture element', + subcategory='final design variable', + shape='o', + label=FPG.node[node]['label'] + '^*', + level=3) + PSG_data.add_edge('Optimizer', new_node) + PSG_data.add_edge(new_node, 'Initiator') + + # Add parameters and connect with INI function + for node in parameter_nodes: + # Connect parameter node to initiator + PSG_data.add_edge('Initiator', node) + + # Adjust and connect optimizer functions output to optimizer + for idx, node in enumerate(optimizer_functions): + PSG_data.node[node]['diagonal_position']= 3 + len(analysis_order) + idx + PSG_data.node[node]['category'] = 'architecture element' + PSG_data.node[node]['subcategory'] = 'optimizer function' + for node in optimizer_nodes_in: + PSG_data.add_edge(node,'Optimizer') + + return {'data flow':PSG_data,'process flow':PSG_process} if __name__ == '__main__': diff --git a/pyKADMOS/MDOproblem.pyc b/pyKADMOS/MDOproblem.pyc index 46762ba3067c8c092b49955331961a15966634e1..3f6db9505cc38010256b6a7d24f669db8dc84b65 100644 GIT binary patch delta 4200 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 R?<R)*U$2*jKTG19;{Pj>71{s* delta 1990 zcmb7F&u<%55T4of+Oe~C{4=iO#%a<fIBiK=0--=TRCSa}h!)wnMpe^F@Jtj(BsjJp zm3Fm)AR&RoWsgX3q!JPmN-tbEAykCKKfnznZk&K4h;QC*%qp}JXxF=M-#7Ekd^5A_ zPru@CKI4S>TRQdq^lM)xhL^n}5oPeZg5Tg5i)cvHV^TN`+AwIJ$&Jy_prJ_)Hce77 zQWmK=ZJ0n=46F#6(CAo*x^WuD$cYP&O43%020Ju_drEfRWsioi7_ozToRm!}4cLH1 zFCl2)k4Ky?c1EcL!7_)z#&oc;NU$Guu!$hpzZ|pV1tQ#}_DpKe9BmmisIjD(|7U+v zCoK8y6S*nc`<8}d<Rr-%qcX6@`hB`(kULJUEv4!Kv8kd8_yv@2Y06?0^nixM5tkBN zP%LC|PrFP;T_PT+l{VY`fyFx|0g(wd#lPaFseh536!pe6!BHHh9>b#JShRN4Ny{ZA zm$+OKxa_TvV?x=IXp%<Qw4uAugG5VW4YG#RsVq<^q@Oi}F>GC0JU}ZY!s%voMKdAn zfj$6m4K;tF8IO^3Xf(1pY(biO8Qp~mQWbJ0sE5TAT~bv|t|`kXdRb;qPg*%NI!>2l zl_fQ;2idFXal^w5sS~7TH84l&X;LQ%6#E=!*t%JA3{t10DZBT~y@Bq%4%ArhM*6PF zQHw}7!BZt?92GE_RZZs`&PL2b((}<BJ4i534kDtP1~G03-#=@1Bz27-BSE%FyF$%^ zRuhPMEFz{(Y9vOcJI(=zI0%PFy!VmTg5l7u3P$<ve~=`_4NCn8anQE-P;CeuYV$%# zc;y$gr2d~~XRj}Bd}Do6rcRxX)^e6AWp#$iZZ1^r<RZ$?YUPhh8zc3Hk6NO#6yh98 zV1*?R&jl|C`cCXf(DO$K%Id<Sf<Ezof<h(YO7HrA#5!u(!%L=~lsD~pEvP{1DH;|r z+}v1S)J;J5(Q{i2Pm+_TtvKy^78ZD{tX=JU7EVx!!HO`=Xr@w>3E!jwIR&8o?<^T3 z2VYtPqh`gZRlj&pebF@h2kn`I+V#B2hJT?s=YP<A!T$^Q`POs(a{J|c6VpZm6PNn= z#myM*{`>8E+`!`YY5$A%)JijjHNFN!*RD5KTg{Eb$JNH#YU^5k63<Qf!@+lx==I&5 zH@3QW2mY_^LA5y$tRR?>bk#<8aA$Ma-K`h>k8dm`B<xGAHUGhlSN+SKXMMl(OliCO z_MPn=)eYiELU8lXz4E5_HP)0VC1%Yk*LarmjJr|gW1QtAPva=*pUqRooMB-k^kJr9 zmotx>r`Y6*X>*$AagC3Tgc)a>D`3pw$a0DcNARq9g3nwD;UWkta0m!WoZyG-=<qX0 lz~-!8S2$^;mi^q#_xLA&;@0hh-)~Ma|BU5_*5@`1{|0)ZTL%CD diff --git a/pyKADMOS/MDOstatic.py b/pyKADMOS/MDOstatic.py index 4c81b1c01..ad818b8e2 100644 --- a/pyKADMOS/MDOstatic.py +++ b/pyKADMOS/MDOstatic.py @@ -168,12 +168,16 @@ def get_categorized_nodes(graph, print_in_log=True): 'inputless': [], 'outputless': [], 'complete': []}, - 'architecture element': {'optimizer': [], - 'MDA': [], - 'optimizer function': [], - 'MDA analysis': [], - 'initial guess design variable': [], - 'final design variable': []}} + 'architecture element': {'initiator': [], + 'optimizer': [], + 'MDA': [], + 'optimizer function': [], + 'MDA analysis': [], + 'initial guess design variable': [], + 'final design variable': [], + 'MDA coupling variable': [], + 'initial guess MDA coupling variable': [], + 'final MDA coupling variable': []}} for node, data in graph.nodes_iter(data=True): for key1 in result: @@ -229,6 +233,8 @@ def find_all_nodes(graph, category='all', subcategory='all', attr_cond=None, pri * all outputs * all couplings * all problematic nodes + * all PSG blocks + * all design variables * hole * supplied input * supplied shared input @@ -248,7 +254,15 @@ def find_all_nodes(graph, category='all', subcategory='all', attr_cond=None, pri * inputless * outputless * complete - * TODO ADD MORE FROM ARCHITECTURE ELEMENTS + * optimizer + * MDA + * optimizer function + * MDA analysis + * initial guess design variable + * final design variable + * MDA coupling variable + * initial guess MDA coupling variable + * final MDA coupling variable Example usage: Just get all nodes of a graph in a list: @@ -266,12 +280,15 @@ def find_all_nodes(graph, category='all', subcategory='all', attr_cond=None, pri """ # Assert inputs possible_categories = ['all','variable','variable group','function','architecture element'] - possible_subcategories = ['all','all inputs','all outputs','all couplings','all problematic nodes','hole', + possible_subcategories = ['all','all inputs','all outputs','all couplings','all problematic nodes', + 'all PSG blocks','all design variables', 'hole', 'supplied input','supplied shared input','output','collision','coupling', 'shared coupling','collided coupling','collided shared coupling','hole group', 'supplied input group','supplied shared input group','output group','coupling group', - 'shared coupling group','hole','inputless','outputless','complete'] - # TODO: add architecture elements subcategories + 'shared coupling group','hole','inputless','outputless','complete','initiator', + 'optimizer','MDA','optimizer function','MDA analysis','initial guess design variable', + 'final design variable','MDA coupling variable','initial guess MDA coupling variable', + 'final MDA coupling variable'] assert isinstance(graph,type(nx.DiGraph())) assert isinstance(category, str) assert isinstance(subcategory, str) @@ -307,10 +324,15 @@ def find_all_nodes(graph, category='all', subcategory='all', attr_cond=None, pri subcategory = ['output', 'collision', 'output group'] elif subcategory == 'all couplings': subcategory = ['coupling', 'shared coupling', 'collided coupling', 'collided shared coupling', - 'coupling group', 'shared coupling group'] + 'coupling group', 'shared coupling group','MDA coupling variable', + 'initial guess MDA coupling variable','final MDA coupling variable'] elif subcategory == 'all problematic nodes': subcategory = ['hole', 'collision', 'collided coupling', 'collided shared coupling', 'hole group', 'inputless', 'outputless'] + elif subcategory == 'all PSG blocks': + subcategory = ['initiator','optimizer','MDA','optimizer function','MDA analysis'] + elif subcategory == 'all design variables': + subcategory = ['initial guess design variable', 'final design variable'] if not isinstance(category, list) and category != 'all': category = [category] @@ -440,4 +462,4 @@ def get_adjacency_matrix(graph, print_in_log=True): pp.pprint(nx.convert.to_dict_of_dicts(graph, edge_data=1)) return {'dict of dicts': nx.convert.to_dict_of_dicts(graph, edge_data=1), - 'SciPy sparse matrix': nx.adjacency_matrix(graph)} + 'SciPy sparse matrix': nx.adjacency_matrix(graph)} \ No newline at end of file diff --git a/pyKADMOS/MDOstatic.pyc b/pyKADMOS/MDOstatic.pyc index 437d5764514717bc8003e5c7232c80651a3634a6..865790597cf43130b5ba16e11a08bc8247cb121d 100644 GIT binary patch delta 2197 zcmcIlO>9#~5T1QMah%u*fduTB#Luw<iSt8<AqfydDk4!)BBe$&rD_j`HO8@P<M&=5 z6i1<?hyDo;D<n8nRaH@;3Q8j*RUBwlwW6rBmsUNMONDx>DwT5O(3yRXWB2D+`+0U} z=G&c}+3$^4F0h~9WG?lIx8dUB)QanKKl?`9^WS6*!fx*yOabuCFhWCzGjuvb5JtEG zBZ~?wyaPpmIR-o=R@%E8yTD)6A)|mfFMes?cr1*1ozy2;Q33Rk?w?bksKPP>R+yw` zwh&~t20Y@}f@tut*&+k;E5^Iwz_WY{iLI+MTZg$i;61>5#nHfK7A>6)98uiqT-r`2 z?7S)Nb)0*#4FIO6o-vN+=TBwRxs-7_VWtzuvPmn99tWE>Qu9g6GX5PGK-`IRE|IPA zmqt4;Gxn1BJ~%3#21gqrh}w@o>pQX6II`UjydAg)cz~*hmE)bjgMbC&A>duW!;~jx zg*jnHsfc*r=s0p6F#ih-YyeCf^IKNHx?5#bR*gSY8C9^c^t-8QgnufRqtWH4q9xQC zZ=uSTch*-o*~usnstyv>3TAb=nPj%Rd`(zsyi*G;cuBqDOsL-*g^UW;HEHP+pN3*( z%dgVXFa8MmmIlD~;@Q|@y$l4fh#P8PHYt1%uQG>6Ky9<ax2<VWg%7Q1V>P}Rg>R<} zutJ#erpgW{6+SHON{xNVJg@MWbV#zTEx4la9ny|<uHNXQnuFb5(-hzijek<O7kCr! zjlefSN&|cea-RWmo4X{>pD4T;_&VS|SW2nVeO0>ar8}(h7U1iFZvfs3+#ySa3vP)| zOT1g+r&Xd7Zs*|J%Ct(kByyibHb`Va{TtCz6S@QiB&bn>-c=p?r4;FcRlZ3Yc+A@> zmX<TRTJyFz7Y=wIs+5{zc_=;%kMwNN${2jfAE|VK-5Op?v7zchVj3S5EE4O<Y31bz zp3n$<UgJBV*jNR=NZ^+vzBZ&3!tO}e4V{l54GK5JTagaeZphSQG;uSsX=z%=*1@CL zNU-rVL(v2NOdXh0y1h>JBF9w5_-PzPEDmGfU&g%l=ynq<dZBPoM|RR=x;!C1dcnLe z50KIME=dtjEk%-V>vjtT!oc_f@d4uSvdUPQ%~$jax7{$eo?x=i-Pa2DwOOjbT?bLP zs~09Td}a%eRD5QOZaCbthZ@O(yL7$#b!{M#%^EX@4;aU?`QsU@!6<*C203`rN~dyb zO-+2z*IpWne!*VIpR&`hre8~%RV%Q;RcRH3abiAq+)n3nRZi-K32b_2t#oxv;qL4Z zy}gYdrz1Myh0)vUscxQRX#eltO76fvTWTeXQn3Gb#s-9U@QtX|gte$Gfz?_z)h1uM zG#F&f@gO?m28j>~@vtMA_`m)GDhC#yZ2PfpE5+;*k0&}y*M<%;)-V3tzMn<J$nX}n zRlG8MvaXj9QSo5-LhxIhT3@4pnKstU-1zh0cfFjunc%URX2;kpT|VY1-HF*+WRUiV zkr*a1N@9$}HWEG(yTtQjmxZxcV`odhjU7<2lCkka>*PvC0QyIZ$Hb-a5FTu0Jg*bq z-Ya$QeZUwcFvP;5Yu|H?-GtjhVn{6Pn{qPj6SpRhiom3geJOTK_8%mWU5_G{w9n+t s%tCyKR_G+i9PcC{57tk!9VB*<m?E*81jUcX#mAH9UE{u6?uaMy7pjr^1ONa4 delta 1613 zcmY*ZUuct86hHU-lQeB&|JazMH8F`_ve?9SHZ<0)&_79R##+0^mQYB?#Oo?8v?l$w z7W_)FDa_%^*hSbLL~suZ!$FrPUj$$3gE*Oc5rl#GHYN<l#@@DbZjzdjoAcds?(dv? z?(dv?UtVW>JIt>B>1uuAzqn_A=wsiDecyd%6J}4miywv5mI9kMzyeri!2RNBPb3il zpQXc!0_6p^ISG~msQNOC{jg;NO9Ork0X7LRM4;ERXt0vO3MG}9xEO>A1BObW^am6y z2IaeqhhQ?t!z7M3W~L6yHsA*E2vmS=*}<~IvQFDkfK{N``B=32b?>|){_=lbeHysI zSY9jyPm6DY1Fc>FNaKI~6Y+C!-qi}+2fPP(FD!XQA>`lQ1<YrMfr+6|>QGT&{o5v^ z(lGweWK_XKCi*D}!oQI2XtX!fgP0naEz<a=$z5;6>>OdVG3qtXPGYB?O(R@+oS6== zRN4%Sft0VK1xfUafpEeVfE5+iuSv@>aXFlf)+~?eL{nw#@Tmev(4Rs(sgOJ*9)&&I zzcEQT@u)%hA10ZvYc>UWpUl;@Zl!rGp<qFfETjyhdJa$-g-4}b*5|FgsPK2BU7q5= zzFjsI9+L}5d~={3r8%*$-f9Z)T378UybZV$csFo2ENOsEy1GXF!0oc_o+;b~{1EUX zu%yb>S-ILGSN~RcJ1p`J;GMv`fO~*@VaX<OeG=!8xS-0hX)sC+cDUX^OLmEbM&HQt zIm<Z}8R3jdQqGC1Mz8CNN*UEGSHyQlDt5Pl!Mn4e67LUGWYcPG;_<P{!-7SUF-5Dp zBlx)lcWe9vSZz(<u!i7b#OubwBWzlum}5Hc!|IjB#Fr7jy&qOua5r&3;@N(sVJ~sI zzj&Y9!E%Cc#RlaUn%N<*c+FJD_~;u)EPfK;tKhkwY33o=azW`=&2-7htNMgm#RcV} zOyFOQpOlq#{=c%90=n5r8{x*-_;~9v-HOWOWyZu4`a$I#u-rv3><m^aYB&mXwAmV> zG^>}Mt2hd!4HZYha^O=iK$rbOOZ8s#npV9K|B1!sW->Fu@k}N-J(JG{&*o>QgX8&h z?t{5(dTt&q*{SSw_T1e0YO4PYV+moryDRP;y)KHUZi@ZEUu;o~m=9HNCzlzEi`Jnu zJ1))*MOjpQHgwq*qtz4Q_0W!IpSJ!H1)O!WF4oSR_;V{_H}#QDN_+Kn%G8XL<S|I% z6p0jx(<J&y(1Vp97FXZDsh`2=#j1N`QpKzmN2fZZCnG>Fi9zvTG=yoq99<I~BO3dn zIy3f!v5>f(42UxmT`Vl7CO&L42pb_WAnr_LYUk+_zfY9#o&PwUI7|S1qySbgnHy{6 rl}!ZRN_&ks`6NjUlb~lbPdVk^BQc921{h{R3}(XiVec)6;WYjOzrj^9 diff --git a/pyKADMOS/MDOvisualization.py b/pyKADMOS/MDOvisualization.py index b9ae12057..c861f3e3a 100644 --- a/pyKADMOS/MDOvisualization.py +++ b/pyKADMOS/MDOvisualization.py @@ -272,58 +272,89 @@ def create_XDSM(PSG, filename): PSG_process = PSG['process flow'] PSG_data = PSG['data flow'] - # add diagonal components in order from up to down - # all 'EMPTY' heading name component is used for Input and output, the component will not be shown. - ad('EMPTY', 'Analysis', '') - - print '' - print 'NODE CHECK' - for node,data in PSG_process.nodes_iter(data=True): - print node - print data - loc_idx1 = 0 - loc_idx2 = 0 + # Add diagonal components in order from up to down + # Add analysis blocks for idx in range(0,PSG_process.graph['number_of_diagonal_blocks']): - print idx node_list = find_all_nodes(PSG_process, attr_cond=['diagonal_position','==',idx]) - print node_list assert len(node_list)==1, "Somehow, a unique diagonal position '%d' could not be found in the PSG process" \ " graph." % idx node = node_list[0] - if PSG_process.node[node]['subcategory'] == 'optimizer': - node_name = 'opt' + if PSG_process.node[node]['subcategory'] == 'initiator': + node_style = 'Initiator' + node_text = '$'+str(PSG_process.node[node]['process_step'])+','+\ + str(PSG_process.node[node]['converger_step'])+'$:\\'+PSG_process.node[node]['label'] + elif PSG_process.node[node]['subcategory'] == 'optimizer': node_style = 'Optimization' - node_text = r'Optimization' + node_text = '$'+str(PSG_process.node[node]['process_step'])+','+\ + str(PSG_process.node[node]['converger_step'])+'\to'+\ + str(PSG_process.node[node]['process_step']+1)+'$:\\'+PSG_process.node[node]['label'] elif PSG_process.node[node]['subcategory'] == 'MDA': - node_name = 'mda' node_style = 'MDA' - node_text = r'MDA' + node_text = '$'+str(PSG_process.node[node]['process_step'])+','+\ + str(PSG_process.node[node]['converger_step'])+'\to'+\ + str(PSG_process.node[node]['process_step']+1)+'$:\\'+PSG_process.node[node]['label'] elif PSG_process.node[node]['subcategory'] == 'MDA analysis': - node_name = 'ana'+str(loc_idx1) node_style = 'Analysis' - node_text = PSG_process.node[node]['label'].encode('string-escape') - loc_idx1 += 1 + node_text = '$' + str(PSG_process.node[node]['process_step']) + '$:\\' + PSG_process.node[node]['label'] elif PSG_process.node[node]['subcategory'] == 'optimizer function': - node_name = 'fun'+str(loc_idx2) node_style = 'Function' - node_text = PSG_process.node[node]['label'].encode('string-escape') - loc_idx2 += 1 + node_text = '$' + str(PSG_process.node[node]['process_step']) + '$:\\' + PSG_process.node[node]['label'] else: raise AssertionError('PSG node category not as expected.') - ad(node_name, node_style, ('$0,3\to 1$:\\'+node_text).encode('string-escape')) - - dsm.addChain(['opt', 'mda', 'ana0', 'ana1', 'mda', 'fun0', 'opt']) # TODO, make generic based on PSG - dsm.addChain(['mda', 'fun1', 'opt']) # TODO, make generic based on PSG - dsm.addChain(['mda', 'fun2', 'opt']) # TODO, make generic based on PSG - - # TODO, add correct process numbering based on PSG - - # TODO, add final design variables and initial guess design variables (including chain) - - # TODO: add data flow! + ad(node, node_style, node_text.encode('string-escape')) + + # Add process chain lines to the XDSM + for edge in PSG_process.edges_iter(): + # Add line between two blocks that are on the diagonal + if len(set(edge).intersection(set(find_all_nodes(PSG_process,category='architecture element', + subcategory='all PSG blocks')))) == 2: + dsm.addChain([edge[0], edge[1]]) + + # Determine connected diagonal blocks and add data dependency + for idx1 in range(0, PSG_process.graph['number_of_diagonal_blocks']-1): + for idx2 in range(idx1+1, PSG_process.graph['number_of_diagonal_blocks']): + # Find first diagonal node + node_list = find_all_nodes(PSG_data, attr_cond=['diagonal_position', '==', idx1]) + assert len(node_list) == 1, "Somehow, a unique diagonal position '%d' could not be found in the PSG process" \ + " graph." % idx1 + node1 = node_list[0] + # Find second diagonal node + node_list = find_all_nodes(PSG_data, attr_cond=['diagonal_position', '==', idx2]) + assert len(node_list) == 1, "Somehow, a unique diagonal position '%d' could not be found in the PSG process" \ + " graph." % idx2 + node2 = node_list[0] + node1_out = map((lambda x: x[1]),PSG_data.out_edges(node1)) + node1_in = map((lambda x: x[0]),PSG_data.in_edges(node1)) + node2_out = map((lambda x: x[1]),PSG_data.out_edges(node2)) + node2_in = map((lambda x: x[0]),PSG_data.in_edges(node2)) + + # Determine intersection between outputs and inputs + node_set_upp = set(node1_out).intersection(set(node2_in)) + node_set_low = set(node1_in).intersection(set(node2_out)) + + # Determine data type for visualization + if node1 == 'Initiator': + data_type = 'DataIO' + else: + data_type = 'DataInter' + + + # Upper triangle of XDSM + if node_set_upp: + str_num = str(PSG_process.node[node2]['process_step']) + ': ' + str_upp = ', '.join(map(str, map((lambda x: '$' + PSG_data.node[x]['label'] + '$'), node_set_upp))) + co(node2, node1, data_type, (str_num+str_upp).encode('string-escape')) + + # Lower triangle of XDSM + if node_set_low: + # Check existence of process edge and add edge number if it exists + str_num = (str(PSG_process.node[node1]['converger_step']) + ': ') \ + if ('converger_step' in PSG_process.node[node1]) \ + else (str(PSG_process.node[node1]['process_step']) + ': ') + str_low = ', '.join(map(str, map((lambda x: '$' + PSG_data.node[x]['label'] + '$'), node_set_low))) + co(node1, node2, data_type, (str_num+str_low).encode('string-escape')) # TODO: update documentation and possible node categories - # TODO: reconsider automatic copying of node attributes in PSG creation # output tex file and compile it dsm.write(filename.encode('string-escape'), compilepdf=True) \ No newline at end of file diff --git a/pyKADMOS/MDOvisualization.pyc b/pyKADMOS/MDOvisualization.pyc index 8eb607ac9a09a0ca752c45a767ba2203a4164bb5..69b73546f01a20ce557179d7f02ff3dcb5ed2ead 100644 GIT binary patch delta 2911 zcmb_e&2Jk;6o0d8JF#OsUruaO(mHJ@rcGP9O)07nYDGjT5-oC6MbK2%*0XWfacpOI zLQ}M>rKF-MC!|#+4oF-$AjAQL#2F9=j&R}3e^3ej0p5G|x{lk>79sD<zVG*&nfGS> zd;723Vo3ixmH6q0+IK^L96y=|fCLU5hXXMH1+WcpPrzLPs{*8ej{!Ul*<kp@e*Yf8 z)_qN(A_{H<>Ke!x<hM0gyyj_M6qHV4IRtVTWE|Wm)O6Su!i#~5fEz;^WCGSSaPEVO zf*c{6X_S5>NR46h-Vle5fjb0wnZ%JI2RkODp9T*DkAm7|GlmcZWaT(ycPl2kib=>4 z+HS}U<g;EJn%{~(A?2CkJf8?Ty+<1V33;-E01z22H_PZA4`O~0M2<nEHJN)9gpc8# zxY+*y;;X?O&ohV>O+L2^gdc8U2;%W;dT%h?J`VS_CZFFG?&+c>xlm@PbbP83jS9mZ z1~(3MEQbB0*w#U8lwo;mjZ?>|h!?M211~{!rxM^M$gDm>bhk(kfGhykmz+hFMnU+I z2N~?2+78+$$&reZUJ3B?HI2-~#-AEK%Uhp6(hF#n<9_&1^G0CnCK<RR<jf`5*DzN# z50|FH4)it5$leX}qpti;$BYbiOzM$1$-UzYMY@fb91N2Nl>&JP?f`+Rr@>9}rfA?{ z%c07j3w5J?x-r(h5US8E9lDLP>Tsw+ubygxk7blBJICTqu$KUDl2v1Us_~A>2QNd3 zWtz|E*NA)(yeVkn#Ze@}odo;U=)*f8-Rl?m5@fw;kVl}-aM1=AbQk!NJ4%-v`r^6K zg9x(V;!VaI;9}TmaIvfE!+uz95fDvu$$;(Yaw07E6y(=pV7L1apa}JJZ4iQHuJ7g| zRi}^s72G_7%P_Jl9dtQHmtue&bU8xT2X4dD@mbzj(U+-=$HB!pG?2$Y(OwH70hWr# zzrS1hQUq5|{p?#!OIe0$*(#17go`~+AUCIyIJfOq)pVSSqs%r|Ho&|}<6Lbu-#6`= zX|uwi&&k}`l`=))P_4GI)~ydrn}b~LaE7v4O-DnUcnkXgVD|0B^A2Ufcfn{Hja!c8 zs9_YG?=peEkPE(8SnyLQbd+s1YsXBdYP8MrDoHXp8FuxCrOc|@w9SIqFxSndatNf+ zXcXRAx=^^@XjRu7ixO992{edV!r@Rh7duiweyK>(OBU&iIG{*Wc^aqSPG%)IHx_;E z4HP+~d#Xre*dHmlovCn`3(pj05Ku47o6i(xFEsweFpP?!&7z@<i<kKrnQSW4=2JUc z;MaViw{|+jNgPfVC)~mvyhV6B^HRf)E=saXMKZcn_HgF<=xpi&vf=jPAu`D)j|Wzf zh#)X#mT9YucSCUhbJj5bPVn1!<-qkY3w|%Cyw}@S!)(jdA}y~R2~M0o=aa^iHPfkJ zx!L72$Z~mGyhB)kSl+w_L(1207$~NtuN&=7OKhqNd$Wnv>@pEFskhKJio{JDBbQGh zRiuAv?2jA59;?A;rw<1YPEYw|+C0YDY)KP4@K(d*6wE4fOW`-L1C<F&Zk0mfB<CT+ zQja>>b1qd{n~JlsMFn9|OA~Xlr&{l@sH4^;rs9~Yve|C$7BpHn*_%$YqHeWKyo0e+ zlwE0VuJ>qi3+3q1=@#n4G8Pk*H-iVIE5WBPPx)KOf{2SzF{&j*A~GZPiJU-6WJOGS zi)Ov{a26$^MM+DF8GTZlMcae=teDlhUf~;~@K48CPl~t}i^NcJL>$s%`f;X?M)6_@ TB4>VyeS;8+!0mVJmAQWaWZn*> delta 1244 zcmah{%}*Ow5dX~@Y_G8~5HL72i9={)wMoO5psHFW5uik>@*#tiL?t3CzlAI{Yr{Si zh<4?quKID_O6{eGO0CpumHY)g^;D@B&iNCf<jSEl4{$6l(dx~|Z+<iLcHX>sPX9Gh ziMP4T!C3XL)cz+Q=K-YoB=`hBTYv^yz>mQ9z#2gjz5^nQ-8g;aY%}UcXhC&DC81Ji zB|xlh+*D~6yB{I!!UkvA&=%LBg@*;KScsB{QV5gG35C7&823~LQ5qs`?EXSJA-1G< zLG_^6vas;*8AXg`I74$^4m7h+IjCL%*Ar+FMLh_6gpd^7;@)|DZ6SCAor3BUVu8_b zNW$Eq$aj%0X}L~O_465!gzYk^Q;4|!AR=zTvKRiV6Wpd6GUR1a1w$S(WR^^Rd4jBl z4fjt{BhWU&v|MjkTJSh>o#Y~l8yTq6Lf}fw<iD8X@%WEAY5iyx)u<_YK<Wci)NU6& z^PZyiVNn}?*39OtWXfDDgjt0A&*u>KVz_-1dEBi(aPJ3TgJ*XNs^CJEpw6=eH73wH z?*M_0D2!e(s60(4I(`D>euQ=-^`Ti8B2vIo`QnS$Gr!XWKRK{?>+bRcEgO2>cWQfq z7x04es%BW+zO%4cn!mX?|7Ar8@lUgVH|q`UZF*1LZQdt<J)LEJ=MZ(YSNBce*1~n8 zH<c3zf&G$m+(0tfso1Q8oCv+``RkY6pz1W-V1SW!o6_2jUu~CNqn$YW>Fi1mQ^qGQ zP22U-<oIVRx{H0TIB{%D8iP|05jNV$l$Kws);Ako&26Z)vRt4d1u9b_rsMt3uZ_t6 zI!etyc0AwA>B+XI-Euzu_KUfu1n(~0SXGX8Dl?KKh#6w7US0Ln?qsJkWhTKW?<nBc zmAhKwF~9SCXVW#eGO<AK)!cVM?e6L_=b=n2Dm(lReYvH$|LV|J_XQ@K@|3qSl<DfT zx~ZGa@v$k%-x;<>`HT=pY1m+PhwfwKH02mMvaBqfx5lVIh4{Ct|0I8vu85xxuEzgf G8~-0g()5Y| diff --git a/pyKADMOS/PyXDSM/.gitignore b/pyKADMOS/PyXDSM/.gitignore deleted file mode 100755 index 08f41ee6a..000000000 --- a/pyKADMOS/PyXDSM/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -*.*~ -*.aux -*.log -*.pdf -*.swp -.rope*/ - diff --git a/pyKADMOS/PyXDSM/Example/IDF.py b/pyKADMOS/PyXDSM/Example/IDF.py deleted file mode 100755 index bca44b3ed..000000000 --- a/pyKADMOS/PyXDSM/Example/IDF.py +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env python2 -#-*- coding:utf-8 -*- -# speicify XDSM_writer code path -import sys -sys.path.append('../XDSM_writer') - -from XDSM_writer import XDSM - - -def make_IDF_XDSM(): - - dsm = XDSM() - ad = lambda *args, **kargs: dsm.addComp(*args, **kargs) - co = lambda *args, **kargs: dsm.addDep(*args, **kargs) - - # add diagnol (Component) in order from up to down - - ad('EMPTY', 'Analysis', '') - #all 'EMPTY' heading name component is used for Input and output, - # the component will not be shown, - # here used for upper input and left output - ad('opt', 'Optimization', r'$0,3\to 1$:\\Optimization') - ad('ana', 'Analysis, stack', r'$1$\\Analysis $i$') - ad('fun', 'Function', r'$2$\\Functions') - - #add dependency variables, here order free - co('opt', 'EMPTY', 'DataInter', - r'$\mathbf{x}^{(0)}, \hat{\mathbf{y}}^{(0)}$') - co('EMPTY', 'opt', 'DataInter', - r'$x^*$') - co('ana', 'opt', 'DataInter', - r'$1:\mathbf{x}_0, \mathbf{x}_i, \hat{\mathbf{y}}_{j\neq i}$') - co('EMPTY', 'ana', 'DataInter,stack', - r'$\mathbf{y}_i^*$') - co('fun', 'opt', 'DataInter', - r'$2:\mathbf{x}, \hat{\mathbf{y}}$') - co('fun', 'ana', 'DataInter, stack', - r'$2:\mathbf{y}_i$') - co('opt', 'fun', 'DataInter', - '$3:f_0,\mathbf{c}, \mathbf{c}^c$') - - # component name from start to the end in turn - dsm.addChain([ - 'opt-EMPTY', 'opt', 'ana', 'fun', 'opt', 'EMPTY-opt']) - #the dependency node using "downstream_component-upstream_component" - - # output tex file and compile it - dsm.write(r'IDF.pdf', compilepdf=True) - -if __name__ == '__main__': - make_IDF_XDSM() - - - diff --git a/pyKADMOS/PyXDSM/ReadMe.md b/pyKADMOS/PyXDSM/ReadMe.md deleted file mode 100755 index 6a3a42b94..000000000 --- a/pyKADMOS/PyXDSM/ReadMe.md +++ /dev/null @@ -1,43 +0,0 @@ -##Extended Design Structure Matrix (XDSM) -###python and Tex code of generation utitlity - -#### Requirement: - -* Python 2.7.X -* newest TexLive or other latex suite (need Xetex-relevant pacakges) - - -##### Feature(Compared with original version): - -1. add input-ouput node generation() -2. add chain line support(addChain method) -3. Chinese support based on Xetex, (using XDSMCJK) - -Detals can be refered from the source code and example file. - - -Any question contact: - - -> greatcwmine AT gmail DOT com - - ----------- -This code is a modified version from - - -> http://mdolab.engin.umich.edu/content/xdsm-overview - -licensed by: -> The XDSM LaTeX source and generator files are provided as-is and free of charge. Users are free to download, modify, and redistribute the software as they please, provided this notice remains. - - -> If you use the XDSM format for research, we ask that you cite the following journal publication in your work: - - -> A. B. Lambe and J. R. R. A. Martins, “Extensions to the Design Structure Matrix for the Description of Multidisciplinary Design, Analysis, and Optimization Processesâ€, Structural and Multidisciplinary Optimization, vol. 46, no. 2, p. 273-284, 2012. - - - -Thank A. B. Lambe, J. R. R. A. Martins for developing and sharing - diff --git a/pyKADMOS/PyXDSM/XDSM/XDSM.py b/pyKADMOS/PyXDSM/XDSM/XDSM.py deleted file mode 100755 index 9dd07765a..000000000 --- a/pyKADMOS/PyXDSM/XDSM/XDSM.py +++ /dev/null @@ -1,283 +0,0 @@ -""" -XDSM tex source writer utility. Three methods: -1. addComp(name, style, string, stack=False) - name: [string] label of the component - style: [string] Tikz block style, defined in diagram_styles.tex - string: [string] name of the component that appears in the pdf - stack: [boolean] adds the stack option -2. addDep(out, inp, style, string, stack=False) - out: [string] label of the component that depends on the variable - inp: [string] label of the component that computes the variable - style: [string] Tikz block style, defined in diagram_styles.tex - string: [string] name of the variable that appears in the pdf - stack: [boolean] adds the stack option -3. write(filename, compilepdf=False) - filename: [string] write to filename+'.pdf' - compilepdf: [string] whether to run pdflatex on the tex file -4. addChain( chain_node_list) - list the chain in consequence - -XDSMCJK - add Chinese supporting using xetex and xeCJK package - the interface is the same as XDSM - the characters in latex file need using UTF-8 encoding - except ANSI characters - -Original author: - A.B.Labme lambe@utias.utoronto.ca -Modified By: - David Chen greatcwmine@gmail.com - -""" - - -class XDSM(object): - - """ original XDSM_writer graphic class """ - - def __init__(self, xdsm_path=None): - """ - xdsm_path : the XDSM_writer tex style file directory path, - default is path of the same folder of XDSM_writer.py """ - self.inds = {} - self.comps = [] - self.deps = [] - self.chains = [] - - if xdsm_path: - self._xdsm_path = xdsm_path - else: - import os - self._xdsm_path = os.path.dirname(os.path.abspath(__file__)) - - def _is_empty_comp(self, name): - """ define empty node rule """ - if name[:5] == 'EMPTY': - return True - else: - return False - - def addComp(self, name, style, string, stack=False): - """ addComp(name, style, string, stack=False) - name: [string] label of the component - using EMPTY heading keywort to specify EMPTY node - (e.g. overall inputs and outpus) - style: [string] Tikz block style, defined in diagram_styles.tex - string: [string] name of the component that appears in the pdf - stack: [boolean] adds the stack option - """ - self.inds[name] = len(self.comps) - self.comps.append([name, style, string, stack]) - - def addDep(self, out, inp, style, string, stack=False): - """ addDep(out, inp, style, string, stack=False) - out: [string] label of the component that depends on the variable - inp: [string] label of the component that computes the variable - style: [string] Tikz block style, defined in diagram_styles.tex - string: [string] name of the variable that appears in the pdf - stack: [boolean] adds the stack option - """ - - self.deps.append([out, inp, style, string, stack]) - - def addChain(self, chain_list): - """ set the process chain list """ - if len(chain_list) < 2: - raise ValueError('the process chain has 2 elements at least') - self.chains.append(chain_list) - - def getCmds(self): - """ generate the XDSM_writer matrix node""" - def write(i, j, name, style, string, stack): - M[i][j] = ' \\node' - M[i][j] += ' [' + style + (',stack]' if stack else ']') - M[i][j] += ' (' + name + ')' - M[i][j] += ' {' + string + '};' - M[i][j] += ' &\n' if j < n - 1 \ - else (' \\\\\n %Row ' + str(i+2) + '\n') - - n = len(self.comps) - - inds = self.inds - - names = [[None for j in range(n)] - for i in range(n)] - - for name, style, string, stack in self.comps: - names[inds[name]][inds[name]] = name - for out, inp, style, string, stack in self.deps: - names[inds[inp]][inds[out]] = out+'-'+inp - - M = [ - [(' &\n' if j < n - 1 else ' \\\\\n') for j in range(n)] - for i in range(n)] - for name, style, string, stack in self.comps: - # skip EMPTY* component - if not self._is_empty_comp(name): - write(inds[name], inds[name], name, style, string, stack) - - for out, inp, style, string, stack in self.deps: - write(inds[inp], inds[out], out+'-'+inp, style, string, stack) - - H = ['' for i in range(n)] - for i in range(n): - minj = i - maxj = i - for out, inp, style, string, stack in self.deps: - j = inds[out] - if inds[inp] is i and not self._is_empty_comp(inp): - minj = j if j < minj else minj - maxj = j if j > maxj else maxj - if minj is not maxj: - H[i] = ' ' - H[i] += ' (' + names[i][minj] + ')' - H[i] += ' edge [DataLine]' - H[i] += ' (' + names[i][maxj] + ')\n' - - V = ['' for jj in range(n)] - for j in range(n): - mini = j - maxi = j - for out, inp, style, string, stack in self.deps: - i = inds[inp] - if inds[out] is j and not self._is_empty_comp(out): - mini = i if i < mini else mini - maxi = i if i > maxi else maxi - if mini is not maxi: - V[j] = ' ' - V[j] += ' (' + names[mini][j] + ')' - V[j] += ' edge [DataLine]' - V[j] += ' (' + names[maxi][j] + ')\n' - - return M, H, V - - def _write_construction(self, fun_w): - """ write the XDSM_writer construction code - Args: - fun_w: closure function fun_w(string) to write string to stream - Return: None - """ - n = len(self.comps) - M, H, V = self.getCmds() - w = lambda s: fun_w(s+'\n') - import os - xpath = self._xdsm_path.replace('\\', r'/') - - w('\\usepackage{geometry}') - w('\\usepackage{amsfonts}') - w('\\usepackage{amsmath}') - w('\\usepackage{amssymb}') - w('\\usepackage{tikz}') - w('') - w('\\input{%s/diagram_border}' % xpath) - w('') - w('\\begin{document}') - w('') - w('\\input{%s/diagram_styles}' % xpath) - w('') - w('\\begin{tikzpicture}') - w('') - - w(' \\matrix[MatrixSetup]') - w(' {') - w(' %Row 1') - for i in range(n): - for j in range(n): - fun_w(M[i][j]) - w(' };') - w('') - # for the chain process - if self.chains: - w(r' % XDSM_writer process chains ') - for i, chn in enumerate(self.chains): - w(r' { [start chain=process]') - w(r' \begin{pgfonlayer}{process}') - w(r' \chainin (%s);' % chn[0]) - last_node = chn[0] - for e in chn[1:]: - if '-' in e or '-' in last_node: - w(r' \chainin (%s) [join=by ProcessTip];' % e) - else: - w(r' \chainin (%s) [join=by ProcessHV];' % e) - - last_node = e - w(r' \end{pgfonlayer}') - w(r' }') - w('') - - w(' \\begin{pgfonlayer}{data}') - w(' \\path') - w(' % Horizontal edges') - for i in range(n): - fun_w(H[i]) - w(' % Vertical edges') - for j in range(n): - fun_w(V[j]) - w(' ;') - w(' \\end{pgfonlayer}') - - w('') - w('\\end{tikzpicture}') - w('') - w('\\end{document}') - - def write(self, filename, compilepdf=False): - """ generate latex code """ - - f = open(filename+'.tex', 'w') - w = lambda s: f.write(s+'\n') - - w('\\documentclass{article}') - - self._write_construction(f.write) - - f.close() - - if compilepdf: - self.compilepdf(filename) - - def compilepdf(self, filename): - """ make using pdflatex to compile the tex file""" - import os - os.system('pdflatex ' + filename + '.tex') - - -class XDSMCJK(XDSM): - - """ XDSM_writer class with Chinese based on xetex and xeCJK package""" - - def write(self, filename, compilepdf=False): - """ generate xatex code """ - import codecs - w = lambda s: f.write(s+'\n') - f = codecs.open(filename+'.tex', 'w', 'utf-8') - - w(r'%# -*- coding:utf-8 -*-') - w('\\documentclass{article}') - w('\\usepackage{xeCJK}') - w('\\setCJKmainfont{SimSun}') - w('\\setmainfont{Times New Roman}') - - self._write_construction(f.write) - - f.close() - - if compilepdf: - self.compilepdf(filename) - - def compilepdf(self, filename): - filename = filename.strip() - if filename[-3:] == '.tex': - filename = filename[:-3] - import os - cmd = 'xelatex ' + filename + '.tex' - dirname = os.path.dirname(filename) - if dirname: - cmd += ' -output-directory="%s"' % dirname - ret = os.system(cmd) - # open it to preview - if ret == 0: - if os.name == 'posix': # *nix - os.system('xdg-open' + filename + '.pdf') - elif os.name == 'nt': # windows - os.system(filename.replace('/', '\\') + '.pdf') diff --git a/pyKADMOS/PyXDSM/XDSM/__init__.py b/pyKADMOS/PyXDSM/XDSM/__init__.py deleted file mode 100755 index e69de29bb..000000000 diff --git a/pyKADMOS/PyXDSM/XDSM/diagram_border.tex b/pyKADMOS/PyXDSM/XDSM/diagram_border.tex deleted file mode 100755 index 611663598..000000000 --- a/pyKADMOS/PyXDSM/XDSM/diagram_border.tex +++ /dev/null @@ -1,10 +0,0 @@ -% Define the set of tikz packages to be included in the architecture diagram document - -\usetikzlibrary{arrows,chains,positioning,scopes,shapes.geometric,shapes.misc,shadows} - -% Set the border around all of the architecture diagrams to be tight to the diagrams themselves -% (i.e. no longer need to tinker with page size parameters) - -\usepackage[active,tightpage]{preview} -\PreviewEnvironment{tikzpicture} -\setlength{\PreviewBorder}{5pt} diff --git a/pyKADMOS/PyXDSM/XDSM/diagram_styles.tex b/pyKADMOS/PyXDSM/XDSM/diagram_styles.tex deleted file mode 100755 index 95073e865..000000000 --- a/pyKADMOS/PyXDSM/XDSM/diagram_styles.tex +++ /dev/null @@ -1,109 +0,0 @@ -% Define all the styles used to produce XDSMs for MDO - -% Component types -\tikzstyle{Optimization} = [rounded rectangle,draw,fill=blue!20,inner sep=6pt,minimum height=1cm,text badly centered,align=center] -\tikzstyle{ConvergeCheck} = [rounded rectangle,draw,fill=lime!20,inner sep=6pt,minimum height=1cm,text badly centered,align=center] -\tikzstyle{LP_Optimization} = [rectangle,draw,fill=blue!20,inner sep=6pt,minimum height=1cm,text badly centered,align=center] -\tikzstyle{Analysis} = [rectangle,draw,fill=green!20,inner sep=6pt,minimum height=1cm,text badly centered,align=center] -\tikzstyle{Function} = [rectangle,draw,fill=purple!20,inner sep=6pt,minimum height=1cm,text badly centered,align=center] -\tikzstyle{MDA} = [rounded rectangle,draw,fill=orange!20,inner sep=6pt,minimum height=1cm,text badly centered,align=center] -\tikzstyle{Metamodel} = [rectangle,draw,fill=yellow!20,inner sep=6pt,minimum height=1cm,text badly centered,align=center] -\tikzstyle{DOE} = [rounded rectangle,draw,fill=yellow!20,inner sep=6pt,minimum height=1cm,text badly centered,align=center] -%\tikzstyle{OptFunction} = [rectangle,draw,fill=red!20,inner sep=6pt,minimum height=1cm,text badly centered] - -%% A simple command to give the repeated structure look for components and data -\tikzstyle{stack} = [double copy shadow] - -%% A simple command to fade components and data, e.g. demonstrating a sequence of steps in an animation -\tikzstyle{faded} = [draw=black!50,fill=white,text opacity=0.5] - -%% Simple fading commands for the lines -\tikzstyle{fadeddata} = [color=black!20] -\tikzstyle{fadedprocess} = [color=black!50] - -% **OLD** Component types for repeated structures (i.e. for parallel structures) -%\tikzstyle{Optimization_i} = [double copy shadow, Optimization] -%\tikzstyle{LP_Optimization_i} = [double copy shadow, LP_Optimization] -%\tikzstyle{Analysis_i} = [double copy shadow, Analysis] -%\tikzstyle{Function_i} = [double copy shadow, Function] -%\tikzstyle{MDA_i} = [double copy shadow, MDA] -%\tikzstyle{Metamodel_i} = [double copy shadow, Metamodel] -%\tikzstyle{DOE_i} = [double copy shadow, DOE] - -% **OLD** Faded component types for, e.g. demonstrations of each step. We use these style definitions to "gray out" large parts of the diagram. -%\tikzstyle{Optimization_fade} = [Optimization,fill=blue!10,draw=black!30,text opacity=0.3] -%\tikzstyle{Analysis_fade} = [Analysis,fill=green!10,draw=black!30,text opacity=0.3] -%\tikzstyle{Function_fade} = [Function,fill=purple!10,draw=black!30,text opacity=0.3] -%\tikzstyle{MDA_fade} = [MDA,fill=orange!10,draw=black!30,text opacity=0.3] -%\tikzstyle{Metamodel_fade} = [Metamodel,fill=yellow!10,draw=black!30,text opacity=0.3] -%\tikzstyle{DOE_fade} = [DOE,fill=yellow!10,draw=black!30,text opacity=0.3] -% -%\tikzstyle{Optimization_i_fade} = [Optimization_i,fill=blue!10,draw=black!30,text opacity=0.3] -%\tikzstyle{Analysis_i_fade} = [Analysis_i,fill=green!10,draw=black!30,text opacity=0.3] -%\tikzstyle{Function_i_fade} = [Function_i,fill=purple!10,draw=black!30,text opacity=0.3] -%\tikzstyle{MDA_i_fade} = [MDA_i,fill=orange!10,draw=black!30,text opacity=0.3] -%\tikzstyle{Metamodel_i_fade} = [Metamodel_i,fill=yellow!10,draw=black!30,text opacity=0.3] -%\tikzstyle{DOE_i_fade} = [DOE_i,fill=yellow!10,draw=black!30,text opacity=0.3] - -% Data types -\tikzstyle{DataInter} = [trapezium,trapezium left angle=75,trapezium right angle=105,draw,fill=black!10,align=center] -\tikzstyle{DataIO} = [trapezium,trapezium left angle=75,trapezium right angle=105,draw,fill=white,align=center] - -% **OLD** Data types for repeated structures -%\tikzstyle{DataInter_i} = [double copy shadow, DataInter] -%\tikzstyle{DataIO_i} = [double copy shadow, DataIO] - -% **OLD** Faded data types -%\tikzstyle{DataInter_fade} = [DataInter,draw=black!30,fill=white,text opacity=0.3] -%\tikzstyle{DataIO_fade} = [DataIO_i,draw=black!30,fill=white,text opacity=0.3] -% -%\tikzstyle{DataInter_i_fade} = [DataInter_i,draw=black!30,fill=white,text opacity=0.3] -%\tikzstyle{DataIO_i_fade} = [DataIO_i,draw=black!30,fill=white,text opacity=0.3] - -% Edges -\tikzstyle{DataLine} = [color=black!40,line width=5pt] -\tikzstyle{ProcessHV} = [-,line width=1pt,to path={-| (\tikztotarget)}] -\tikzstyle{ProcessTip} = [-,line width=1pt] - -% **OLD** Faded edges -%\tikzstyle{DataLine_fade} = [DataLine,color=black!10] -%\tikzstyle{ProcessHV_fade} = [ProcessHV,color=black!30] -%\tikzstyle{ProcessTip_fade} = [ProcessTip,color=black!30] - -% Matrix options -\tikzstyle{MatrixSetup} = [row sep=3mm, column sep=2mm] - -% Declare a background layer for showing node connections -\pgfdeclarelayer{data} -\pgfdeclarelayer{process} -\pgfsetlayers{data,process,main} - -% A new command to split the component text over multiple lines -\newcommand{\MultilineComponent}[3] -{ - \begin{minipage}{#1} - \begin{center} - #2 \linebreak #3 - \end{center} - \end{minipage} -} - -% A new command to split the component text over multiple columns -\newcommand{\MultiColumnComponent}[5] -{ - \begin{minipage}{#1} - \begin{center} - #2 \linebreak #3 - \end{center} - \begin{minipage}{0.49\textwidth} - \begin{center} - #4 - \end{center} - \end{minipage} - \begin{minipage}{0.49\textwidth} - \begin{center} - #5 - \end{center} - \end{minipage} - \end{minipage} -} diff --git a/pyKADMOS/XDSM_writer/diagram_styles.tex b/pyKADMOS/XDSM_writer/diagram_styles.tex index 95073e865..a48d1939a 100755 --- a/pyKADMOS/XDSM_writer/diagram_styles.tex +++ b/pyKADMOS/XDSM_writer/diagram_styles.tex @@ -6,6 +6,7 @@ \tikzstyle{LP_Optimization} = [rectangle,draw,fill=blue!20,inner sep=6pt,minimum height=1cm,text badly centered,align=center] \tikzstyle{Analysis} = [rectangle,draw,fill=green!20,inner sep=6pt,minimum height=1cm,text badly centered,align=center] \tikzstyle{Function} = [rectangle,draw,fill=purple!20,inner sep=6pt,minimum height=1cm,text badly centered,align=center] +\tikzstyle{Initiator} = [rectangle,draw,fill=white!20,inner sep=6pt,minimum height=1cm,text badly centered,align=center] \tikzstyle{MDA} = [rounded rectangle,draw,fill=orange!20,inner sep=6pt,minimum height=1cm,text badly centered,align=center] \tikzstyle{Metamodel} = [rectangle,draw,fill=yellow!20,inner sep=6pt,minimum height=1cm,text badly centered,align=center] \tikzstyle{DOE} = [rounded rectangle,draw,fill=yellow!20,inner sep=6pt,minimum height=1cm,text badly centered,align=center] diff --git a/pyKADMOS/sellarProblem.py b/pyKADMOS/sellarProblem.py index d2f8acc30..79e3dc135 100644 --- a/pyKADMOS/sellarProblem.py +++ b/pyKADMOS/sellarProblem.py @@ -71,13 +71,6 @@ for node, data in MCG.nodes_iter(data=True): MCG_part = sellarProblem.get_partitioned_graph(MCG,3,output='Graph',recursive=False, contig=True)#,tpwgts=[0.5,0.2,0.3]) plot_graph(MCG_part, 9, color_setting='partitions', fig_size=fig_size, show_now=False) -# all_nodes = find_all_nodes(function_graph_D12, category='all', subcategory='all', -# print_in_log=True, attr_cond=['shape','==','o'], -# print_attributes=['label', 'shape', 'execution time']) -# -# print 'all nodes' -# pp.pprint(all_nodes) - # Get the PSG for an MDF approach with Gauss-Seidel FPG_MDF = MCG.copy() @@ -85,7 +78,7 @@ find_all_nodes(FPG_MDF, print_in_log=True) FPG_MDF.node['/data_schema/geometry/z1']['PSG role'] = 'design variable' FPG_MDF.node['/data_schema/geometry/z2']['PSG role'] = 'design variable' -FPG_MDF.node['/data_schema/geometry/x1']['PSG role'] = 'design variable' +#FPG_MDF.node['/data_schema/geometry/x1']['PSG role'] = 'design variable' FPG_MDF.node['/data_schema/analyses/g1']['PSG role'] = 'constraint' FPG_MDF.node['/data_schema/analyses/g2']['PSG role'] = 'constraint' FPG_MDF.node['/data_schema/analyses/f']['PSG role'] = 'objective' @@ -93,9 +86,9 @@ FPG_MDF.node['/data_schema/analyses/f']['PSG role'] = 'objective' MDA_type = 'Gauss-Seidel' analysis_order = ['D1','D2'] - PSG = sellarProblem.get_PSG_for_MDF(FPG_MDF, MDA_type, analysis_order) plot_graph(PSG['process flow'], 10, color_setting='default', fig_size=fig_size, show_now=False) +plot_graph(PSG['data flow'], 11, color_setting='default', fig_size=fig_size, show_now=False) create_XDSM(PSG,'testXDSM') \ No newline at end of file diff --git a/pyKADMOS/testXDSM.log b/pyKADMOS/testXDSM.log index c5dfda67c..660f971da 100644 --- a/pyKADMOS/testXDSM.log +++ b/pyKADMOS/testXDSM.log @@ -1,4 +1,4 @@ -This is pdfTeX, Version 3.14159265-2.6-1.40.16 (TeX Live 2015) (preloaded format=pdflatex 2015.10.20) 17 JUN 2016 00:06 +This is pdfTeX, Version 3.14159265-2.6-1.40.16 (TeX Live 2015) (preloaded format=pdflatex 2015.10.20) 20 JUN 2016 15:41 entering extended mode restricted \write18 enabled. %&-line parsing enabled. @@ -618,16 +618,16 @@ styles.tex \pgf@layerbox@process=\box43 \pgf@layerboxsaved@process=\box44 ) -LaTeX Font Info: Try loading font information for U+msa on input line 28. +LaTeX Font Info: Try loading font information for U+msa on input line 19. (/usr/local/texlive/2015/texmf-dist/tex/latex/amsfonts/umsa.fd File: umsa.fd 2013/01/14 v3.01 AMS symbols A ) -LaTeX Font Info: Try loading font information for U+msb on input line 28. +LaTeX Font Info: Try loading font information for U+msb on input line 19. (/usr/local/texlive/2015/texmf-dist/tex/latex/amsfonts/umsb.fd File: umsb.fd 2013/01/14 v3.01 AMS symbols B ) -Overfull \hbox (1.18648pt too wide) in paragraph at lines 122--122 +Overfull \hbox (19.64833pt too wide) in paragraph at lines 195--195 [][] [] @@ -635,21 +635,24 @@ Preview: Tightpage -327680 -327680 327680 327680 [1{/usr/local/texlive/2015/texmf-var/fonts/map/pdftex/updmap/pdftex.map}] (./testXDSM.aux) ) Here is how much of TeX's memory you used: - 14355 strings out of 493089 - 292890 string characters out of 6134841 - 336955 words of memory out of 5000000 - 17556 multiletter control sequences out of 15000+600000 + 14579 strings out of 493089 + 298143 string characters out of 6134841 + 357592 words of memory out of 5000000 + 17780 multiletter control sequences out of 15000+600000 5339 words of font info for 22 fonts, out of 8000000 for 9000 1141 hyphenation exceptions out of 8191 55i,15n,82p,428b,952s stack positions out of 5000i,500n,10000p,200000b,80000s </usr/local/texlive/2015/texmf-dist/fonts/type1/public/amsfon ts/cm/cmmi10.pfb></usr/local/texlive/2015/texmf-dist/fonts/type1/public/amsfont -s/cm/cmr10.pfb></usr/local/texlive/2015/texmf-dist/fonts/type1/public/amsfonts/ -cm/cmsy10.pfb> -Output written on testXDSM.pdf (1 page, 31166 bytes). +s/cm/cmmi7.pfb></usr/local/texlive/2015/texmf-dist/fonts/type1/public/amsfonts/ +cm/cmr10.pfb></usr/local/texlive/2015/texmf-dist/fonts/type1/public/amsfonts/cm +/cmr7.pfb></usr/local/texlive/2015/texmf-dist/fonts/type1/public/amsfonts/cm/cm +sy10.pfb></usr/local/texlive/2015/texmf-dist/fonts/type1/public/amsfonts/cm/cms +y7.pfb> +Output written on testXDSM.pdf (1 page, 55483 bytes). PDF statistics: - 47 PDF objects out of 1000 (max. 8388607) - 24 compressed objects within 1 object stream + 59 PDF objects out of 1000 (max. 8388607) + 33 compressed objects within 1 object stream 0 named destinations out of 1000 (max. 500000) 109 words of extra memory for PDF output out of 10000 (max. 10000000) diff --git a/pyKADMOS/testXDSM.pdf b/pyKADMOS/testXDSM.pdf index 71d2b6162eab6508c525ea2c775ab6b542895ab0..1f3d18b71b694779c00ca0ae62cc5574684e5676 100644 GIT binary patch delta 46545 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 delta 22189 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 D$KP?D diff --git a/pyKADMOS/testXDSM.tex b/pyKADMOS/testXDSM.tex index 36788681e..7d6ecc23e 100644 --- a/pyKADMOS/testXDSM.tex +++ b/pyKADMOS/testXDSM.tex @@ -16,106 +16,179 @@ \matrix[MatrixSetup] { %Row 1 + \node [Initiator] (Initiator) {$0,8$:\\INI}; & + \node [DataIO] (Optimizer-Initiator) {1: $z1^0$, $z2^0$}; & + \node [DataIO] (MDA-Initiator) {2: $y2^{c0}$}; & + \node [DataIO] (D1-Initiator) {3: $x1$}; & & - & - & - & - & - & + \node [DataIO] (F-Initiator) {6: $x1$}; & & \\ + \node [DataIO] (Initiator-Optimizer) {8: $z1^*$, $z2^*$}; & + \node [Optimization] (Optimizer) {$1,7\to2$:\\OPT}; & & - \node [Optimization] (opt) {$0,3\to 1$:\\Optimization}; & - & - & - & - & + \node [DataInter] (D1-Optimizer) {3: $z2$, $z1$}; & + \node [DataInter] (D2-Optimizer) {4: $z2$, $z1$}; & + \node [DataInter] (F-Optimizer) {6: $z2$}; & & \\ & & - \node [MDA] (mda) {$0,3\to 1$:\\MDA}; & - & + \node [MDA] (MDA) {$2,5\to3$:\\MDA}; & + \node [DataInter] (D1-MDA) {3: $y2^c$}; & & & & \\ + \node [DataIO] (Initiator-D1) {8: $y1^*$}; & & & + \node [Analysis] (D1) {$3$:\\D1}; & + \node [DataInter] (D2-D1) {4: $y1$}; & + \node [DataInter] (F-D1) {6: $y1$}; & & - \node [Analysis] (ana0) {$0,3\to 1$:\\D1}; & - & + \node [DataInter] (G1-D1) {6: $y1$}; \\ + %Row 5 + \node [DataIO] (Initiator-D2) {8: $y2^*$}; & & + \node [DataInter] (MDA-D2) {5: $y2$}; & & + \node [Analysis] (D2) {$4$:\\D2}; & + \node [DataInter] (F-D2) {6: $y2$}; & + \node [DataInter] (G2-D2) {6: $y2$}; & \\ & + \node [DataInter] (Optimizer-F) {7: $f$}; & & & & - \node [Analysis] (ana1) {$0,3\to 1$:\\D2}; & - & + \node [Function] (F) {$6$:\\F}; & & \\ & + \node [DataInter] (Optimizer-G2) {7: $g2$}; & & & & & - \node [Function] (fun0) {$0,3\to 1$:\\G2}; & - & + \node [Function] (G2) {$6$:\\G2}; & \\ & + \node [DataInter] (Optimizer-G1) {7: $g1$}; & & & & & & - \node [Function] (fun1) {$0,3\to 1$:\\G1}; & - \\ - & - & - & - & - & - & - & - \node [Function] (fun2) {$0,3\to 1$:\\F}; \\ + \node [Function] (G1) {$6$:\\G1}; \\ %Row 9 }; % XDSM_writer process chains { [start chain=process] \begin{pgfonlayer}{process} - \chainin (opt); - \chainin (mda) [join=by ProcessHV]; - \chainin (ana0) [join=by ProcessHV]; - \chainin (ana1) [join=by ProcessHV]; - \chainin (mda) [join=by ProcessHV]; - \chainin (fun0) [join=by ProcessHV]; - \chainin (opt) [join=by ProcessHV]; + \chainin (Initiator); + \chainin (Optimizer) [join=by ProcessHV]; + \end{pgfonlayer} + } + + { [start chain=process] + \begin{pgfonlayer}{process} + \chainin (Optimizer); + \chainin (Initiator) [join=by ProcessHV]; + \end{pgfonlayer} + } + + { [start chain=process] + \begin{pgfonlayer}{process} + \chainin (Optimizer); + \chainin (MDA) [join=by ProcessHV]; + \end{pgfonlayer} + } + + { [start chain=process] + \begin{pgfonlayer}{process} + \chainin (G2); + \chainin (Optimizer) [join=by ProcessHV]; + \end{pgfonlayer} + } + + { [start chain=process] + \begin{pgfonlayer}{process} + \chainin (G1); + \chainin (Optimizer) [join=by ProcessHV]; + \end{pgfonlayer} + } + + { [start chain=process] + \begin{pgfonlayer}{process} + \chainin (F); + \chainin (Optimizer) [join=by ProcessHV]; + \end{pgfonlayer} + } + + { [start chain=process] + \begin{pgfonlayer}{process} + \chainin (MDA); + \chainin (F) [join=by ProcessHV]; + \end{pgfonlayer} + } + + { [start chain=process] + \begin{pgfonlayer}{process} + \chainin (MDA); + \chainin (G2) [join=by ProcessHV]; + \end{pgfonlayer} + } + + { [start chain=process] + \begin{pgfonlayer}{process} + \chainin (MDA); + \chainin (G1) [join=by ProcessHV]; + \end{pgfonlayer} + } + + { [start chain=process] + \begin{pgfonlayer}{process} + \chainin (MDA); + \chainin (D1) [join=by ProcessHV]; \end{pgfonlayer} } { [start chain=process] \begin{pgfonlayer}{process} - \chainin (mda); - \chainin (fun1) [join=by ProcessHV]; - \chainin (opt) [join=by ProcessHV]; + \chainin (D2); + \chainin (MDA) [join=by ProcessHV]; \end{pgfonlayer} } { [start chain=process] \begin{pgfonlayer}{process} - \chainin (mda); - \chainin (fun2) [join=by ProcessHV]; - \chainin (opt) [join=by ProcessHV]; + \chainin (D1); + \chainin (D2) [join=by ProcessHV]; \end{pgfonlayer} } \begin{pgfonlayer}{data} \path % Horizontal edges + (Initiator) edge [DataLine] (F-Initiator) + (Initiator-Optimizer) edge [DataLine] (F-Optimizer) + (MDA) edge [DataLine] (D1-MDA) + (Initiator-D1) edge [DataLine] (G1-D1) + (Initiator-D2) edge [DataLine] (G2-D2) + (Optimizer-F) edge [DataLine] (F) + (Optimizer-G2) edge [DataLine] (G2) + (Optimizer-G1) edge [DataLine] (G1) % Vertical edges + (Initiator) edge [DataLine] (Initiator-D2) + (Optimizer-Initiator) edge [DataLine] (Optimizer-G1) + (MDA-Initiator) edge [DataLine] (MDA-D2) + (D1-Initiator) edge [DataLine] (D1) + (D2-Optimizer) edge [DataLine] (D2) + (F-Initiator) edge [DataLine] (F) + (G2-D2) edge [DataLine] (G2) + (G1-D1) edge [DataLine] (G1) ; \end{pgfonlayer} -- GitLab