RunSimulationNearField.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. <template>
  2. <div class="row items-baseline">
  3. <div
  4. class="col-xs-12 col-sm-auto text-weight-bold text-center q-px-md q-py-sm"
  5. >
  6. <q-tooltip
  7. v-if="
  8. $store.state.guiRuntime.safeFromWL >
  9. $store.state.simulationSetup.gui.nearFieldSetup.atWL ||
  10. $store.state.guiRuntime.safeToWL <
  11. $store.state.simulationSetup.gui.nearFieldSetup.atWL
  12. "
  13. anchor="top middle"
  14. self="center middle"
  15. class="bg-amber-4 text-black shadow-4"
  16. >
  17. Will use materials<br />
  18. spectrum range.
  19. </q-tooltip>
  20. <q-btn
  21. :loading="isRunning"
  22. :disable="isRunning || !isNmieLoaded"
  23. color="primary"
  24. no-caps
  25. :label="isNmieLoaded ? 'Run simulation' : 'Loading...'"
  26. @click="runNearFieldSimulation"
  27. >
  28. <template #loading>
  29. <q-spinner-gears />
  30. </template>
  31. </q-btn>
  32. </div>
  33. <div class="col-xs-grow col-sm q-px-xs">
  34. <div class="row justify-xs-center justify-sm-start items-baseline">
  35. <div class="col-auto">
  36. <SaveSimulationNearField />
  37. </div>
  38. </div>
  39. </div>
  40. </div>
  41. <div class="row items-baseline">
  42. <div
  43. class="col-xs-12 col-sm-auto text-weight-bold text-center q-px-md q-py-sm"
  44. >
  45. <q-btn
  46. :loading="isRunning"
  47. :disable="isRunning || !isNmieLoaded"
  48. color="primary"
  49. no-caps
  50. :label="isNmieLoaded ? 'Refine zoomed region' : 'Loading...'"
  51. @click="refineOnZoom"
  52. >
  53. <template #loading>
  54. <q-spinner-gears />
  55. </template>
  56. </q-btn>
  57. </div>
  58. <div class="col-xs-grow col-sm q-px-xs">
  59. <div class="row justify-xs-center justify-sm-start items-baseline">
  60. <div class="col-auto">
  61. <q-checkbox v-model="isAutoRefineNearField" size="sm">
  62. auto refine
  63. </q-checkbox>
  64. </div>
  65. <div class="col-auto q-px-sm">
  66. <q-tooltip
  67. v-if="isUnusedReset"
  68. anchor="top middle"
  69. self="center middle"
  70. >
  71. to previous 'Run simulation' button click</q-tooltip
  72. >
  73. <q-btn
  74. no-caps
  75. flat
  76. icon="restart_alt"
  77. color="primary"
  78. label="reset"
  79. @click="resetZoom()"
  80. />
  81. </div>
  82. </div>
  83. </div>
  84. </div>
  85. </template>
  86. <script lang="ts">
  87. import { computed, defineComponent, nextTick, watch, ref } from 'vue';
  88. import { useStore } from 'src/store';
  89. import { cloneDeep, floor } from 'lodash';
  90. import SaveSimulationNearField from 'components/nearfield/SaveSimulationNearField.vue';
  91. import {
  92. nearFieldPlane,
  93. nearFieldSetup,
  94. } from 'src/store/simulation-setup/state';
  95. export default defineComponent({
  96. name: 'RunSimulationNearField',
  97. components: { SaveSimulationNearField },
  98. setup() {
  99. const $store = useStore();
  100. const isAutoRefineNearField = computed({
  101. get: () => $store.state.guiRuntime.isAutoRefineNearField,
  102. set: (val) => $store.commit('guiRuntime/setIsAutoRefineNearField', val),
  103. });
  104. const isRunning = computed({
  105. get: () => $store.state.simulationSetup.nmies.nearField.isNmieRunning,
  106. set: (val) => {
  107. val
  108. ? $store.commit('simulationSetup/markNmieNearFieldAsStarted')
  109. : $store.commit('simulationSetup/markNmieNearFieldAsFinished');
  110. },
  111. });
  112. const isNmieLoaded = computed(() => {
  113. return $store.state.simulationSetup.nmies.nearField.instance;
  114. });
  115. const atWL = computed(
  116. () => $store.state.simulationSetup.current.nearFieldSetup.atWL
  117. );
  118. //-------------------------------------------------------------------------//
  119. //--------------------- Main --------------------------------------------//
  120. //-------------------------------------------------------------------------//
  121. function runNearFieldSimulation() {
  122. if (!isNmieLoaded.value) {
  123. console.log('Nmie was not loaded yet');
  124. return;
  125. }
  126. if (isRunning.value) {
  127. console.log('Some Nmie is already running!');
  128. return;
  129. }
  130. isRunning.value = true;
  131. void setTimeout(() => {
  132. void nextTick(() => {
  133. $store.commit('simulationSetup/copySetupFromGuiToCurrent');
  134. const host = $store.state.simulationSetup.current.hostIndex;
  135. const currentNearFieldSetup = cloneDeep(
  136. $store.state.simulationSetup.current.nearFieldSetup
  137. );
  138. const plotXSideResolution = currentNearFieldSetup.plotXSideResolution;
  139. const plotYSideResolution = currentNearFieldSetup.plotYSideResolution;
  140. const relativePlotSize = currentNearFieldSetup.relativePlotSize;
  141. const crossSection = currentNearFieldSetup.crossSection;
  142. const atX = currentNearFieldSetup.atRelativeX0;
  143. const atY = currentNearFieldSetup.atRelativeY0;
  144. const atZ = currentNearFieldSetup.atRelativeZ0;
  145. const isMarkUnconvergedAsNaN = 1; // 0 - do not mark, else do mark
  146. try {
  147. if (!$store.state.simulationSetup.nmies.nearField.instance)
  148. throw 'ERROR! Scattnlay module was not loaded';
  149. const nmie = $store.state.simulationSetup.nmies.nearField.instance;
  150. const layers = cloneDeep(
  151. $store.state.simulationSetup.current.layers
  152. );
  153. const nmieStartedTime = performance.now();
  154. nmie.SetWavelength(atWL.value);
  155. nmie.ClearTarget();
  156. for (const layer of layers) {
  157. if (layer.material.nSpline)
  158. layer.n = layer.material.nSpline.at(atWL.value);
  159. if (layer.material.kSpline)
  160. layer.k = layer.material.kSpline.at(atWL.value);
  161. nmie.AddTargetLayerReIm(
  162. layer.layerWidth * host,
  163. layer.n / host,
  164. layer.k / host
  165. );
  166. }
  167. nmie.SetModeNmaxAndType(-1, -1);
  168. nmie.RunFieldCalculationCartesian(
  169. plotYSideResolution,
  170. plotXSideResolution, // in simulation z-axis resolution for Ek and Hk cross-sections
  171. relativePlotSize,
  172. crossSection,
  173. atX,
  174. atY,
  175. atZ,
  176. isMarkUnconvergedAsNaN
  177. );
  178. const Eabs = nmie.GetFieldEabs();
  179. $store.commit('plotRuntime/setNearField', Eabs);
  180. const nmieTotalRunTime =
  181. (performance.now() - nmieStartedTime) / 1000;
  182. // console.log('Total simulation time:', nmieTotalRunTime, 's')
  183. $store.commit(
  184. 'simulationSetup/setNmieNearFieldTotalRunTime',
  185. nmieTotalRunTime
  186. );
  187. } catch (e) {
  188. console.log('Some error:', e);
  189. }
  190. isRunning.value = false;
  191. });
  192. }, 100);
  193. }
  194. runNearFieldSimulation();
  195. const layerWidths = computed(() =>
  196. $store.state.simulationSetup.current.layers.map((x) => x.layerWidth)
  197. );
  198. const totalR = computed(() => layerWidths.value.reduce((a, b) => a + b, 0));
  199. const nearFieldZoom = computed(() => $store.state.guiRuntime.nearFieldZoom);
  200. const crossSection = computed(
  201. () => $store.state.simulationSetup.current.nearFieldSetup.crossSection
  202. );
  203. const atX = computed(
  204. () =>
  205. (nearFieldZoom.value.fromX + nearFieldZoom.value.toX) /
  206. 2.0 /
  207. totalR.value
  208. );
  209. const atY = computed(
  210. () =>
  211. (nearFieldZoom.value.fromY + nearFieldZoom.value.toY) /
  212. 2.0 /
  213. totalR.value
  214. );
  215. const sideX = computed(
  216. () => (nearFieldZoom.value.toX - nearFieldZoom.value.fromX) / totalR.value
  217. );
  218. const sideY = computed(
  219. () => (nearFieldZoom.value.toY - nearFieldZoom.value.fromY) / totalR.value
  220. );
  221. const plotXSideResolutionGUI = computed(
  222. () => $store.state.simulationSetup.gui.nearFieldSetup.plotXSideResolution
  223. );
  224. const plotYSideResolutionGUI = computed(
  225. () => $store.state.simulationSetup.gui.nearFieldSetup.plotYSideResolution
  226. );
  227. const totalPoints = computed(
  228. () => plotXSideResolutionGUI.value * plotYSideResolutionGUI.value
  229. );
  230. let prevSettingsZoom = cloneDeep(
  231. $store.state.simulationSetup.current.nearFieldSetup
  232. );
  233. let prevSettingsUser = cloneDeep(
  234. $store.state.simulationSetup.current.nearFieldSetup
  235. );
  236. function isEqual(a: nearFieldSetup, b: nearFieldSetup) {
  237. const keys = Object.keys(a);
  238. for (let key of keys) {
  239. // prettier-ignore
  240. // eslint-disable-next-line @typescript-eslint/ban-ts-comment
  241. // @ts-ignore
  242. // eslint-disable-next-line
  243. if (a[key] != b[key]) return false
  244. }
  245. return true;
  246. }
  247. function refineOnZoom() {
  248. const currentSettings = cloneDeep(
  249. $store.state.simulationSetup.current.nearFieldSetup
  250. );
  251. if (!isEqual(currentSettings, prevSettingsZoom)) {
  252. // The only reason for current settings of near-field setup
  253. // to be different from what was previously set in the end of
  254. // refineOnZoom() is some user input... So, remember the state after
  255. // last user intervention to use it on press of a 'reset' button.
  256. prevSettingsUser = cloneDeep(currentSettings);
  257. }
  258. if (sideX.value == 0 || sideY.value == 0) return;
  259. $store.commit('guiRuntime/setPlotRatioLabel', 'fixed');
  260. $store.commit('guiRuntime/setPlotRatio', sideY.value / sideX.value);
  261. $store.commit(
  262. 'simulationSetup/setNearFieldRelativePlotSize',
  263. sideX.value / 2.0
  264. );
  265. $store.commit(
  266. 'simulationSetup/setNearFieldPlotXSideResolution',
  267. floor(Math.sqrt((totalPoints.value * sideX.value) / sideY.value))
  268. );
  269. $store.commit(
  270. 'simulationSetup/setNearFieldPlotYSideResolution',
  271. floor(
  272. $store.state.guiRuntime.plotRatio *
  273. $store.state.simulationSetup.gui.nearFieldSetup.plotXSideResolution
  274. )
  275. );
  276. if (crossSection.value == nearFieldPlane.Ek) {
  277. $store.commit('simulationSetup/setNearFieldAtRelativeZ0', atX.value);
  278. $store.commit('simulationSetup/setNearFieldAtRelativeX0', atY.value);
  279. }
  280. if (crossSection.value == nearFieldPlane.Hk) {
  281. $store.commit('simulationSetup/setNearFieldAtRelativeZ0', atX.value);
  282. $store.commit('simulationSetup/setNearFieldAtRelativeY0', atY.value);
  283. }
  284. if (crossSection.value == nearFieldPlane.EH) {
  285. $store.commit('simulationSetup/setNearFieldAtRelativeY0', atX.value);
  286. $store.commit('simulationSetup/setNearFieldAtRelativeX0', atY.value);
  287. }
  288. prevSettingsZoom = cloneDeep(
  289. $store.state.simulationSetup.gui.nearFieldSetup
  290. );
  291. runNearFieldSimulation();
  292. }
  293. watch([atX, atY, sideX, sideY], () => {
  294. if (!isAutoRefineNearField.value) return;
  295. refineOnZoom();
  296. });
  297. let count = 0;
  298. watch([plotXSideResolutionGUI, plotYSideResolutionGUI], () => {
  299. if (
  300. plotYSideResolutionGUI.value * plotXSideResolutionGUI.value >
  301. 150 * 150 &&
  302. count == 0
  303. ) {
  304. isAutoRefineNearField.value = false;
  305. count = 1;
  306. }
  307. });
  308. const isUnusedReset = ref(true);
  309. return {
  310. isUnusedReset,
  311. isRunning,
  312. isNmieLoaded,
  313. runNearFieldSimulation,
  314. refineOnZoom,
  315. isAutoRefineNearField,
  316. resetZoom() {
  317. isUnusedReset.value = false;
  318. $store.commit('simulationSetup/setNearFieldSetup', prevSettingsUser);
  319. $store.commit(
  320. 'guiRuntime/setPlotRatio',
  321. prevSettingsUser.plotYSideResolution /
  322. prevSettingsUser.plotXSideResolution
  323. );
  324. runNearFieldSimulation();
  325. },
  326. };
  327. },
  328. });
  329. </script>