@mat3ra/wode 2025.10.1-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (252) hide show
  1. package/.babelrc +17 -0
  2. package/LICENSE.md +15 -0
  3. package/README.md +164 -0
  4. package/assets/subworkflows/deepmd/deepmd.yml +31 -0
  5. package/assets/subworkflows/deepmd/espresso_cp_md.yml +16 -0
  6. package/assets/subworkflows/espresso/average_electrostatic_potential_find_minima.yml +27 -0
  7. package/assets/subworkflows/espresso/average_electrostatic_potential_via_band_structure.yml +67 -0
  8. package/assets/subworkflows/espresso/band_gap.yml +21 -0
  9. package/assets/subworkflows/espresso/band_gap_hse_dos.yml +30 -0
  10. package/assets/subworkflows/espresso/band_structure.yml +26 -0
  11. package/assets/subworkflows/espresso/band_structure_dos.yml +34 -0
  12. package/assets/subworkflows/espresso/band_structure_hse.yml +30 -0
  13. package/assets/subworkflows/espresso/band_structure_magn.yml +31 -0
  14. package/assets/subworkflows/espresso/band_structure_soc.yml +30 -0
  15. package/assets/subworkflows/espresso/dielectric_tensor.yml +35 -0
  16. package/assets/subworkflows/espresso/dos.yml +24 -0
  17. package/assets/subworkflows/espresso/electronic_density_mesh.yml +19 -0
  18. package/assets/subworkflows/espresso/esm.yml +14 -0
  19. package/assets/subworkflows/espresso/esm_relax.yml +14 -0
  20. package/assets/subworkflows/espresso/espresso_extract_kpoints.yml +16 -0
  21. package/assets/subworkflows/espresso/espresso_xml_get_qpt_irr.yml +12 -0
  22. package/assets/subworkflows/espresso/fixed_cell_relaxation.yml +16 -0
  23. package/assets/subworkflows/espresso/gw_band_structure_band_gap_full_frequency.yml +22 -0
  24. package/assets/subworkflows/espresso/gw_band_structure_band_gap_plasmon_pole.yml +22 -0
  25. package/assets/subworkflows/espresso/hubbard_u_hp.yml +21 -0
  26. package/assets/subworkflows/espresso/kpoint_convergence.yml +86 -0
  27. package/assets/subworkflows/espresso/neb.yml +16 -0
  28. package/assets/subworkflows/espresso/ph_init_qpoints.yml +14 -0
  29. package/assets/subworkflows/espresso/ph_single_irr_qpt.yml +14 -0
  30. package/assets/subworkflows/espresso/phonon_dispersions.yml +29 -0
  31. package/assets/subworkflows/espresso/phonon_dos.yml +29 -0
  32. package/assets/subworkflows/espresso/phonon_dos_dispersion.yml +34 -0
  33. package/assets/subworkflows/espresso/phonon_reduce.yml +29 -0
  34. package/assets/subworkflows/espresso/post_processor.yml +14 -0
  35. package/assets/subworkflows/espresso/pre_processor.yml +14 -0
  36. package/assets/subworkflows/espresso/pw_scf.yml +16 -0
  37. package/assets/subworkflows/espresso/recalculate_bands.yml +19 -0
  38. package/assets/subworkflows/espresso/surface_energy.yml +16 -0
  39. package/assets/subworkflows/espresso/total_energy.yml +16 -0
  40. package/assets/subworkflows/espresso/valence_band_offset_calc_from_previous_esp_vbm.yml +35 -0
  41. package/assets/subworkflows/espresso/variable_cell_relaxation.yml +18 -0
  42. package/assets/subworkflows/espresso/zero_point_energy.yml +19 -0
  43. package/assets/subworkflows/jupyterLab/jupyter_notebook.yml +17 -0
  44. package/assets/subworkflows/nwchem/total_energy.yml +16 -0
  45. package/assets/subworkflows/python/ml/classification_tail.yml +56 -0
  46. package/assets/subworkflows/python/ml/clustering_tail.yml +62 -0
  47. package/assets/subworkflows/python/ml/regression_tail.yml +56 -0
  48. package/assets/subworkflows/python/ml/train_head.yml +61 -0
  49. package/assets/subworkflows/python/python_script.yml +14 -0
  50. package/assets/subworkflows/shell/batch_espresso_pwscf.yml +14 -0
  51. package/assets/subworkflows/shell/hello_world.yml +14 -0
  52. package/assets/subworkflows/vasp/band_gap.yml +21 -0
  53. package/assets/subworkflows/vasp/band_structure.yml +21 -0
  54. package/assets/subworkflows/vasp/band_structure_dos.yml +23 -0
  55. package/assets/subworkflows/vasp/dos.yml +18 -0
  56. package/assets/subworkflows/vasp/fixed_cell_relaxation.yml +16 -0
  57. package/assets/subworkflows/vasp/initial_final_total_energies.yml +25 -0
  58. package/assets/subworkflows/vasp/kpoint_convergence.yml +89 -0
  59. package/assets/subworkflows/vasp/neb_subworkflow.yml +16 -0
  60. package/assets/subworkflows/vasp/prepare_images.yml +16 -0
  61. package/assets/subworkflows/vasp/recalculate_bands.yml +16 -0
  62. package/assets/subworkflows/vasp/surface_energy.yml +18 -0
  63. package/assets/subworkflows/vasp/total_energy.yml +16 -0
  64. package/assets/subworkflows/vasp/variable_cell_relaxation.yml +18 -0
  65. package/assets/subworkflows/vasp/zero_point_energy.yml +16 -0
  66. package/assets/workflows/deepmd/deepmd_md.yml +6 -0
  67. package/assets/workflows/espresso/band_gap.yml +4 -0
  68. package/assets/workflows/espresso/band_gap_dos_hse.yml +4 -0
  69. package/assets/workflows/espresso/band_structure.yml +4 -0
  70. package/assets/workflows/espresso/band_structure_dos.yml +4 -0
  71. package/assets/workflows/espresso/band_structure_hse.yml +14 -0
  72. package/assets/workflows/espresso/band_structure_magn.yml +7 -0
  73. package/assets/workflows/espresso/band_structure_soc.yml +7 -0
  74. package/assets/workflows/espresso/dielectric_tensor.yml +4 -0
  75. package/assets/workflows/espresso/dos.yml +4 -0
  76. package/assets/workflows/espresso/electronic_density_mesh.yml +4 -0
  77. package/assets/workflows/espresso/esm.yml +4 -0
  78. package/assets/workflows/espresso/esm_relax.yml +4 -0
  79. package/assets/workflows/espresso/fixed_cell_relaxation.yml +4 -0
  80. package/assets/workflows/espresso/gw_band_structure_band_gap_full_frequency.yml +4 -0
  81. package/assets/workflows/espresso/gw_band_structure_band_gap_plasmon_pole.yml +4 -0
  82. package/assets/workflows/espresso/hubbard_u_hp.yml +7 -0
  83. package/assets/workflows/espresso/kpoint_convergence.yml +4 -0
  84. package/assets/workflows/espresso/neb.yml +4 -0
  85. package/assets/workflows/espresso/phonon_dispersions.yml +4 -0
  86. package/assets/workflows/espresso/phonon_dos.yml +4 -0
  87. package/assets/workflows/espresso/phonon_dos_dispersion.yml +4 -0
  88. package/assets/workflows/espresso/phonon_map.yml +28 -0
  89. package/assets/workflows/espresso/recalculate_bands.yml +4 -0
  90. package/assets/workflows/espresso/surface_energy.yml +4 -0
  91. package/assets/workflows/espresso/total_energy.yml +4 -0
  92. package/assets/workflows/espresso/valence_band_offset.yml +171 -0
  93. package/assets/workflows/espresso/variable_cell_relaxation.yml +4 -0
  94. package/assets/workflows/espresso/zero_point_energy.yml +4 -0
  95. package/assets/workflows/jupyterLab/jupyter_notebook.yml +4 -0
  96. package/assets/workflows/nwchem/total_energy.yml +4 -0
  97. package/assets/workflows/python/ml/classification_workflow.yml +9 -0
  98. package/assets/workflows/python/ml/clustering_workflow.yml +9 -0
  99. package/assets/workflows/python/ml/regression_workflow.yml +9 -0
  100. package/assets/workflows/python/python_script.yml +4 -0
  101. package/assets/workflows/shell/batch_espresso_pwscf.yml +4 -0
  102. package/assets/workflows/shell/hello_world.yml +4 -0
  103. package/assets/workflows/vasp/band_gap.yml +4 -0
  104. package/assets/workflows/vasp/band_structure.yml +4 -0
  105. package/assets/workflows/vasp/band_structure_dos.yml +4 -0
  106. package/assets/workflows/vasp/dos.yml +4 -0
  107. package/assets/workflows/vasp/fixed_cell_relaxation.yml +4 -0
  108. package/assets/workflows/vasp/kpoint_convergence.yml +4 -0
  109. package/assets/workflows/vasp/neb.yml +8 -0
  110. package/assets/workflows/vasp/recalculate_bands.yml +4 -0
  111. package/assets/workflows/vasp/surface_energy.yml +4 -0
  112. package/assets/workflows/vasp/total_energy.yml +4 -0
  113. package/assets/workflows/vasp/variable_cell_relaxation.yml +4 -0
  114. package/assets/workflows/vasp/zero_point_energy.yml +4 -0
  115. package/build_workflows.js +65 -0
  116. package/dist/context/context.js +49 -0
  117. package/dist/context/mixins/ApplicationContextMixin.js +19 -0
  118. package/dist/context/mixins/JobContextMixin.js +39 -0
  119. package/dist/context/mixins/MaterialContextMixin.js +40 -0
  120. package/dist/context/mixins/MaterialsContextMixin.js +19 -0
  121. package/dist/context/mixins/MaterialsSetContextMixin.js +25 -0
  122. package/dist/context/mixins/MethodDataContextMixin.js +48 -0
  123. package/dist/context/mixins/WorkflowContextMixin.js +28 -0
  124. package/dist/context/providers/BoundaryConditionsFormDataProvider.js +86 -0
  125. package/dist/context/providers/CollinearMagnetizationContextProvider.js +113 -0
  126. package/dist/context/providers/HubbardContextProviderLegacy.js +81 -0
  127. package/dist/context/providers/HubbardJContextProvider.js +74 -0
  128. package/dist/context/providers/HubbardUContextProvider.js +77 -0
  129. package/dist/context/providers/HubbardVContextProvider.js +104 -0
  130. package/dist/context/providers/IonDynamicsContextProvider.js +62 -0
  131. package/dist/context/providers/MLSettingsContextProvider.js +52 -0
  132. package/dist/context/providers/MLTrainTestSplitContextProvider.js +48 -0
  133. package/dist/context/providers/NEBFormDataProvider.js +38 -0
  134. package/dist/context/providers/NonCollinearMagnetizationContextProvider.js +253 -0
  135. package/dist/context/providers/PlanewaveCutoffsContextProvider.js +67 -0
  136. package/dist/context/providers/PointsGridFormDataProvider.js +272 -0
  137. package/dist/context/providers/PointsPathFormDataProvider.js +155 -0
  138. package/dist/context/providers/by_application/ExecutableContextProvider.js +17 -0
  139. package/dist/context/providers/by_application/espresso/QENEBContextProvider.js +60 -0
  140. package/dist/context/providers/by_application/espresso/QEPWXContextProvider.js +149 -0
  141. package/dist/context/providers/by_application/nwchem/NWChemTotalEnergyContextProvider.js +84 -0
  142. package/dist/context/providers/by_application/vasp/VASPContextProvider.js +64 -0
  143. package/dist/context/providers/by_application/vasp/VASPNEBContextProvider.js +56 -0
  144. package/dist/context/providers/settings.js +37 -0
  145. package/dist/context/providers.js +199 -0
  146. package/dist/enums.js +65 -0
  147. package/dist/index.js +64 -0
  148. package/dist/patch.js +19 -0
  149. package/dist/subworkflows/convergence/factory.js +35 -0
  150. package/dist/subworkflows/convergence/non_uniform_kgrid.js +31 -0
  151. package/dist/subworkflows/convergence/parameter.js +70 -0
  152. package/dist/subworkflows/convergence/uniform_kgrid.js +26 -0
  153. package/dist/subworkflows/convergence.js +189 -0
  154. package/dist/subworkflows/create.js +285 -0
  155. package/dist/subworkflows/dynamic/espresso/getQpointIrrep.js +34 -0
  156. package/dist/subworkflows/dynamic/index.js +19 -0
  157. package/dist/subworkflows/dynamic/surfaceEnergy.js +67 -0
  158. package/dist/subworkflows/index.js +19 -0
  159. package/dist/subworkflows/subworkflow.js +279 -0
  160. package/dist/units/assertion.js +37 -0
  161. package/dist/units/assignment.js +42 -0
  162. package/dist/units/base.js +91 -0
  163. package/dist/units/builders/AssertionUnitConfigBuilder.js +34 -0
  164. package/dist/units/builders/AssignmentUnitConfigBuilder.js +41 -0
  165. package/dist/units/builders/ExecutionUnitConfigBuilder.js +67 -0
  166. package/dist/units/builders/IOUnitConfigBuilder.js +54 -0
  167. package/dist/units/builders/UnitConfigBuilder.js +79 -0
  168. package/dist/units/builders/index.js +18 -0
  169. package/dist/units/condition.js +52 -0
  170. package/dist/units/execution.js +222 -0
  171. package/dist/units/factory.js +53 -0
  172. package/dist/units/index.js +82 -0
  173. package/dist/units/io.js +148 -0
  174. package/dist/units/map.js +38 -0
  175. package/dist/units/processing.js +41 -0
  176. package/dist/units/reduce.js +24 -0
  177. package/dist/units/subworkflow.js +23 -0
  178. package/dist/utils.js +92 -0
  179. package/dist/workflows/create.js +312 -0
  180. package/dist/workflows/default.js +41 -0
  181. package/dist/workflows/index.js +108 -0
  182. package/dist/workflows/relaxation.js +37 -0
  183. package/dist/workflows/workflow.js +303 -0
  184. package/package.json +94 -0
  185. package/src/context/context.js +47 -0
  186. package/src/context/mixins/ApplicationContextMixin.js +19 -0
  187. package/src/context/mixins/JobContextMixin.js +36 -0
  188. package/src/context/mixins/MaterialContextMixin.js +41 -0
  189. package/src/context/mixins/MaterialsContextMixin.js +18 -0
  190. package/src/context/mixins/MaterialsSetContextMixin.js +24 -0
  191. package/src/context/mixins/MethodDataContextMixin.js +48 -0
  192. package/src/context/mixins/WorkflowContextMixin.js +25 -0
  193. package/src/context/providers/BoundaryConditionsFormDataProvider.js +80 -0
  194. package/src/context/providers/CollinearMagnetizationContextProvider.js +117 -0
  195. package/src/context/providers/HubbardContextProviderLegacy.js +75 -0
  196. package/src/context/providers/HubbardJContextProvider.js +73 -0
  197. package/src/context/providers/HubbardUContextProvider.js +100 -0
  198. package/src/context/providers/HubbardVContextProvider.js +111 -0
  199. package/src/context/providers/IonDynamicsContextProvider.js +56 -0
  200. package/src/context/providers/MLSettingsContextProvider.js +48 -0
  201. package/src/context/providers/MLTrainTestSplitContextProvider.js +45 -0
  202. package/src/context/providers/NEBFormDataProvider.js +32 -0
  203. package/src/context/providers/NonCollinearMagnetizationContextProvider.js +269 -0
  204. package/src/context/providers/PlanewaveCutoffsContextProvider.js +68 -0
  205. package/src/context/providers/PointsGridFormDataProvider.js +285 -0
  206. package/src/context/providers/PointsPathFormDataProvider.js +165 -0
  207. package/src/context/providers/by_application/ExecutableContextProvider.js +10 -0
  208. package/src/context/providers/by_application/espresso/QENEBContextProvider.js +56 -0
  209. package/src/context/providers/by_application/espresso/QEPWXContextProvider.js +166 -0
  210. package/src/context/providers/by_application/nwchem/NWChemTotalEnergyContextProvider.js +86 -0
  211. package/src/context/providers/by_application/vasp/VASPContextProvider.js +56 -0
  212. package/src/context/providers/by_application/vasp/VASPNEBContextProvider.js +46 -0
  213. package/src/context/providers/settings.js +38 -0
  214. package/src/context/providers.js +140 -0
  215. package/src/enums.js +65 -0
  216. package/src/index.js +17 -0
  217. package/src/patch.js +12 -0
  218. package/src/subworkflows/convergence/factory.js +14 -0
  219. package/src/subworkflows/convergence/non_uniform_kgrid.js +28 -0
  220. package/src/subworkflows/convergence/parameter.js +58 -0
  221. package/src/subworkflows/convergence/uniform_kgrid.js +22 -0
  222. package/src/subworkflows/convergence.js +196 -0
  223. package/src/subworkflows/create.js +201 -0
  224. package/src/subworkflows/dynamic/espresso/getQpointIrrep.js +35 -0
  225. package/src/subworkflows/dynamic/index.js +8 -0
  226. package/src/subworkflows/dynamic/surfaceEnergy.js +124 -0
  227. package/src/subworkflows/index.js +2 -0
  228. package/src/subworkflows/subworkflow.js +329 -0
  229. package/src/units/assertion.js +29 -0
  230. package/src/units/assignment.js +34 -0
  231. package/src/units/base.js +97 -0
  232. package/src/units/builders/AssertionUnitConfigBuilder.js +28 -0
  233. package/src/units/builders/AssignmentUnitConfigBuilder.js +36 -0
  234. package/src/units/builders/ExecutionUnitConfigBuilder.js +59 -0
  235. package/src/units/builders/IOUnitConfigBuilder.js +53 -0
  236. package/src/units/builders/UnitConfigBuilder.js +86 -0
  237. package/src/units/builders/index.js +15 -0
  238. package/src/units/condition.js +47 -0
  239. package/src/units/execution.js +263 -0
  240. package/src/units/factory.js +53 -0
  241. package/src/units/index.js +25 -0
  242. package/src/units/io.js +163 -0
  243. package/src/units/map.js +33 -0
  244. package/src/units/processing.js +39 -0
  245. package/src/units/reduce.js +17 -0
  246. package/src/units/subworkflow.js +15 -0
  247. package/src/utils.js +73 -0
  248. package/src/workflows/create.js +222 -0
  249. package/src/workflows/default.js +39 -0
  250. package/src/workflows/index.js +99 -0
  251. package/src/workflows/relaxation.js +41 -0
  252. package/src/workflows/workflow.js +351 -0
