RunSimulationNearField.vue 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. <template>
  2. <div class="row items-baseline">
  3. <div class="col-xs-12 col-sm-auto text-weight-bold text-center q-px-md q-py-sm">
  4. <q-tooltip
  5. v-if=" $store.state.guiRuntime.safeFromWL > $store.state.simulationSetup.gui.nearFieldSetup.atWL ||
  6. $store.state.guiRuntime.safeToWL < $store.state.simulationSetup.gui.nearFieldSetup.atWL "
  7. anchor="top middle" self="center middle"
  8. class="bg-amber-4 text-black shadow-4">
  9. Will use materials<br> spectrum range.
  10. </q-tooltip>
  11. <q-btn :loading="isRunning"
  12. :disable="isRunning||!isNmieLoaded"
  13. color="primary"
  14. no-caps
  15. :label="isNmieLoaded ? 'Run simulation' : 'Loading...'"
  16. @click="runNearFieldSimulation">
  17. <template #loading>
  18. <q-spinner-gears />
  19. </template>
  20. </q-btn>
  21. </div>
  22. <div class="col-xs-grow col-sm q-px-xs">
  23. <div class="row justify-xs-center justify-sm-start items-baseline">
  24. <div class="col-auto">
  25. <q-btn
  26. color="primary"
  27. no-caps
  28. @click="saveSpectrumSimulation"
  29. >Save</q-btn>
  30. </div>
  31. </div>
  32. </div>
  33. </div>
  34. </template>
  35. <script lang="ts">
  36. import {computed, defineComponent, nextTick, watch} from 'vue'
  37. import {useStore} from 'src/store'
  38. import {getModeName, range, rangeInt} from 'components/utils'
  39. import {cloneDeep} from 'lodash'
  40. import {saveAs} from 'file-saver'
  41. import {nearFieldPlane} from 'src/store/simulation-setup/state';
  42. export default defineComponent({
  43. name: 'RunSimulationNearField',
  44. setup() {
  45. const $store = useStore()
  46. const isRunning = computed({
  47. get: ()=> $store.state.simulationSetup.nmies.nearField.isNmieRunning,
  48. set: val => {
  49. val ? $store.commit('simulationSetup/markNmieNearFieldAsStarted') : $store.commit('simulationSetup/markNmieNearFieldAsFinished')
  50. }
  51. })
  52. const isNmieLoaded = computed(()=>{ return $store.state.simulationSetup.nmies.nearField.instance })
  53. const atWL = computed(
  54. () => $store.state.simulationSetup.current.nearFieldSetup.atWL)
  55. //-------------------------------------------------------------------------//
  56. //--------------------- Main --------------------------------------------//
  57. //-------------------------------------------------------------------------//
  58. function runNearFieldSimulation() {
  59. if (isRunning.value) {
  60. console.log('Some Nmie is already running!')
  61. return
  62. }
  63. isRunning.value = true
  64. void setTimeout(()=> {
  65. void nextTick(()=> {
  66. $store.commit('simulationSetup/copySetupFromGuiToCurrent')
  67. const host = $store.state.simulationSetup.current.hostIndex
  68. const plotSideResolution = $store.state.simulationSetup.current.nearFieldSetup.plotSideResolution
  69. const relativePlotSize = $store.state.simulationSetup.current.nearFieldSetup.relativePlotSize
  70. const crossSection = $store.state.simulationSetup.current.nearFieldSetup.crossSection
  71. try {
  72. if (!$store.state.simulationSetup.nmies.nearField.instance) throw 'ERROR! Scattnlay module was not loaded'
  73. const nmie = $store.state.simulationSetup.nmies.nearField.instance
  74. const layers = cloneDeep($store.state.simulationSetup.current.layers)
  75. const nmieStartedTime = performance.now()
  76. nmie.SetWavelength(atWL.value)
  77. nmie.ClearTarget()
  78. for (const layer of layers) {
  79. if (layer.material.nSpline) layer.n = layer.material.nSpline.at(atWL.value)
  80. if (layer.material.kSpline) layer.k = layer.material.kSpline.at(atWL.value)
  81. nmie.AddTargetLayerReIm(layer.layerWidth * host, layer.n / host, layer.k / host)
  82. }
  83. nmie.SetModeNmaxAndType(-1, -1)
  84. nmie.RunFieldCalculationCartesian(
  85. plotSideResolution,
  86. relativePlotSize,
  87. crossSection,
  88. 0, 0, 0, 1
  89. )
  90. let Eabs_list = Array.from(nmie.GetFieldEabs())
  91. const Eabs = [];
  92. while (Eabs_list.length) Eabs.push(Eabs_list.splice(0, plotSideResolution));
  93. if (crossSection == nearFieldPlane.Ek) $store.commit('plotRuntime/setNearFieldEk', Eabs)
  94. if (crossSection == nearFieldPlane.Hk) $store.commit('plotRuntime/setNearFieldHk', Eabs)
  95. if (crossSection == nearFieldPlane.EH) $store.commit('plotRuntime/setNearFieldEH', Eabs)
  96. const nmieTotalRunTime = (performance.now() - nmieStartedTime) / 1000
  97. // console.log('Total simulation time:', nmieTotalRunTime, 's')
  98. $store.commit('simulationSetup/setNmieNearFieldTotalRunTime', nmieTotalRunTime)
  99. } catch (e) {
  100. console.log('Some error:', e)
  101. }
  102. isRunning.value = false
  103. })
  104. }, 100)
  105. }
  106. watch(isRunning, ()=>{
  107. console.log(isRunning.value)
  108. })
  109. // onActivated(()=>{
  110. // if (isNmieLoaded.value) runNearFieldSimulation()
  111. // })
  112. return { isRunning, isNmieLoaded,
  113. runNearFieldSimulation,
  114. saveSpectrumSimulation(){
  115. const fileHeader = '# # You can open and plot this file using Python\n' +
  116. '# # (without manually removing this header, it will be skipped), see example below.\n' +
  117. '# import numpy as np\n' +
  118. '# from matplotlib import pyplot as plt\n' +
  119. '# data = np.genfromtxt(\'scattnlay-spectra.txt\', skip_header=21, names=True, delimiter=\', \')\n' +
  120. '# x = data[data.dtype.names[0]] # x-axis has units\n' +
  121. '# # Possible labels for spectrum data: Qsca, Qabs, Qext,\n' +
  122. '# # Qsca_E_dipole, etc. (see last comment before spectra data)\n' +
  123. '# a = data[\'Qsca\']\n' +
  124. '# b = data[\'Qsca_E_dipole\']\n' +
  125. '# c = data[\'Qsca_H_dipole\']\n' +
  126. '# \n' +
  127. '# plt.figure()\n' +
  128. '# plt.plot(x, a, label=\'Qsca\')\n' +
  129. '# plt.plot(x, b, label=\'Qsca E dipole\')\n' +
  130. '# plt.plot(x, c, label=\'Qsca H dipole\')\n' +
  131. '# plt.legend()\n' +
  132. '# plt.xlabel(data.dtype.names[0].replace(\'_\', \', \'))\n' +
  133. '# plt.ylabel(\'Normalized cross-sections\')\n' +
  134. '# plt.show()\n\n'
  135. let xTitle = 'x'
  136. if ( $store.state.plotRuntime.spectrumPlots.layout.xaxis ) {
  137. xTitle = String($store.state.plotRuntime.spectrumPlots.layout.xaxis.title)
  138. }
  139. let columnNames = '# ' + xTitle + ', Qsca, Qabs, Qext, '
  140. const mode_n = rangeInt($store.state.simulationSetup.current.numberOfModesToPlot, 1);
  141. const mode_types = range(0, 1);
  142. for (const n of mode_n) {
  143. for (const mode_type of mode_types) {
  144. const modeTypeName = mode_type == 0 ? 'E' : 'H'
  145. columnNames += 'Qsca_' + modeTypeName + '_' +getModeName(n)+', '
  146. columnNames += 'Qabs_' + modeTypeName + '_' +getModeName(n)+', '
  147. columnNames += 'Qext_' + modeTypeName + '_' +getModeName(n)+', '
  148. }
  149. }
  150. columnNames = columnNames.slice(0, -2)
  151. columnNames += '\n'
  152. let body = ''
  153. const WLs = $store.state.plotRuntime.WLsInUnits
  154. const Qsca = $store.state.plotRuntime.Qsca
  155. const Qabs = $store.state.plotRuntime.Qabs
  156. const Qext = $store.state.plotRuntime.Qext
  157. const Qsca_n = $store.state.plotRuntime.Qsca_n
  158. const Qabs_n = $store.state.plotRuntime.Qabs_n
  159. const Qext_n = $store.state.plotRuntime.Qext_n
  160. for (let i = 0; i < WLs.length; ++i) {
  161. let row = WLs[i].toString() + ', '
  162. + Qsca[i].toString() + ', '
  163. + Qabs[i].toString() + ', '
  164. + Qext[i].toString() + ', '
  165. for (const n of mode_n) {
  166. for (const mode_type of mode_types) {
  167. row += Qsca_n[mode_type][n - 1][i].toString() + ', '
  168. row += Qabs_n[mode_type][n - 1][i].toString() + ', '
  169. row += Qext_n[mode_type][n - 1][i].toString() + ', '
  170. }
  171. }
  172. row = row.slice(0, -2)
  173. row += '\n'
  174. body += row
  175. }
  176. const scattnlaySpectra = new Blob([fileHeader+columnNames+body],
  177. {type: 'text/plain;charset=utf-8',
  178. endings: 'native'} //TODO test if newline is correctly written in Windows, MacOS
  179. )
  180. saveAs(scattnlaySpectra, 'scattnlay-spectra.txt');
  181. }
  182. }
  183. },
  184. })
  185. </script>