App.vue 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861
  1. <template>
  2. <div id="app">
  3. <b-loading :active.sync="isLoading" :can-cancel="isLoading"/>
  4. <ShowInfo/>
  5. <section class="add_padding">
  6. <GetUnits v-bind:units="units"
  7. v-bind:source_units="source_units"
  8. v-bind:isSourceOtherUnits="isSourceOtherUnits"
  9. @unitsData="units=$event"
  10. @source_unitsData="source_units=$event"
  11. @isSourceOtherUnitsData="isSourceOtherUnits=$event"
  12. />
  13. <GetHostIndex v-bind:hostIndex="simulationSetup.hostIndex"
  14. @hostIndexData="simulationSetup.hostIndex=$event" />
  15. <GetSourceParameters v-bind:fromWL="simulationSetup.fromWL"
  16. v-bind:toWL="simulationSetup.toWL"
  17. v-bind:stepWL="simulationSetup.stepWL"
  18. v-bind:source_units="source_units"
  19. @fromWLData="simulationSetup.fromWL=$event"
  20. @toWLData="simulationSetup.toWL=$event"
  21. @stepWLData="simulationSetup.stepWL=$event"
  22. @source_unitsData="source_units=$event"
  23. />
  24. <GetMaterials v-bind:materials="materials"
  25. v-bind:plot_width="chart.layout.width"
  26. v-bind:plot_height="chart.layout.height"
  27. />
  28. <GetParticleParameters v-bind:layers="simulationSetup.layers"
  29. v-bind:units="units"
  30. v-bind:materials="materials"
  31. />
  32. <div class="field is-horizontal">
  33. <div class="field-label is-normal">
  34. <label class="label">Modes to plot</label>
  35. </div>
  36. <div class="field-body" >
  37. <b-field label="">
  38. <b-input v-model="simulationSetup.total_mode_n" type='number' min=1 style="width:7rem"/>
  39. </b-field>
  40. </div>
  41. </div>
  42. <div class="add_padding">
  43. <b-button class="is-primary is-medium" @click="runSimulation();">
  44. Run simulation
  45. </b-button><br>
  46. It took {{ ttime }} s.
  47. </div>
  48. <div class="field is-grouped is-grouped-multiline add_padding">
  49. <b-switch v-model="plotSelector.isPlotQsca">
  50. Qsca
  51. </b-switch>
  52. <b-switch v-model="plotSelector.isPlotQabs">
  53. Qabs
  54. </b-switch>
  55. <b-switch v-model="plotSelector.isPlotQext">
  56. Qext
  57. </b-switch>
  58. </div>
  59. <!-- <b-table :data="plotSelectorData" :columns="plotSelectorColumns" :mobile-cards="isShowInfo"></b-table>-->
  60. <table class="table is-narrow add_padding">
  61. <thead>
  62. <tr>
  63. <th v-for="mode_name in simulationRuntime.mode_n_names" v-bind:key="mode_name.name">
  64. {{ mode_name.name == 'type' ? '': mode_name.name}}
  65. </th>
  66. </tr>
  67. </thead>
  68. <tbody>
  69. <tr>
  70. <th>E</th>
  71. <td v-for="(mode,index) in plotSelector.isPlotModeE" v-bind:key="index">
  72. <template v-if="(simulationRuntime.total_mode_n_evaluated - 1) < index">
  73. <b-checkbox v-model="plotSelector.isPlotModeE[index]" disabled> </b-checkbox>
  74. </template>
  75. <template v-else>
  76. <b-checkbox v-model="plotSelector.isPlotModeE[index]"> </b-checkbox>
  77. </template>
  78. </td>
  79. </tr>
  80. <tr>
  81. <th>H</th>
  82. <td v-for="(mode,index) in plotSelector.isPlotModeH" v-bind:key="index">
  83. <template v-if="(simulationRuntime.total_mode_n_evaluated - 1) < index">
  84. <b-checkbox v-model="plotSelector.isPlotModeH[index]" disabled> </b-checkbox>
  85. </template>
  86. <template v-else>
  87. <b-checkbox v-model="plotSelector.isPlotModeH[index]"> </b-checkbox>
  88. </template>
  89. </td>
  90. </tr>
  91. </tbody>
  92. </table>
  93. </section>
  94. <div class="chart-container">
  95. <reactive-chart :chart="chart"/>
  96. </div>
  97. </div>
  98. </template>
  99. <script>
  100. // You should put *.wasm to public/ and *.js to src/ folder
  101. // To compile fibbonacci example use
  102. // emcc -O3 -s WASM=1 -s EXTRA_EXPORTED_RUNTIME_METHODS='["cwrap"]' -s ALLOW_MEMORY_GROWTH=1 -s MODULARIZE=1 -s 'EXPORT_NAME="fibonacci"' -o ./fibonacci.js fibonacci.c
  103. // for and example from https://gist.github.com/ashleygwilliams/32c31a3f5b8c87bf2894108b3534ee4f
  104. // import fibonacci from './fibonacci.js';
  105. // const module = fibonacci({
  106. // locateFile(path) {
  107. // console.log(path);
  108. // return path;
  109. // }
  110. // });
  111. // module.onRuntimeInitialized = () => {
  112. // console.log(module._fib(12));
  113. // };
  114. // // Test the size of wasm file
  115. // fetch('nmiejs.wasm'
  116. // ).then(response =>
  117. // response.arrayBuffer()
  118. // ).then(bytes =>
  119. // console.log(bytes)
  120. // );
  121. import nmiejs from './nmiejs.js';
  122. // Test nmiejs if working
  123. (async () => {
  124. const module = await nmiejs({
  125. locateFile(path) {
  126. let deploy_path = process.env.BASE_URL;
  127. // '/themes/custom/physics/mie/';
  128. // console.log();
  129. // // let deploy_path = '';
  130. console.log(deploy_path + path);
  131. return deploy_path + path;
  132. }
  133. })
  134. const nmie = new module.nmie();
  135. nmie.ClearTarget();
  136. let R = 100.0;
  137. let reN = 4.0;
  138. let imN = 0.01;
  139. nmie.AddTargetLayerReIm(R, reN, imN)
  140. nmie.SetModeNmaxAndType(-1, -1);
  141. let WL = 800;
  142. nmie.SetWavelength(WL);
  143. nmie.RunMieCalculation();
  144. console.log(nmie.GetQsca());
  145. // outer_arc_points, radius_points, from_Rho, to_Rho,
  146. // from_Theta, to_Theta, from_Phi, to_Phi, isIgnoreAvailableNmax
  147. nmie.RunFieldCalculationPolar(2, 2, 0.1, 1.5, 0, 3.1415, 0, 3.1415, 0);
  148. console.log("Field Eabs:", nmie.GetFieldEabs());
  149. })();
  150. const range = (start, stop, step = 1) => Array(Math.ceil((stop - start) / step)).fill(start).map((x, y) => x + y * step);
  151. function rangeInt(size, startAt = 0) {
  152. return [...Array(size).keys()].map(i => i + startAt);
  153. }
  154. import ReactiveChart from "./components/ReactiveChart.vue";
  155. import ShowInfo from "./components/ShowInfo.vue";
  156. import GetMaterials from "./components/GetMaterials.vue";
  157. import GetHostIndex from "./components/GetHostIndex.vue";
  158. import GetUnits from "./components/GetUnits.vue";
  159. import GetSourceParameters from "./components/GetSourceParameters.vue";
  160. import GetParticleParameters from "./components/GetParticleParameters.vue";
  161. export default {
  162. name: 'app',
  163. components: {
  164. GetHostIndex,
  165. GetMaterials,
  166. GetSourceParameters,
  167. GetParticleParameters,
  168. GetUnits,
  169. ReactiveChart,
  170. ShowInfo
  171. },
  172. data() {
  173. return {
  174. nmie: undefined,
  175. ttime: "",
  176. window: {
  177. width: 0,
  178. height: 0
  179. },
  180. units: 'nm',
  181. units_prev: 'nm',
  182. source_units: 'nm',
  183. source_units_prev: 'nm',
  184. materials: [],
  185. isSourceOtherUnits: false,
  186. simulationSetup: {
  187. hostIndex: 1,
  188. stepWL: 2,
  189. fromWL: 300.0,
  190. toWL: 1000.0,
  191. layers: [
  192. {
  193. R: 100.0,
  194. material: 'nk',
  195. isMaterialLoaded:true,
  196. reN: 4.0,
  197. imN: 0.01,
  198. index: 0
  199. }
  200. ],
  201. total_mode_n: 4
  202. },
  203. simulationRuntime: {
  204. r_units: 'nm',
  205. r_source_units: 'nm',
  206. stepWL: 2,
  207. fromWL: 300.0,
  208. toWL: 1000.0,
  209. layers: [
  210. {
  211. R: 100.0,
  212. material: 'nk',
  213. reN: 4.0,
  214. imN: 0.01,
  215. index:0
  216. }
  217. ],
  218. mode_n: [],
  219. mode_n_names: [],
  220. mode_types: range(0, 2),
  221. mode_names: ['E', 'H'],
  222. WLs: [],
  223. Qsca: [],
  224. Qabs: [],
  225. Qext: [],
  226. Qsca_n: [[], []],
  227. Qabs_n: [[], []],
  228. layout: {},
  229. trace1: {},
  230. trace2: {},
  231. total_mode_n_evaluated: 4,
  232. },
  233. plotData: {
  234. pWLs: [],
  235. pQsca: [],
  236. pQabs: [],
  237. pQext: [],
  238. pQsca_n: [[], []],
  239. pQabs_n: [[], []],
  240. },
  241. changes: 0,
  242. isShowInfo: false,
  243. isLoading: true,
  244. isRunning: false,
  245. plotSelector: {
  246. isPlotModeE: [],
  247. isPlotModeH: [],
  248. isPlotQabs: true,
  249. isPlotQsca: true,
  250. isPlotQext: false,
  251. },
  252. // plotSelectorData: undefined,
  253. // plotSelectorColumns: undefined,
  254. // plotSelectorNames: undefined,
  255. chart: {
  256. uuid: "spectra",
  257. traces: [
  258. {
  259. y: [],
  260. line: {
  261. color: "#5e9e7e",
  262. width: 4,
  263. shape: "line"
  264. }
  265. }
  266. ],
  267. layout: {
  268. margin: {
  269. l:0,
  270. r:40,
  271. b:50,
  272. t:0
  273. },
  274. // paper_bgcolor: '#7f7f7f',
  275. // plot_bgcolor: '#c7c7c7',
  276. // title: 'reactive charts',
  277. xaxis: {
  278. // will be set on mount
  279. title: ''
  280. },
  281. yaxis: {
  282. title: 'Normalized cross-sections'
  283. },
  284. showlegend: true,
  285. legend: {
  286. orientation:"h",
  287. x: -.1,
  288. y: 1.05
  289. },
  290. // width: 100,
  291. height: 100
  292. }
  293. }
  294. };
  295. },
  296. created() {
  297. window.addEventListener('resize', this.handleResize);
  298. this.handleResize();
  299. },
  300. destroyed() {
  301. window.removeEventListener('resize', this.handleResize)
  302. },
  303. mounted() {
  304. this.setXaxisTitle();
  305. (async () => {
  306. const module = await nmiejs({
  307. locateFile(path) {
  308. let deploy_path = process.env.BASE_URL;
  309. // '/themes/custom/physics/mie/';
  310. // console.log();
  311. // // let deploy_path = '';
  312. console.log(deploy_path + path);
  313. return deploy_path + path;
  314. }
  315. })
  316. this.nmie = new module.nmie();
  317. this.isLoading = false;
  318. this.runMie();
  319. this.setIsPlotMode();
  320. this.setModeNNames();
  321. this.plotResults();
  322. })();
  323. },
  324. watch: {
  325. plotSelector: {
  326. handler: function () {
  327. this.plotResults();
  328. },
  329. deep: true
  330. },
  331. 'simulationSetup.total_mode_n': function () {
  332. this.setIsPlotMode();
  333. this.setModeNNames();
  334. },
  335. units: {
  336. handler: function () {
  337. if (!this.isSourceOtherUnits) {
  338. this.source_units = this.units;
  339. }
  340. let u = this.units;
  341. let u_prev = this.units_prev;
  342. let layers = this.simulationSetup.layers;
  343. for (let i=0; i<layers.length; i++) {
  344. layers[i].R = this.convertUnits(u_prev, u, layers[i].R);
  345. }
  346. this.units_prev = this.units;
  347. }
  348. },
  349. source_units: {
  350. handler: function () {
  351. // this.$buefy.notification.open({
  352. // duration: 4000,
  353. // message: 'Source parameters were restored from last simulation for correct plotting.',
  354. // type: 'is-info',
  355. // position: 'is-top',
  356. // });
  357. this.setXaxisTitle();
  358. let u = this.source_units;
  359. let u_prev = this.source_units_prev;
  360. for (let i=0; i<this.plotData.pWLs.length; i++) {
  361. this.plotData.pWLs[i] = this.convertUnits(u_prev, u,
  362. this.plotData.pWLs[i]);
  363. }
  364. this.simulationSetup.fromWL = this.convertUnits(u_prev, u,
  365. this.simulationSetup.fromWL);
  366. this.simulationSetup.toWL = this.convertUnits(u_prev, u,
  367. this.simulationSetup.toWL);
  368. if (this.simulationSetup.fromWL > this.simulationSetup.toWL) {
  369. let tmp = this.simulationSetup.fromWL;
  370. this.simulationSetup.fromWL = this.simulationSetup.toWL;
  371. this.simulationSetup.toWL = tmp;
  372. }
  373. this.simulationSetup.stepWL = (this.simulationSetup.toWL-this.simulationSetup.fromWL)
  374. /this.plotData.pWLs.length;
  375. this.source_units_prev = this.source_units;
  376. // Update plotting
  377. this.plotSelector.isPlotQsca = !this.plotSelector.isPlotQsca
  378. setTimeout(
  379. () => {
  380. this.plotSelector.isPlotQsca = !this.plotSelector.isPlotQsca
  381. }, 2);
  382. }
  383. },
  384. isSourceOtherUnits: {
  385. handler: function () {
  386. // this.setEmptyChart();
  387. this.setXaxisTitle();
  388. if (!this.isSourceOtherUnits) {
  389. this.source_units = this.units;
  390. } else {
  391. this.source_units = 'THz'
  392. }
  393. }
  394. },
  395. window: {
  396. handler: function () {
  397. // this.chart.layout.width = this.window.width * 0.92;
  398. this.chart.layout.height = this.window.height * 0.95;
  399. // if (this.window.width < 600) this.chart.layout.width = this.window.width;
  400. if (this.window.height < 600) this.chart.layout.height = this.window.height;
  401. },
  402. deep: true
  403. }
  404. },
  405. methods: {
  406. handleResize() {
  407. this.window.width = window.innerWidth;
  408. this.window.height = window.innerHeight*0.8;
  409. },
  410. convertUnits2nm(fromU, val) {
  411. if (fromU === 'nm') return val;
  412. if (fromU === 'mkm') return val*1e3;
  413. if (fromU === 'mm') return val*1e6;
  414. if (fromU === 'cm') return val*1e7;
  415. if (fromU === 'm') return val*1e9;
  416. if (fromU === 'km') return val*1e12;
  417. let c = 299792458; // m/s
  418. let hc = 1239841930.092394328e-15; // m*eV
  419. if (fromU === 'THz') return c/(val*1e12)*1e9;
  420. if (fromU === 'GHz') return c/(val*1e9)*1e9;
  421. if (fromU === 'MHz') return c/(val*1e6)*1e9;
  422. if (fromU === 'kHz') return c/(val*1e3)*1e9;
  423. if (fromU === 'Hz') return c/(val*1e0)*1e9;
  424. if (fromU === 'eV') return hc/(val*1e0)*1e9;
  425. if (fromU === 'meV') return hc/(val/1e3)*1e9;
  426. if (fromU === 'fs') return (val/1e12)/c*1e9;
  427. if (fromU === 'ps') return (val/1e15)/c*1e9;
  428. return undefined;
  429. },
  430. convertUnitsFrom_nm(toU, val) {
  431. if (toU === 'nm') return val;
  432. if (toU === 'mkm') return val/1e3;
  433. if (toU === 'mm') return val/1e6;
  434. if (toU === 'cm') return val/1e7;
  435. if (toU === 'm') return val/1e9;
  436. if (toU === 'km') return val/1e12;
  437. let c = 299792458; // m/s
  438. let hc = 1239841930.092394328e-15; // m*eV
  439. if (toU === 'THz') return c/(val/1e9)/1e12;
  440. if (toU === 'GHz') return c/(val/1e9)/1e9;
  441. if (toU === 'MHz') return c/(val/1e9)/1e6;
  442. if (toU === 'kHz') return c/(val/1e9)/1e3;
  443. if (toU === 'Hz') return c/(val/1e9)/1e0;
  444. if (toU === 'eV') return hc/(val/1e9);
  445. if (toU === 'meV') return hc/(val/1e9)*1e3;
  446. if (toU === 'fs') return (val/1e9)/c*1e12;
  447. if (toU === 'ps') return (val/1e9)/c*1e15;
  448. return undefined;
  449. },
  450. convertUnits(fromU,toU, val) {
  451. if (fromU === toU) return val;
  452. return this.convertUnitsFrom_nm(toU, this.convertUnits2nm(fromU, val));
  453. },
  454. notifyDanger: function(message) {
  455. this.$buefy.notification.open({
  456. duration: 3000,
  457. message: message,
  458. type: 'is-danger',
  459. position: 'is-bottom-left',
  460. });
  461. },
  462. runSimulation: function() {
  463. this.$buefy.notification.open({
  464. duration: 200,
  465. message: 'Simulation was started!',
  466. type: 'is-danger',
  467. position: 'is-bottom-left',
  468. });
  469. setTimeout(
  470. () => {
  471. this.runMie();
  472. this.plotResults();
  473. this.$buefy.notification.open({
  474. duration: 3000,
  475. message: 'Finished! '+"It took " + this.ttime + " s.",
  476. type: 'is-success',
  477. position: 'is-bottom-left',
  478. })
  479. ;
  480. }, 20);
  481. },
  482. runMie: function () {
  483. this.simulationRuntime.r_units = this.units;
  484. this.simulationRuntime.r_source_units = this.source_units;
  485. this.simulationRuntime.fromWL = this.simulationSetup.fromWL;
  486. this.simulationRuntime.toWL = this.simulationSetup.toWL;
  487. this.simulationRuntime.stepWL = this.simulationSetup.stepWL;
  488. this.simulationRuntime.layers =this.simulationSetup.layers; // TODO: not a copy, but we need spline_n.at() method in every layer.
  489. let t0 = performance.now();
  490. let fromWL = parseFloat(this.simulationSetup.fromWL);
  491. let toWL = parseFloat(this.simulationSetup.toWL);
  492. let stepWL = parseFloat(this.simulationSetup.stepWL);
  493. let host = parseFloat(this.simulationSetup.hostIndex);
  494. let Qsca = [], Qabs = [], Qext = [];
  495. let Qsca_n = [[], []], Qabs_n = [[], []];
  496. let WLs = range(fromWL, toWL, stepWL);
  497. this.simulationRuntime.WLs = WLs;
  498. let total_mode_n = this.simulationSetup.total_mode_n;
  499. let mode_n = [];
  500. mode_n = rangeInt(Number(total_mode_n), 1);
  501. this.simulationRuntime.total_mode_n_evaluated = total_mode_n;
  502. let mode_types = range(0, 2);
  503. this.simulationSetup.mode_n = mode_n;
  504. this.simulationSetup.mode_types = mode_types;
  505. mode_types.forEach(function (mode_type) {
  506. mode_n.forEach(function () {
  507. Qsca_n[mode_type].push([]);
  508. Qabs_n[mode_type].push([]);
  509. });
  510. });
  511. // Provide all sizes (germetry and wavelengths) to nmie in same units [nm]
  512. const nmie = this.nmie;
  513. // nmie.ClearTarget();
  514. // nmie.AddTargetLayerReIm( this.convertUnits2nm(this.units, R)*host,
  515. // reN/host, imN/host);
  516. let WLs_nm = range(fromWL, toWL, stepWL);
  517. let WL_points = WLs_nm.length;
  518. for (let i = 0; i < WL_points; i++) {
  519. let WL = this.convertUnits2nm(this.source_units, WLs[i]);
  520. nmie.ClearTarget();
  521. for (let num_layer = 0;
  522. num_layer < this.simulationRuntime.layers.length;
  523. num_layer++) {
  524. let layer = this.simulationRuntime.layers[num_layer];
  525. let R = parseFloat(layer.R);
  526. if (layer.material === 'PEC') {
  527. // TODO: set PEC layer
  528. continue;
  529. }
  530. if (layer.material !== 'nk') {
  531. if ( layer.spline_n === undefined ) {
  532. this.notifyDanger('Failed to load material!');
  533. return;
  534. }
  535. if (layer.spline_n.xs[0] > WL
  536. || layer.spline_n.xs[layer.spline_n.xs.length-1] < WL) {
  537. this.notifyDanger('ERROR!!! Source parameters are out of material spectral range!');
  538. return;
  539. }
  540. layer.reN = layer.spline_n.at(WL);
  541. layer.imN = layer.spline_k.at(WL);
  542. }
  543. let reN = parseFloat(layer.reN);
  544. let imN = parseFloat(layer.imN);
  545. nmie.AddTargetLayerReIm( this.convertUnits2nm(this.units, R)*host,
  546. reN/host, imN/host);
  547. }
  548. nmie.SetModeNmaxAndType(-1, -1);
  549. nmie.SetWavelength(WL);
  550. nmie.RunMieCalculation();
  551. Qsca.push(nmie.GetQsca());
  552. Qabs.push(nmie.GetQabs());
  553. Qext.push(nmie.GetQsca()+nmie.GetQabs());
  554. mode_types.forEach(function (mode_type) {
  555. mode_n.forEach(function (n) {
  556. nmie.SetModeNmaxAndType(n, mode_type);
  557. nmie.RunMieCalculation();
  558. Qsca_n[mode_type][n - 1].push(nmie.GetQsca());
  559. Qabs_n[mode_type][n - 1].push(nmie.GetQabs());
  560. });
  561. });
  562. }
  563. this.simulationRuntime.Qsca = Qsca;
  564. this.simulationRuntime.Qabs = Qabs;
  565. this.simulationRuntime.Qext = Qext;
  566. this.simulationRuntime.Qsca_n = Qsca_n;
  567. this.simulationRuntime.Qabs_n = Qabs_n;
  568. let t1 = performance.now();
  569. this.ttime = ((t1 - t0) / 1000).toFixed(2);
  570. // console.log("It took " + this.ttime + " s.");
  571. this.plotData.pWLs = WLs.slice();
  572. this.plotData.pQsca = Qsca;
  573. this.plotData.pQabs = Qabs;
  574. this.plotData.pQext = Qext;
  575. this.plotData.pQsca_n = Qsca_n;
  576. this.plotData.pQabs_n = Qabs_n;
  577. this.changes++;
  578. },
  579. filterBug: function () {
  580. let Qsca = this.simulationRuntime.Qsca;
  581. let Qabs = this.simulationRuntime.Qabs;
  582. let Qext = this.simulationRuntime.Qext;
  583. let Qsca_n = this.simulationRuntime.Qsca_n;
  584. let Qabs_n = this.simulationRuntime.Qabs_n;
  585. let total_mode_n = this.simulationSetup.total_mode_n;
  586. for (let mode_type = 0; mode_type < 2; mode_type++) {
  587. for (let n = 0; n < total_mode_n; n++){
  588. this.filterMedian(Qsca_n[mode_type][n]);
  589. this.filterMedian(Qabs_n[mode_type][n]);
  590. }
  591. }
  592. this.filterMedian(Qsca);
  593. this.filterMedian(Qabs);
  594. for (let i = 0; i < Qsca.length; i++) {
  595. Qext[i] = Qsca[i] + Qabs[i];
  596. }
  597. // this.filterMedian(Qext);
  598. this.simulationRuntime.Qsca = Qsca;
  599. this.simulationRuntime.Qabs = Qabs;
  600. this.simulationRuntime.Qext = Qext;
  601. this.simulationRuntime.Qsca_n = Qsca_n;
  602. this.simulationRuntime.Qabs_n = Qabs_n;
  603. },
  604. filterMedian: function(spectra) {
  605. let l = spectra.length;
  606. let i;
  607. for (i = 1; i < l-1; i++) {
  608. let prev = spectra[i-1];
  609. let curr = spectra[i];
  610. let next = spectra[i+1];
  611. let diff1 = Math.abs((prev-curr)/curr);
  612. let diff2 = Math.abs((next-curr)/curr);
  613. if (diff1 > 0.3 && diff2 > 0.3) {
  614. spectra[i] = (prev+next)/2.0;
  615. }
  616. // console.log(spectra(i));
  617. }
  618. // return spectra;
  619. },
  620. setIsPlotMode: function () {
  621. let total_mode_n = this.simulationSetup.total_mode_n;
  622. total_mode_n++;
  623. let np1 = Number(total_mode_n);
  624. let mode_n = rangeInt(Number(np1), 0);
  625. let modeE = [];
  626. let modeH = [];
  627. mode_n.forEach(function (n) {
  628. if (n !== 0) {
  629. modeE.push(false);
  630. modeH.push(false);
  631. }
  632. });
  633. let saved_modes = this.simulationSetup.total_mode_n > this.simulationRuntime.total_mode_n_evaluated ?
  634. this.simulationRuntime.total_mode_n_evaluated : this.simulationSetup.total_mode_n;
  635. this.simulationRuntime.total_mode_n_evaluated = saved_modes;
  636. let oldModeE = this.plotSelector.isPlotModeE;
  637. let oldModeH = this.plotSelector.isPlotModeH;
  638. let ii;
  639. for (ii = 0; ii < saved_modes; ++ii) {
  640. if (ii < oldModeE.length) {
  641. modeE[ii] = oldModeE[ii];
  642. modeH[ii] = oldModeH[ii];
  643. }
  644. }
  645. this.plotSelector.isPlotModeE = modeE;
  646. this.plotSelector.isPlotModeH = modeH;
  647. },
  648. setXaxisTitle: function () {
  649. if (this.source_units.endsWith('Hz')) {
  650. this.chart.layout.xaxis.title = "Frequency, " + this.source_units;
  651. } else if (this.source_units.endsWith('eV')) {
  652. this.chart.layout.xaxis.title = "Energy, " + this.source_units;
  653. } else if (this.source_units.endsWith('s')) {
  654. this.chart.layout.xaxis.title = "Period, " + this.source_units;
  655. } else {
  656. this.chart.layout.xaxis.title = "Wavelength, " + this.source_units;
  657. }
  658. },
  659. setModeNNames: function () {
  660. let total_mode_n = this.simulationSetup.total_mode_n;
  661. total_mode_n++;
  662. let np1 = Number(total_mode_n);
  663. let mode_n = rangeInt(Number(np1), 0);
  664. let mode_n_names = [];
  665. mode_n.forEach(function (n) {
  666. if (n === 0) mode_n_names.push({id: 0, name: 'type'});
  667. else if (n === 1) mode_n_names.push({id: 1, name: 'dipole'});
  668. else if (n === 2) mode_n_names.push({id: 2, name: 'quadrupole'});
  669. else if (n === 3) mode_n_names.push({id: 3, name: 'octupole'});
  670. else mode_n_names.push({id: n, name: (Math.pow(2, n)).toString()});
  671. });
  672. this.simulationRuntime.mode_n_names = mode_n_names;
  673. },
  674. setQtotalChart: function () {
  675. let traceQsca, traceQabs, traceQext;
  676. traceQsca = {
  677. x: this.plotData.pWLs,
  678. y: this.plotData.pQsca,
  679. type: 'scatter',
  680. name: 'Qsca'
  681. };
  682. traceQabs = {
  683. x: this.plotData.pWLs,
  684. y: this.plotData.pQabs,
  685. type: 'scatter',
  686. name: 'Qabs'
  687. };
  688. traceQext = {
  689. x: this.plotData.pWLs,
  690. y: this.plotData.pQext,
  691. type: 'scatter',
  692. name: 'Qext'
  693. };
  694. this.chart.traces = [];
  695. if (this.plotSelector.isPlotQsca === true) this.chart.traces.push(traceQsca);
  696. if (this.plotSelector.isPlotQabs === true) this.chart.traces.push(traceQabs);
  697. if (this.plotSelector.isPlotQext === true) this.chart.traces.push(traceQext);
  698. },
  699. plotResults: function () {
  700. this.setQtotalChart();
  701. let mode_type, mode_n;
  702. let mode_n_names = this.simulationRuntime.mode_n_names;
  703. let mode_names = this.simulationRuntime.mode_names;
  704. for (mode_type = 0; mode_type < 2; ++mode_type) {
  705. for (mode_n = 0; mode_n < this.simulationRuntime.total_mode_n_evaluated; ++mode_n) {
  706. let is_mode_plot = mode_type === 0 ? this.plotSelector.isPlotModeE : this.plotSelector.isPlotModeH;
  707. if (is_mode_plot[mode_n] === false) continue;
  708. if (this.plotSelector.isPlotQsca === true) {
  709. let trace_sca = {
  710. x: this.plotData.pWLs,
  711. y: this.plotData.pQsca_n[mode_type][mode_n],
  712. type: 'scatter',
  713. name: 'Qsca ' + mode_names[mode_type] + ' ' + mode_n_names[mode_n + 1].name
  714. };
  715. this.chart.traces.push(trace_sca);
  716. }
  717. if (this.plotSelector.isPlotQabs === true) {
  718. let trace_abs = {
  719. x: this.plotData.pWLs,
  720. y: this.plotData.pQabs_n[mode_type][mode_n],
  721. type: 'scatter',
  722. name: 'Qabs ' + mode_names[mode_type] + ' ' + mode_n_names[mode_n + 1].name
  723. };
  724. this.chart.traces.push(trace_abs);
  725. }
  726. }
  727. }
  728. }
  729. },
  730. };
  731. </script>
  732. <style lang="scss">
  733. // Import Bulma's core
  734. @import "~bulma/sass/utilities/_all";
  735. // https://bulma.io/documentation/customize/variables/
  736. // $body-background-color: $green;
  737. // Set your colors
  738. $primary: #7957d5;
  739. $twitter: #4099FF;
  740. $twitter-invert: findColorInvert($twitter);
  741. // Setup $colors to use as bulma classes (e.g. 'is-twitter')
  742. $colors: (
  743. "white": ($white, $black),
  744. "black": ($black, $white),
  745. "light": ($light, $light-invert),
  746. "dark": ($dark, $dark-invert),
  747. "primary": ($primary, $primary-invert),
  748. "info": ($info, $info-invert),
  749. "success": ($success, $success-invert),
  750. "warning": ($warning, $warning-invert),
  751. "danger": ($danger, $danger-invert),
  752. "twitter": ($twitter, $twitter-invert)
  753. );
  754. // Links
  755. // $link: $primary;
  756. // $link-invert: $primary-invert;
  757. // $link-focus-border: $primary;
  758. // Import Bulma and Buefy styles
  759. @charset "utf-8";
  760. /*! bulma.io v0.7.5 | MIT License | github.com/jgthms/bulma */
  761. @import "~bulma/sass/utilities/_all";
  762. @import "~bulma/sass/base/_all";
  763. /*@import "~bulma/sass/elements/_all";*/
  764. @import "~bulma/sass/elements/box.sass";
  765. @import "~bulma/sass/elements/button.sass";
  766. @import "~bulma/sass/elements/container.sass";
  767. @import "~bulma/sass/elements/content.sass";
  768. /*@import "~bulma/sass/elements/icon.sass";*/
  769. @import "~bulma/sass/elements/image.sass";
  770. @import "~bulma/sass/elements/notification.sass";
  771. @import "~bulma/sass/elements/progress.sass";
  772. @import "~bulma/sass/elements/table.sass";
  773. @import "~bulma/sass/elements/tag.sass";
  774. @import "~bulma/sass/elements/title.sass";
  775. @import "~bulma/sass/elements/other.sass";
  776. @import "~bulma/sass/form/_all";
  777. /*@import "~bulma/sass/components/_all";*/
  778. @import "~bulma/sass/components/dropdown";
  779. @import "~bulma/sass/components/tabs";
  780. @import "~bulma/sass/components/modal";
  781. @import "~bulma/sass/components/message";
  782. @import "~bulma/sass/grid/_all";
  783. /*@import "~bulma/sass/layout/_all";*/
  784. // @import "~bulma";
  785. @import "~buefy/src/scss/buefy";
  786. .add_padding {
  787. padding: 1rem;
  788. }
  789. // Custom styles to build into the design of physics.ifmo.ru
  790. // npm run build && ./deploy.sh && xclip -sel c < dist/index.html
  791. .content table {
  792. width: auto;
  793. }
  794. ul {
  795. padding-left: 1.5em;
  796. }
  797. body {
  798. line-height: 1.42857;
  799. }
  800. /*.container {*/
  801. /* width: 750px;*/
  802. /*}*/
  803. h1 {
  804. font-size: 34px;
  805. font-weight: bold;
  806. }
  807. .block-views-blockmessages-header-message-block {
  808. top: 25px;
  809. }
  810. </style>