@@ -0,0 +1,201 @@
1
+ import ApplicationRegistry from "@exabyte-io/ade.js/dist/js/ApplicationRegistry";
2
+ import {
3
+ default_methods as MethodConfigs,
4
+ default_models as ModelConfigs,
5
+ MethodFactory,
6
+ ModelFactory,
7
+ } from "@exabyte-io/mode.js";
8
+ import { workflowSubforkflowMapByApplication } from "@mat3ra/standata";
9
+ import _ from "lodash";
10
+
11
+ import { UnitFactory } from "../units";
12
+ import { builders } from "../units/builders";
13
+ import { applyConfig } from "../utils";
14
+ import { dynamicSubworkflowsByApp, getSurfaceEnergySubworkflowUnits } from "./dynamic";
15
+ import { Subworkflow } from "./subworkflow";
16
+
17
+ // NOTE: DFTModel => DFTModelConfig, configs should have the same name as the model/method class + "Config" at the end
18
+ function _getConfigFromModelOrMethodName(name, kind) {
19
+ const configs = kind === "Model" ? ModelConfigs : MethodConfigs;
20
+ if (!configs[`${name}Config`]) {
21
+ // eslint-disable-next-line no-param-reassign
22
+ name = `Unknown${kind}`;
23
+ }
24
+ return configs[`${name}Config`];
25
+ }
26
+
27
+ /**
28
+ * @summary Create model from subworkflow data
29
+ * @param config {Object} model config
30
+ * @param modelFactoryCls {any} model factory to use
31
+ * @returns {DFTModel|Model}
32
+ */
33
+ function createModel({ config, modelFactoryCls }) {
34
+ const { name, config: modelConfig = {} } = config;
35
+ const defaultConfig = _getConfigFromModelOrMethodName(name, "Model");
36
+ return modelFactoryCls.create({ ...defaultConfig, ...modelConfig });
37
+ }
38
+
39
+ /**
40
+ * @summary Create method from subworkflow data
41
+ * @param config {Object} method configuration
42
+ * @param methodFactoryCls {any}
43
+ * @returns {{method, setSearchText}}
44
+ */
45
+ function createMethod({ config, methodFactoryCls }) {
46
+ const { name, setSearchText = null, config: methodConfig = {} } = config;
47
+ const defaultConfig = _getConfigFromModelOrMethodName(name, "Method");
48
+ const method = methodFactoryCls.create({ ...defaultConfig, ...methodConfig });
49
+ return { method, setSearchText };
50
+ }
51
+
52
+ /**
53
+ * @summary Create top-level objects used in subworkflow initialization
54
+ * @param subworkflowData {Object} subworkflow data
55
+ * @param AppRegistry
56
+ * @param modelFactoryCls {any} model factory class
57
+ * @param methodFactoryCls {any} method factory class
58
+ * @returns {{application: *, method: *, model: (DFTModel|Model), setSearchText: String|null}}
59
+ */
60
+ function createTopLevel({ subworkflowData, modelFactoryCls, methodFactoryCls, AppRegistry }) {
61
+ const { application: appConfig, model: modelConfig, method: methodConfig } = subworkflowData;
62
+ const application = AppRegistry.createApplication(appConfig);
63
+ const model = createModel({ config: modelConfig, modelFactoryCls });
64
+ const { method, setSearchText } = createMethod({ config: methodConfig, methodFactoryCls });
65
+ return {
66
+ application,
67
+ model,
68
+ method,
69
+ setSearchText,
70
+ };
71
+ }
72
+
73
+ /**
74
+ * @summary Create workflow unit from JSON configuration
75
+ * Supports applying functions to the builder prior to building via "functions"
76
+ * Supports applying attributes to the builder after building via "attributes"
77
+ * @param config {Object} unit config
78
+ * @param application {*} application
79
+ * @param unitBuilders {Object} workflow unit builders
80
+ * @param unitFactoryCls {*} workflow unit class factory
81
+ * @returns {*|{head: boolean, preProcessors: [], postProcessors: [], name: *, flowchartId: *, type: *, results: [], monitors: []}}
82
+ */
83
+ export function createUnit({ config, application, unitBuilders, unitFactoryCls }) {
84
+ const { type, config: unitConfig } = config;
85
+ if (type === "executionBuilder") {
86
+ const { name, execName, flavorName, flowchartId } = unitConfig;
87
+ const builder = new unitBuilders.ExecutionUnitConfigBuilder(
88
+ name,
89
+ application,
90
+ execName,
91
+ flavorName,
92
+ flowchartId,
93
+ );
94
+
95
+ // config should contain "functions" and "attributes"
96
+ const cfg = applyConfig({ obj: builder, config, callBuild: true });
97
+ return unitFactoryCls.create(cfg);
98
+ }
99
+
100
+ return unitFactoryCls.create({ type, ...unitConfig });
101
+ }
102
+
103
+ /**
104
+ * @summary Dynamically create subworkflow units
105
+ * @param dynamicSubworkflow {String} name of unit creation function
106
+ * @param units {Array} configured units to provide to dynamic unit creation
107
+ * @param unitBuilders {Object} unit configuration builders
108
+ * @param unitFactoryCls {*} unit factory class
109
+ * @param application {*} application (optional)
110
+ * @returns {*}
111
+ */
112
+ function createDynamicUnits({
113
+ dynamicSubworkflow,
114
+ units,
115
+ unitBuilders,
116
+ unitFactoryCls,
117
+ application = null,
118
+ }) {
119
+ const { name, subfolder } = dynamicSubworkflow;
120
+ const func = subfolder && _.get(dynamicSubworkflowsByApp, `${subfolder}.${name}`, () => {});
121
+ switch (name) {
122
+ case "surfaceEnergy":
123
+ // eslint-disable-next-line no-case-declarations
124
+ const [scfUnit] = units;
125
+ return getSurfaceEnergySubworkflowUnits({ scfUnit, unitBuilders });
126
+ case "getQpointIrrep":
127
+ return func({ unitBuilders, unitFactoryCls, application });
128
+ default:
129
+ throw new Error(`dynamicSubworkflow=${name} not recognized`);
130
+ }
131
+ }
132
+
133
+ function createSubworkflow({
134
+ subworkflowData,
135
+ AppRegistry = ApplicationRegistry,
136
+ modelFactoryCls = ModelFactory,
137
+ methodFactoryCls = MethodFactory,
138
+ subworkflowCls = Subworkflow,
139
+ unitFactoryCls = UnitFactory,
140
+ unitBuilders = builders,
141
+ }) {
142
+ const { application, model, method, setSearchText } = createTopLevel({
143
+ subworkflowData,
144
+ AppRegistry,
145
+ modelFactoryCls,
146
+ methodFactoryCls,
147
+ });
148
+
149
+ let units = [];
150
+ const { name, units: unitConfigs, config = {}, dynamicSubworkflow = null } = subworkflowData;
151
+ unitConfigs.forEach((_config) => {
152
+ units.push(
153
+ createUnit({
154
+ config: _config,
155
+ application,
156
+ unitBuilders,
157
+ unitFactoryCls,
158
+ }),
159
+ );
160
+ });
161
+ if (dynamicSubworkflow) {
162
+ units = createDynamicUnits({
163
+ dynamicSubworkflow,
164
+ units,
165
+ unitBuilders,
166
+ unitFactoryCls,
167
+ application,
168
+ });
169
+ }
170
+
171
+ const { functions = {}, attributes = {}, ...cfg } = config;
172
+ let subworkflow = subworkflowCls.fromArguments(application, model, method, name, units, cfg);
173
+ subworkflow = applyConfig({ obj: subworkflow, config: { functions, attributes } });
174
+ if (setSearchText) subworkflow.model.method.setSearchText(setSearchText);
175
+ return subworkflow;
176
+ }
177
+
178
+ /**
179
+ * @summary Convenience wrapper around createSubworkflow to create by app name and swf name
180
+ * @param appName {String} application name
181
+ * @param swfName {String} subworkflow name (snake_case.yml)
182
+ * @param workflowSubworkflowMapByApplication {Object} object containing all workflow/subworkflow map by application
183
+ * @param swArgs {Object} classes for instantiation
184
+ * @returns {*} subworkflow object
185
+ */
186
+ function createSubworkflowByName({
187
+ appName,
188
+ swfName,
189
+ workflowSubworkflowMapByApplication = workflowSubforkflowMapByApplication,
190
+ ...swArgs
191
+ }) {
192
+ const { subworkflows } = workflowSubworkflowMapByApplication;
193
+ const { [appName]: allSubworkflowData } = subworkflows;
194
+ const { [swfName]: subworkflowData } = allSubworkflowData;
195
+ return createSubworkflow({
196
+ subworkflowData,
197
+ ...swArgs,
198
+ });
199
+ }
200
+
201
+ export { createSubworkflow, createSubworkflowByName };
@@ -0,0 +1,35 @@
1
+ import { UNIT_TYPES } from "../../../enums";
2
+
3
+ /**
4
+ * @summary Get QptIrr units used in phonon map calculations
5
+ * @param unitBuilders {Object} unit builders
6
+ * @param unitFactoryCls {*} unit factory class
7
+ * @param application {*} application instance
8
+ * @returns {[{head: boolean, preProcessors: [], postProcessors: [], name: *, flowchartId: *, type: *, results: [], monitors: []},*]}
9
+ */
10
+ function getQpointIrrep({ unitBuilders, unitFactoryCls, application }) {
11
+ const { ExecutionUnitConfigBuilder } = unitBuilders;
12
+
13
+ const pythonUnit = new ExecutionUnitConfigBuilder(
14
+ "python",
15
+ application,
16
+ "python",
17
+ "espresso_xml_get_qpt_irr",
18
+ ).build();
19
+
20
+ const assignmentUnit = unitFactoryCls.create({
21
+ type: UNIT_TYPES.assignment,
22
+ input: [
23
+ {
24
+ scope: pythonUnit.flowchartId,
25
+ name: "STDOUT",
26
+ },
27
+ ],
28
+ operand: "Q_POINTS",
29
+ value: "json.loads(STDOUT)",
30
+ });
31
+
32
+ return [pythonUnit, assignmentUnit];
33
+ }
34
+
35
+ export { getQpointIrrep };
@@ -0,0 +1,8 @@
1
+ import { getQpointIrrep } from "./espresso/getQpointIrrep";
2
+ import { getSurfaceEnergySubworkflowUnits } from "./surfaceEnergy";
3
+
4
+ const dynamicSubworkflowsByApp = {
5
+ espresso: { getQpointIrrep },
6
+ };
7
+
8
+ export { getSurfaceEnergySubworkflowUnits, dynamicSubworkflowsByApp };
@@ -0,0 +1,124 @@
1
+ import { Utils } from "@mat3ra/utils";
2
+
3
+ function getIOUnitEndpointOptions(query, projection = "{}") {
4
+ return {
5
+ params: {
6
+ query,
7
+ projection,
8
+ },
9
+ };
10
+ }
11
+
12
+ function getAssignmentUnitInput(unit, name) {
13
+ return [
14
+ {
15
+ name,
16
+ scope: unit.flowchartId,
17
+ },
18
+ ];
19
+ }
20
+
21
+ function getSurfaceEnergySubworkflowUnits({ scfUnit, unitBuilders }) {
22
+ const { IOUnitConfigBuilder, AssignmentUnitConfigBuilder, AssertionUnitConfigBuilder } =
23
+ unitBuilders;
24
+
25
+ let input, endpointOptions;
26
+ endpointOptions = getIOUnitEndpointOptions("{'_id': MATERIAL_ID}");
27
+ const getSlabUnit = new IOUnitConfigBuilder("io-slab", "materials", endpointOptions).build();
28
+
29
+ input = getAssignmentUnitInput(getSlabUnit, "DATA");
30
+ const setSlabUnit = new AssignmentUnitConfigBuilder("slab", "SLAB", "DATA[0]", input).build();
31
+
32
+ endpointOptions = getIOUnitEndpointOptions("{'_id': SLAB.metadata.bulkId}");
33
+ const getBulkUnit = new IOUnitConfigBuilder("io-bulk", "materials", endpointOptions).build();
34
+
35
+ const BULKValue = "DATA[0] if DATA else None";
36
+ input = getAssignmentUnitInput(getBulkUnit, "DATA");
37
+ const setBulkUnit = new AssignmentUnitConfigBuilder("bulk", "BULK", BULKValue, input).build();
38
+
39
+ const assertBulkUnit = new AssertionUnitConfigBuilder(
40
+ "assert-bulk",
41
+ "BULK != None",
42
+ "Bulk material does not exist!",
43
+ ).build();
44
+
45
+ const query = Utils.str.removeNewLinesAndExtraSpaces(`{
46
+ 'exabyteId': BULK.exabyteId,
47
+ 'data.name': 'total_energy',
48
+ 'group': {'$regex': ''.join((SUBWORKFLOW.application.shortName, ':'))}
49
+ }`);
50
+ // Do not confuse `sort` with `$sort`. `sort` is used in meteor collections and `$sort` is used in Mongo queries.
51
+ const projection = "{'sort': {'precision.value': -1}, 'limit': 1}";
52
+ endpointOptions = getIOUnitEndpointOptions(query, projection);
53
+ const getEBulkUnit = new IOUnitConfigBuilder(
54
+ "io-e-bulk",
55
+ "refined-properties",
56
+ endpointOptions,
57
+ ).build();
58
+
59
+ input = getAssignmentUnitInput(getEBulkUnit, "DATA");
60
+ const EBULKValue = "DATA[0].data.value if DATA else None";
61
+ const setEBulkUnit = new AssignmentUnitConfigBuilder(
62
+ "e-bulk",
63
+ "E_BULK",
64
+ EBULKValue,
65
+ input,
66
+ ).build();
67
+
68
+ const assertEBulkUnit = new AssertionUnitConfigBuilder(
69
+ "assert-e-bulk",
70
+ "E_BULK != None",
71
+ "E_BULK does not exist!",
72
+ ).build();
73
+
74
+ const AValue = "np.linalg.norm(np.cross(SLAB.lattice.vectors.a, SLAB.lattice.vectors.b))";
75
+ const setSurfaceUnit = new AssignmentUnitConfigBuilder("surface", "A", AValue).build();
76
+
77
+ const setNBulkUnit = new AssignmentUnitConfigBuilder(
78
+ "n-bulk",
79
+ "N_BULK",
80
+ "len(BULK.basis.elements)",
81
+ ).build();
82
+ const setNSlabUnit = new AssignmentUnitConfigBuilder(
83
+ "n-slab",
84
+ "N_SLAB",
85
+ "len(SLAB.basis.elements)",
86
+ ).build();
87
+
88
+ input = getAssignmentUnitInput(scfUnit, "total_energy");
89
+ const setESlabUnit = new AssignmentUnitConfigBuilder(
90
+ "e-slab",
91
+ "E_SLAB",
92
+ "total_energy",
93
+ input,
94
+ ).build();
95
+
96
+ const results = [{ name: "surface_energy" }];
97
+ const SEValue = "1 / (2 * A) * (E_SLAB - E_BULK * (N_SLAB/N_BULK))";
98
+ const surfaceEnergyUnit = new AssignmentUnitConfigBuilder(
99
+ "surface-energy",
100
+ "SURFACE_ENERGY",
101
+ SEValue,
102
+ [],
103
+ results,
104
+ ).build();
105
+
106
+ return [
107
+ getSlabUnit,
108
+ setSlabUnit,
109
+ getBulkUnit,
110
+ setBulkUnit,
111
+ assertBulkUnit,
112
+ getEBulkUnit,
113
+ setEBulkUnit,
114
+ assertEBulkUnit,
115
+ setSurfaceUnit,
116
+ setNBulkUnit,
117
+ setNSlabUnit,
118
+ scfUnit,
119
+ setESlabUnit,
120
+ surfaceEnergyUnit,
121
+ ];
122
+ }
123
+
124
+ export { getSurfaceEnergySubworkflowUnits };
@@ -0,0 +1,2 @@
1
+ export { Subworkflow } from "./subworkflow";
2
+ export { createSubworkflowByName } from "./create";
@@ -0,0 +1,329 @@
1
+ import { Application } from "@exabyte-io/ade.js";
2
+ import { Model, ModelFactory } from "@exabyte-io/mode.js";
3
+ import {
4
+ ContextAndRenderFieldsMixin,
5
+ NamedDefaultableRepetitionImportantSettingsInMemoryEntity,
6
+ } from "@mat3ra/code/dist/js/entity";
7
+ import { Utils } from "@mat3ra/utils";
8
+ import lodash from "lodash";
9
+ import { mix } from "mixwith";
10
+ import _ from "underscore";
11
+
12
+ import { UNIT_TYPES } from "../enums";
13
+ import { UnitFactory } from "../units";
14
+ import { setNextLinks, setUnitsHead } from "../utils";
15
+ import { ConvergenceMixin } from "./convergence";
16
+
17
+ /* eslint max-classes-per-file:0 */
18
+
19
+ class BaseSubworkflow extends mix(NamedDefaultableRepetitionImportantSettingsInMemoryEntity).with(
20
+ ConvergenceMixin,
21
+ ContextAndRenderFieldsMixin,
22
+ ) {}
23
+
24
+ export class Subworkflow extends BaseSubworkflow {
25
+ static usePredefinedIds = false;
26
+
27
+ constructor(config) {
28
+ super(config);
29
+ this._Application = Application;
30
+ this._ModelFactory = ModelFactory;
31
+ this._UnitFactory = UnitFactory;
32
+ this.initialize();
33
+ }
34
+
35
+ initialize() {
36
+ this._application = new this._Application(this.prop("application"));
37
+ this._model = this._ModelFactory.create({
38
+ ...this.prop("model"),
39
+ application: this.prop("application"),
40
+ });
41
+ this._units = setNextLinks(setUnitsHead(this.prop("units", [])), this.id).map((cfg) =>
42
+ this._UnitFactory.create(
43
+ Object.assign(cfg, { application: this.application.toJSON() }),
44
+ ),
45
+ );
46
+ }
47
+
48
+ static generateSubworkflowId(...args) {
49
+ args[0] = `subworkflow-${args[0]}`;
50
+ if (this.usePredefinedIds) return Utils.uuid.getUUIDFromNamespace(...args);
51
+ return Utils.uuid.getUUID();
52
+ }
53
+
54
+ static get defaultConfig() {
55
+ const defaultName = "New Subworkflow";
56
+ return {
57
+ _id: this.generateSubworkflowId(defaultName),
58
+ name: defaultName,
59
+ application: Application.defaultConfig,
60
+ model: Model.defaultConfig,
61
+ properties: [],
62
+ units: [],
63
+ };
64
+ }
65
+
66
+ /*
67
+ * @returns {SubworkflowUnit}
68
+ */
69
+ getAsUnit() {
70
+ return this._UnitFactory.create({
71
+ type: UNIT_TYPES.subworkflow,
72
+ _id: this.id,
73
+ name: this.name,
74
+ });
75
+ }
76
+
77
+ /*
78
+ * @summary Used to generate initial application tree, therefore omit setting application.
79
+ */
80
+ static fromArguments(
81
+ application,
82
+ model,
83
+ method,
84
+ name,
85
+ units = [],
86
+ config = {},
87
+ Cls = Subworkflow,
88
+ ) {
89
+ return new Cls({
90
+ ...config,
91
+ _id: Cls.generateSubworkflowId(name),
92
+ name,
93
+ application: application.toJSON(),
94
+ properties: lodash.sortedUniq(
95
+ lodash.flatten(units.filter((x) => x.resultNames).map((x) => x.resultNames)),
96
+ ),
97
+ model: {
98
+ ...model.toJSON(),
99
+ method: method.toJSON(),
100
+ },
101
+ units: units.map((unit) => (unit.toJSON ? unit.toJSON() : unit)),
102
+ });
103
+ }
104
+
105
+ get application() {
106
+ return this._application;
107
+ }
108
+
109
+ setApplication(application) {
110
+ // TODO: adjust the logic above to take into account whether units need re-rendering after version change etc.
111
+ // reset units if application name changes
112
+ const previousApplicationName = this.application.name;
113
+ this._application = application;
114
+
115
+ if (previousApplicationName !== application.name) {
116
+ // TODO: figure out how to set a default unit per new application instead of removing all
117
+ this.setUnits([]);
118
+ } else {
119
+ // propagate new application version to all units
120
+ this.units
121
+ .filter((unit) => typeof unit.setApplication === "function")
122
+ .forEach((unit) => unit.setApplication(application, true));
123
+ }
124
+
125
+ this.setProp("application", application.toJSON());
126
+ // set model to the default one for the application selected
127
+ this.setModel(
128
+ this._ModelFactory.createFromApplication({
129
+ application: this.prop("application"),
130
+ }),
131
+ );
132
+ }
133
+
134
+ get model() {
135
+ return this._model;
136
+ }
137
+
138
+ setModel(model) {
139
+ this._model = model;
140
+ }
141
+
142
+ get units() {
143
+ return this._units;
144
+ }
145
+
146
+ setUnits(units) {
147
+ this._units = units;
148
+ }
149
+
150
+ toJSON(exclude = []) {
151
+ return {
152
+ ...super.toJSON(exclude),
153
+ model: this.model.toJSON(),
154
+ units: this.units.map((x) => x.toJSON()),
155
+ ...(this.compute ? { compute: this.compute } : {}), // {"compute": null } won't pass esse validation
156
+ };
157
+ }
158
+
159
+ get contextProviders() {
160
+ const unitsWithContextProviders = this.units.filter(
161
+ (u) => u.allContextProviders && u.allContextProviders.length,
162
+ );
163
+ const allContextProviders = _.flatten(
164
+ unitsWithContextProviders.map((u) => u.allContextProviders),
165
+ );
166
+ const subworkflowContextProviders = allContextProviders.filter(
167
+ (p) => p.isSubworkflowContextProvider,
168
+ );
169
+ return _.uniq(subworkflowContextProviders, (p) => p.name);
170
+ }
171
+
172
+ /**
173
+ * Extracts a reduced version of the entity config to be stored inside redux state.
174
+ * This is used to track changes to context, monitors, properties, etc. when multiple materials are in state.
175
+ */
176
+ extractReducedExternalDependentConfig() {
177
+ return {
178
+ id: this.id,
179
+ context: this.context || {},
180
+ units: this.units.map((unit) => unit.extractReducedExternalDependentConfig()),
181
+ };
182
+ }
183
+
184
+ /**
185
+ * Applies the reduced config obtained from extractReducedExternalDependentConfig on the entity.
186
+ */
187
+ applyReducedExternalDependentConfig(config) {
188
+ this.context = config.context || {};
189
+ this.units.forEach((unit) => {
190
+ const unitConfig = (config.units || []).find((c) => c.id === unit.flowchartId);
191
+ unit.applyReducedExternalDependentConfig(unitConfig || {});
192
+ });
193
+ }
194
+
195
+ get contextFromAssignmentUnits() {
196
+ const ctx = {};
197
+ this.units
198
+ .filter((u) => u.type === UNIT_TYPES.assignment)
199
+ .forEach((u) => {
200
+ ctx[u.operand] = u.value;
201
+ });
202
+ return ctx;
203
+ }
204
+
205
+ render(context = {}) {
206
+ const ctx = {
207
+ ...context,
208
+ application: this.application,
209
+ methodData: this.model.method.data,
210
+ model: this.model.toJSON(),
211
+ // context below is assembled from context providers and passed to units to override theirs
212
+ ...this.context,
213
+ subworkflowContext: this.contextFromAssignmentUnits,
214
+ };
215
+
216
+ this.units.forEach((u) => u.render(ctx));
217
+ }
218
+
219
+ /**
220
+ * TODO: reuse workflow function instead
221
+ * @param unit {Unit}
222
+ * @param head {Boolean}
223
+ * @param index {Number}
224
+ */
225
+ addUnit(unit, index = -1) {
226
+ const { units } = this;
227
+ if (units.length === 0) {
228
+ unit.head = true;
229
+ this.setUnits([unit]);
230
+ } else {
231
+ if (index >= 0) units.splice(index, 0, unit);
232
+ else units.push(unit);
233
+ this.setUnits(setNextLinks(setUnitsHead(units)));
234
+ }
235
+ }
236
+
237
+ removeUnit(flowchartId) {
238
+ const previousUnit = this.units.find((x) => x.next === flowchartId);
239
+ if (previousUnit) previousUnit.unsetProp("next");
240
+ // TODO: remove the setNextLinks and setUnitsHead and handle the logic via flowchart designer
241
+ this.setUnits(
242
+ setNextLinks(setUnitsHead(this.units.filter((x) => x.flowchartId !== flowchartId))),
243
+ );
244
+ }
245
+
246
+ get properties() {
247
+ return lodash.flatten(this.units.map((x) => x.resultNames));
248
+ }
249
+
250
+ getUnit(flowchartId) {
251
+ return this.units.find((x) => x.flowchartId === flowchartId);
252
+ }
253
+
254
+ unitIndex(flowchartId) {
255
+ return lodash.findIndex(this.units, (unit) => {
256
+ return unit.flowchartId === flowchartId;
257
+ });
258
+ }
259
+
260
+ replaceUnit(index, unit) {
261
+ this.units[index] = unit;
262
+ this.setUnits(setNextLinks(setUnitsHead(this.units)));
263
+ }
264
+
265
+ // eslint-disable-next-line class-methods-use-this
266
+ get scopeVariables() {
267
+ return ["N_k", "N_k_nonuniform"];
268
+ }
269
+
270
+ // eslint-disable-next-line class-methods-use-this
271
+ get scalarResults() {
272
+ return ["total_energy", "pressure"];
273
+ }
274
+
275
+ get isMultiMaterial() {
276
+ return this.prop("isMultiMaterial", false);
277
+ }
278
+
279
+ get isDraft() {
280
+ return this.prop("isDraft", false);
281
+ }
282
+
283
+ setIsDraft(bool) {
284
+ return this.setProp("isDraft", bool);
285
+ }
286
+
287
+ get methodData() {
288
+ return this.model.method.data;
289
+ }
290
+
291
+ /**
292
+ * @summary Calculates hash of the subworkflow. Meaningful fields are units, app and model.
293
+ * units must be sorted topologically before hashing (already sorted).
294
+ */
295
+ calculateHash() {
296
+ const config = this.toJSON();
297
+ const meaningfulFields = {
298
+ application: Utils.specific.removeTimestampableKeysFromConfig(config.application),
299
+ model: this._calculateModelHash(),
300
+ units: _.map(this.units, (u) => u.calculateHash()).join(),
301
+ };
302
+ return Utils.hash.calculateHashFromObject(meaningfulFields);
303
+ }
304
+
305
+ _calculateModelHash() {
306
+ const { model } = this.toJSON();
307
+ // ignore empty data object
308
+ if (this.model.method.omitInHashCalculation) delete model.method.data;
309
+ return Utils.hash.calculateHashFromObject(model);
310
+ }
311
+
312
+ findUnitById(id) {
313
+ // TODO: come back and refactor after converting flowchartId to id
314
+ return this.units.find((u) => u.flowchartId === id);
315
+ }
316
+
317
+ findUnitKeyById(id) {
318
+ const index = this.units.findIndex((u) => u.flowchartId === id);
319
+ return `units.${index}`;
320
+ }
321
+
322
+ findUnitWithTag(tag) {
323
+ return this.units.find((unit) => unit.tags.includes(tag));
324
+ }
325
+
326
+ get hasConvergence() {
327
+ return !!this.convergenceParam && !!this.convergenceResult && !!this.convergenceSeries;
328
+ }
329
+ }