shell-generator.cc 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907
  1. //**********************************************************************************//
  2. // Copyright (C) 2009-2018 Ovidio Pena <ovidio@bytesfall.com> //
  3. // Copyright (C) 2013-2018 Konstantin Ladutenko <kostyfisik@gmail.com> //
  4. // //
  5. // This file is part of scattnlay //
  6. // //
  7. // This program is free software: you can redistribute it and/or modify //
  8. // it under the terms of the GNU General Public License as published by //
  9. // the Free Software Foundation, either version 3 of the License, or //
  10. // (at your option) any later version. //
  11. // //
  12. // This program is distributed in the hope that it will be useful, //
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of //
  14. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
  15. // GNU General Public License for more details. //
  16. // //
  17. // The only additional remark is that we expect that all publications //
  18. // describing work using this software, or all commercial products //
  19. // using it, cite at least one of the following references: //
  20. // [1] O. Pena and U. Pal, "Scattering of electromagnetic radiation by //
  21. // a multilayered sphere," Computer Physics Communications, //
  22. // vol. 180, Nov. 2009, pp. 2348-2354. //
  23. // [2] K. Ladutenko, U. Pal, A. Rivera, and O. Pena-Rodriguez, "Mie //
  24. // calculation of electromagnetic near-field for a multilayered //
  25. // sphere," Computer Physics Communications, vol. 214, May 2017, //
  26. // pp. 225-230. //
  27. // //
  28. // You should have received a copy of the GNU General Public License //
  29. // along with this program. If not, see <http://www.gnu.org/licenses/>. //
  30. //**********************************************************************************//
  31. // @brief Generates points for integration on sphere surface
  32. #include <algorithm>
  33. #include <cmath>
  34. #include <complex>
  35. #include <cstdio>
  36. #include <fstream>
  37. #include <iostream>
  38. #include <set>
  39. #include <sstream>
  40. #include <stdexcept>
  41. #include <string>
  42. #include <vector>
  43. #include "shell-generator.hpp"
  44. namespace shell_generator {
  45. template<class T> inline T pow2(const T value) {return value*value;}
  46. // ********************************************************************** //
  47. // ********************************************************************** //
  48. // ********************************************************************** //
  49. template<typename T, typename A> inline
  50. T dot(std::vector<T,A> const& a,
  51. std::vector<T,A> const& b) {
  52. return a[0]*b[0]+a[1]*b[1]+a[2]*b[2];
  53. // return std::inner_product(begin(a), end(a), begin(b),
  54. // static_cast<T>(0.0));
  55. }
  56. template<typename T, typename A> inline
  57. std::vector<T> cross(std::vector<T,A> const& a,
  58. std::vector<T,A> const& b) {
  59. std::vector<T> c = {
  60. a[1]*b[2]-a[2]*b[1],
  61. a[2]*b[0]-a[0]*b[2],
  62. a[0]*b[1]-a[1]*b[0]
  63. };
  64. return c;
  65. }
  66. // template<typename T, typename A> inline
  67. // std::vector<std::vector<T> > dyadic(std::vector<T,A> const& a,
  68. // std::vector<T,A> const& b) {
  69. // std::vector<std::vector<T> > c = {
  70. // {a[0]*b[0], a[0]*b[1], a[0]*b[2]},
  71. // {a[1]*b[0], a[1]*b[1], a[1]*b[2]},
  72. // {a[2]*b[0], a[2]*b[1], a[2]*b[2]}
  73. // };
  74. // return c;
  75. // }
  76. // template<typename T, typename A> inline
  77. // std::vector<std::vector<T>,A >
  78. // operator+(std::vector<std::vector<T>,A > const& a,
  79. // std::vector<std::vector<T>,A > const& b) {
  80. // std::vector<std::vector<T>,A > c = {
  81. // {a[0][0]+b[0][0], a[0][1]+b[0][1], a[0][2]+b[0][2]},
  82. // {a[1][0]+b[1][0], a[1][1]+b[1][1], a[1][2]+b[1][2]},
  83. // {a[2][0]+b[2][0], a[2][1]+b[2][1], a[2][2]+b[2][2]}
  84. // };
  85. // return c;
  86. // }
  87. template<typename T, typename A> inline
  88. std::vector<T,A >
  89. operator+(std::vector<T,A > const& a,
  90. std::vector<T,A > const& b) {
  91. std::vector<T,A > c = {a[0]+b[0],
  92. a[1]+b[1],
  93. a[2]+b[2]};
  94. return c;
  95. }
  96. template<typename T, typename A> inline
  97. std::vector<T,A >
  98. operator-(std::vector<T,A > const& a,
  99. std::vector<T,A > const& b) {
  100. std::vector<T,A > c = {a[0]-b[0],
  101. a[1]-b[1],
  102. a[2]-b[2]};
  103. return c;
  104. }
  105. // template<typename T, typename A> inline
  106. // std::vector<std::vector<T>,A >
  107. // operator-(std::vector<std::vector<T>,A > const& a,
  108. // std::vector<std::vector<T>,A > const& b) {
  109. // std::vector<std::vector<T>,A > c = {
  110. // {a[0][0]-b[0][0], a[0][1]-b[0][1], a[0][2]-b[0][2]},
  111. // {a[1][0]-b[1][0], a[1][1]-b[1][1], a[1][2]-b[1][2]},
  112. // {a[2][0]-b[2][0], a[2][1]-b[2][1], a[2][2]-b[2][2]}
  113. // };
  114. // return c;
  115. // }
  116. // template<typename T, typename A> inline
  117. // std::vector<std::vector<T>,A >
  118. // real(std::vector<std::vector<T>,A > const& a) {
  119. // std::vector<std::vector<T>,A > c = {
  120. // {a[0][0].real(), a[0][1].real(), a[0][2].real()},
  121. // {a[1][0].real(), a[1][1].real(), a[1][2].real()},
  122. // {a[2][0].real(), a[2][1].real(), a[2][2].real()}
  123. // };
  124. // return c;
  125. // }
  126. template<typename T, typename A> inline
  127. std::vector<T>
  128. real(std::vector<std::complex<T>,A > const& a) {
  129. std::vector<T> c = {a[0].real(),
  130. a[1].real(),
  131. a[2].real()};
  132. return c;
  133. }
  134. template<typename T, typename A> inline
  135. T real(std::complex<T> const& a) {
  136. return a.real();
  137. }
  138. template<typename T, typename A>
  139. std::vector< std::complex<T>,A > vconj(std::vector< std::complex<T>,A > const& a) {
  140. std::vector< std::complex<T>,A > b = {std::conj(a[0]),
  141. std::conj(a[1]),
  142. std::conj(a[2]) };
  143. // for (auto elem : a)
  144. // b.push_back(std::conj(elem));
  145. return b;
  146. }
  147. template<typename T1, typename T2, typename A>
  148. std::vector<T2,A> operator*(T1 const& a, std::vector< T2,A > const& b) {
  149. std::vector<T2,A > c = {a*b[0],
  150. a*b[1],
  151. a*b[2]};
  152. // for (auto elem : b)
  153. // c.push_back(a*elem);
  154. return c;
  155. }
  156. template<typename T1, typename T2, typename A>
  157. std::vector<T2,A> operator/(std::vector< T2,A > const& b, T1 const& a) {
  158. std::vector<T2,A > c = {b[0]/a,
  159. b[1]/a,
  160. b[2]/a};
  161. // for (auto elem : b)
  162. // c.push_back(a*elem);
  163. return c;
  164. }
  165. // ********************************************************************** //
  166. // ********************************************************************** //
  167. // ********************************************************************** //
  168. // ********************************************************************** //
  169. // ********************************************************************** //
  170. // ********************************************************************** //
  171. void ShellGenerator::RotateZ(double angle) {
  172. for(auto& p : vertices_) {
  173. double x,y;
  174. x = std::cos(angle)*p[0]-std::sin(angle)*p[1];
  175. y = std::sin(angle)*p[0]+std::cos(angle)*p[1];
  176. p[0] = x;
  177. p[1] = y;
  178. }
  179. }
  180. // ********************************************************************** //
  181. // ********************************************************************** //
  182. // ********************************************************************** //
  183. void ShellGenerator::RotateY(double angle) {
  184. for(auto& p : vertices_) {
  185. double x,z;
  186. x = std::cos(angle)*p[0]+std::sin(angle)*p[2];
  187. z = -std::sin(angle)*p[0]+std::cos(angle)*p[2];
  188. p[0] = x;
  189. p[2] = z;
  190. }
  191. }
  192. // ********************************************************************** //
  193. // ********************************************************************** //
  194. // ********************************************************************** //
  195. void ShellGenerator::RotateX(double angle) {
  196. for(auto& p : vertices_) {
  197. double y,z;
  198. y = std::cos(angle)*p[1]-std::sin(angle)*p[2];
  199. z = std::sin(angle)*p[1]+std::cos(angle)*p[2];
  200. p[1] = y;
  201. p[2] = z;
  202. }
  203. }
  204. // ********************************************************************** //
  205. // ********************************************************************** //
  206. // ********************************************************************** //
  207. void ShellGenerator::MoveX(double delta) {
  208. for(auto& p : vertices_) {
  209. p[0] += delta;
  210. }
  211. }
  212. // ********************************************************************** //
  213. // ********************************************************************** //
  214. // ********************************************************************** //
  215. void ShellGenerator::MoveY(double delta) {
  216. for(auto& p : vertices_) {
  217. p[1] += delta;
  218. }
  219. }
  220. // ********************************************************************** //
  221. // ********************************************************************** //
  222. // ********************************************************************** //
  223. void ShellGenerator::MoveZ(double delta) {
  224. for(auto& p : vertices_) {
  225. p[2] += delta;
  226. }
  227. }
  228. // ********************************************************************** //
  229. // ********************************************************************** //
  230. // ********************************************************************** //
  231. double ShellGenerator::IntegrateGaussSimple(double charge, double shift) {
  232. double integral = 0.0;
  233. // return field at point p from the charge, located at (shift, 0,0)
  234. auto field = [](double charge, double shift, std::vector<double> p){
  235. double r = std::sqrt(pow2(p[0]-shift) + pow2(p[1]) + pow2(p[2]) );
  236. //std::cout << "r: " << r << std::endl;
  237. const double pi = 3.1415926535897932384626433832795;
  238. double ampl = charge/(4.0*pi*pow2(r));
  239. std::vector<double> field = {ampl*(p[0]-shift)/r, ampl*(p[1])/r, ampl*(p[2])/r};
  240. return field;
  241. };
  242. //simple
  243. // for (auto vert :vertices_) {
  244. for (long unsigned int i = 0; i<face_centers_.size(); ++i) {
  245. auto vert = face_centers_[i];
  246. auto E0 = field(charge, shift, vert);
  247. // std::cout << "E0: ";
  248. for (auto component : E0) std::cout << component << " ";
  249. // std::cout << std::endl;
  250. // Vector to unit product
  251. double r = norm(vert);
  252. std::vector<double> unit = { vert[0]/r, vert[1]/r, vert[2]/r};
  253. // std::cout << norm(unit) << std::endl;
  254. for (int j =0; j < 3; ++j)
  255. integral += per_face_area_[i]*unit[j]*E0[j];
  256. }
  257. return integral;
  258. }
  259. // ********************************************************************** //
  260. // ********************************************************************** //
  261. // ********************************************************************** //
  262. double ShellGenerator::IntegrateGauss(double charge, double shift) {
  263. if (faces_.size() == 0)
  264. throw std::invalid_argument("Error! Faces were not initialized!\nSee IntegrateGaussSimple for using vertices information only.");
  265. double integral = 0.0;
  266. // return field at point p from the charge, located at (shift, 0,0)
  267. auto field = [](double charge, double shift, std::vector<double> p){
  268. double r = std::sqrt(pow2(p[0]-shift) + pow2(p[1]) + pow2(p[2]) );
  269. const double pi = 3.1415926535897932384626433832795;
  270. double ampl = charge/(4.0*pi*pow2(r));
  271. std::vector<double> field = {ampl*(p[0]-shift)/r, ampl*(p[1])/r, ampl*(p[2])/r};
  272. return field;
  273. };
  274. for(const auto face : faces_){
  275. std::vector<double> mean_vector = {0.0, 0.0, 0.0}, mean_point = {0.0, 0.0, 0.0};
  276. //Get mean
  277. for (int vert = 0; vert<3; ++vert) { //vertice
  278. auto point = vertices_[face[vert]];
  279. auto E0 = field(charge, shift, point);
  280. for (int i=0; i<3; ++i) {
  281. mean_vector[i] += E0[i]/3.0;
  282. mean_point[i] += point[i]/3.0;
  283. }
  284. }
  285. // Vector to unit product
  286. double r = norm(mean_point);
  287. std::vector<double> unit = { mean_point[0]/r, mean_point[1]/r, mean_point[2]/r};
  288. // std::cout << norm(unit) << std::endl;
  289. for (int i =0; i < 3; ++i)
  290. integral += face_area_*
  291. unit[i]*mean_vector[i];
  292. }
  293. return integral;
  294. }
  295. // ********************************************************************** //
  296. // ********************************************************************** //
  297. // ********************************************************************** //
  298. std::vector<double> ShellGenerator::IntegrateByComp() {
  299. std::vector<double> integral = {0.0, 0.0, 0.0};
  300. for (unsigned int i=0; i<E_.size(); ++i) {
  301. auto E = E_[i];
  302. auto H = H_[i];
  303. auto vert = face_centers_[i];
  304. double r = norm(vert);
  305. std::vector<double> n = { vert[0]/r, vert[1]/r, vert[2]/r};
  306. const std::vector< std::vector<double> > d = {{1.0, 0.0, 0.0},
  307. {0.0, 1.0, 0.0},
  308. {0.0, 0.0, 1.0}};
  309. std::vector<double> F = {0.0, 0.0, 0.0};
  310. std::complex<double> S(0.0);
  311. for (int ii = 0; ii < 3; ++ii)
  312. S += E[ii]*std::conj(E[ii]) + H[ii]*std::conj(H[ii]);
  313. std::vector< std::vector<std::complex<double> > >
  314. T = {{0.0, 0.0, 0.0},
  315. {0.0, 0.0, 0.0},
  316. {0.0, 0.0, 0.0}};
  317. for (int i = 0; i < 3; ++i) {
  318. for (int j = 0; j < 3; ++j) {
  319. T[i][j] = E[i]*std::conj(E[j]) + H[i]*std::conj(H[j])
  320. -1.0/2.0*S*d[i][j];
  321. F[i] += (1/(2.0/* *4.0*pi */))*real(T[i][j]*n[j]);
  322. }
  323. }
  324. integral = integral + per_face_area_[i]*F;
  325. }
  326. return integral;
  327. }
  328. // ********************************************************************** //
  329. // ********************************************************************** //
  330. // ********************************************************************** //
  331. std::vector<double> ShellGenerator::IntegrateByCompReal() {
  332. std::vector<double> integral = {0.0, 0.0, 0.0};
  333. for (unsigned int i=0; i<E_.size(); ++i) {
  334. auto E = E_[i];
  335. auto H = H_[i];
  336. auto vert = face_centers_[i];
  337. double r = norm(vert);
  338. std::vector<double> n = { vert[0]/r, vert[1]/r, vert[2]/r};
  339. const std::vector< std::vector<double> > d = {{1.0, 0.0, 0.0},
  340. {0.0, 1.0, 0.0},
  341. {0.0, 0.0, 1.0}};
  342. std::vector<double> F = {0.0, 0.0, 0.0};
  343. std::complex<double> S(0.0);
  344. for (int ii = 0; ii < 3; ++ii)
  345. S += pow2(real(E[ii])) + pow2(real(H[ii]));
  346. std::vector< std::vector<std::complex<double> > >
  347. T = {{0.0, 0.0, 0.0},
  348. {0.0, 0.0, 0.0},
  349. {0.0, 0.0, 0.0}};
  350. for (int i = 0; i < 3; ++i) {
  351. for (int j = 0; j < 3; ++j) {
  352. T[i][j] = real(E[i])*real(E[j]) + real(H[i])*real(H[j])
  353. -1.0/2.0*S*d[i][j];
  354. F[i] += (1/(2.0/* *4.0*pi */))*real(T[i][j]*n[j]);
  355. }
  356. }
  357. integral = integral + per_face_area_[i]*F;
  358. }
  359. return integral;
  360. }
  361. // ********************************************************************** //
  362. // ********************************************************************** //
  363. // ********************************************************************** //
  364. std::vector<double> ShellGenerator::IntegrateByFaces() {
  365. std::vector<double> integral = {0.0, 0.0, 0.0};
  366. //simple
  367. for (long unsigned int i=0; i<E_.size(); ++i) {
  368. //std::cout << i << " ";
  369. auto E = E_[i];
  370. //auto H = 377.0*H_[i];
  371. auto H = H_[i];
  372. // auto Es = Es_[i];
  373. // auto Hs = Hs_[i];
  374. auto vert = face_centers_[i];
  375. // Vector to unit product
  376. double r = norm(vert);
  377. //std::vector<std::complex<double> > unit = { vert[0]/r, vert[1]/r, vert[2]/r};
  378. // std::cout << norm(unit) << std::endl;
  379. //const double pi = 3.1415926535897932384626433832795;
  380. // std::vector<double> P = (1/(2.0))
  381. // *real(
  382. // dot(unit,E)*vconj(E) +
  383. // dot(unit,H)*vconj(H) +
  384. // (-1.0/2.0)*(dot(E,vconj(E))
  385. // +dot(H,vconj(H))
  386. // )*unit
  387. // );
  388. // std::vector<double> P = (1/(2.0))
  389. // *real(
  390. // Es[0]*vconj(E) +
  391. // Hs[0]*vconj(H) +
  392. // (-1.0/2.0)*(dot(E,vconj(E))
  393. // +dot(H,vconj(H))
  394. // )*unit
  395. // );
  396. // std::vector<double> P = (1/(2.0))
  397. // *(
  398. // real(dot(unit,E)*vconj(E)) +
  399. // real(dot(unit,H)*vconj(H))) +
  400. // (-1.0/4.0)*(dot(E,vconj(E))*unit
  401. // +dot(H,vconj(H))*unit
  402. // )
  403. // );
  404. // auto
  405. // std::cout <<"E "<<E[0]<<", "<< E[1] <<", "<<E[2] << std::endl;
  406. // std::cout <<"H "<<H[0]<<", "<< H[1] <<", "<<H[2] << std::endl;
  407. // std::cout <<"vert "<<vert[0]<<", "<< vert[1] <<", "<<vert[2] << std::endl<<std::endl;
  408. //integral = integral + per_face_area_[i]*P;
  409. // // Test Poynting vector integration in real components -- WRONG
  410. // std::vector<double> unit = { vert[0]/r, vert[1]/r, vert[2]/r};
  411. // std::vector<double> P = (1/(2.0))
  412. // *(cross((real(E)),real(H)));
  413. // integral[0] = integral[0] + per_face_area_[i]*dot(P,unit);
  414. // Test Poynting vector integration
  415. std::vector<double> unit = { vert[0]/r, vert[1]/r, vert[2]/r};
  416. std::vector<double> P = (1/(2.0))
  417. *real(cross(E,vconj(H)));
  418. //integral[0] = integral[0] + per_face_area_[i]*dot(P,unit);
  419. integral = integral + per_face_area_[i]*P;
  420. }
  421. return integral;
  422. }
  423. // ********************************************************************** //
  424. // ********************************************************************** //
  425. // ********************************************************************** //
  426. std::vector<double> ShellGenerator::Integrate() {
  427. std::vector<double> integral = {0.0, 0.0, 0.0};
  428. //simple
  429. for (unsigned int i=0; i<E_.size(); ++i) {
  430. auto E = E_[i];
  431. //auto H = 377.0*H_[i];
  432. auto H = H_[i];
  433. auto vert = vertices_[i];
  434. // Vector to unit product
  435. double r = norm(vert);
  436. std::vector<std::complex<double> > unit = { vert[0]/r, vert[1]/r, vert[2]/r};
  437. // std::cout << norm(unit) << std::endl;
  438. //const double pi = 3.1415926535897932384626433832795;
  439. std::vector<double> P = (1/(2.0))
  440. *real(
  441. dot(unit,E)*vconj(E) +
  442. dot(unit,H)*vconj(H) +
  443. (-1.0/2.0)*(dot(E,vconj(E))
  444. +dot(H,vconj(H))
  445. )*unit
  446. );
  447. // auto std::cout <<"E "<<E[0]<<", "<< E[1] <<", "<<E[2] << std::endl;
  448. // std::cout <<"H "<<H[0]<<", "<< H[1] <<", "<<H[2] << std::endl;
  449. // std::cout <<"vert "<<vert[0]<<", "<< vert[1] <<", "<<vert[2] << std::endl<<std::endl;
  450. integral = integral + per_vertice_area_*P;
  451. }
  452. return integral;
  453. }
  454. // ********************************************************************** //
  455. // ********************************************************************** //
  456. // ********************************************************************** //
  457. std::vector< std::vector<double> > ShellGenerator::GetVerticesT() {
  458. std::vector< std::vector<double> > vertices_t;
  459. vertices_t.resize(3);
  460. for(const auto vert : vertices_){
  461. vertices_t[0].push_back(vert[0]);
  462. vertices_t[1].push_back(vert[1]);
  463. vertices_t[2].push_back(vert[2]);
  464. }
  465. return vertices_t;
  466. }
  467. // ********************************************************************** //
  468. // ********************************************************************** //
  469. // ********************************************************************** //
  470. std::vector< std::vector<double> > ShellGenerator::GetFaceCentersT() {
  471. EvalFaces();
  472. std::vector< std::vector<double> > vertices_t;
  473. vertices_t.resize(3);
  474. for(const auto vert : face_centers_){
  475. vertices_t[0].push_back(vert[0]);
  476. vertices_t[1].push_back(vert[1]);
  477. vertices_t[2].push_back(vert[2]);
  478. }
  479. return vertices_t;
  480. }
  481. // ********************************************************************** //
  482. // ********************************************************************** //
  483. // ********************************************************************** //
  484. double ShellGenerator::norm(std::vector<double> a){
  485. double norm_value = 0;
  486. for (auto coord:a)
  487. norm_value += pow2(coord);
  488. return std::sqrt(norm_value);
  489. }
  490. // ********************************************************************** //
  491. // ********************************************************************** //
  492. // ********************************************************************** //
  493. void ShellGenerator::Rescale(double scale) {
  494. for(auto& vert : vertices_){
  495. double factor = norm(vert);
  496. //std::cout<< factor <<std::endl;
  497. for (auto &coord:vert) {
  498. coord = coord*scale/factor;
  499. }
  500. //std::cout << " " << norm(vert) << " ";
  501. }
  502. const double pi = 3.1415926535897932384626433832795;
  503. double area = 4.0*pi*pow2(scale);
  504. //face_area_ = area/faces_.size();
  505. per_vertice_area_ = area/vertices_.size();
  506. //std::cout << "Per verice area: " << per_vertice_area_ << std::endl;
  507. }
  508. // ********************************************************************** //
  509. // ********************************************************************** //
  510. // ********************************************************************** //
  511. void ShellGenerator::PrintVerts() {
  512. std::cout << "Verts coords:" << std::endl;
  513. for(auto vert : vertices_){
  514. std::cout <<"(";
  515. for (auto coord:vert) std::cout<<coord<<",";
  516. std::cout <<"),";
  517. }
  518. std::cout << std::endl;
  519. }
  520. // ********************************************************************** //
  521. // ********************************************************************** //
  522. // ********************************************************************** //
  523. void ShellGenerator::EvalFaces() {
  524. face_centers_.clear();
  525. per_face_area_.clear();
  526. for (auto face : faces_) {
  527. std::set<long unsigned int> edge_points;
  528. for (auto edge : face) {
  529. edge_points.insert(edges_[edge][0]);
  530. edge_points.insert(edges_[edge][1]);
  531. }
  532. std::vector<double> mid_point({0.0, 0.0, 0.0});
  533. for (auto point : edge_points) {
  534. mid_point = mid_point + vertices_[point];
  535. }
  536. mid_point = mid_point/3.0;
  537. face_centers_.push_back(mid_point);
  538. std::vector<long unsigned int> v_edge_points( edge_points.begin(),
  539. edge_points.end() );
  540. auto vec_a = vertices_[v_edge_points[1]] - vertices_[v_edge_points[0]];
  541. auto vec_b = vertices_[v_edge_points[2]] - vertices_[v_edge_points[0]];
  542. auto area = norm(cross(vec_a, vec_b))/2.0;
  543. per_face_area_.push_back(area);
  544. //std::cout << "Area " <<area<<std::endl;
  545. } // end for face in faces_
  546. double total_flat_area = 0.0;
  547. for (auto face:per_face_area_)
  548. total_flat_area += face;
  549. auto scale = norm(vertices_[0]);
  550. const double pi = 3.1415926535897932384626433832795;
  551. double area = 4.0*pi*pow2(scale);
  552. face_area_ = area/faces_.size();
  553. double area_scale = area/total_flat_area;
  554. for (auto& face:per_face_area_)
  555. face *= area_scale;
  556. for(auto& vert : face_centers_){
  557. double factor = norm(vert);
  558. //std::cout<< factor <<std::endl;
  559. for (auto &coord:vert) {
  560. coord*=scale/factor;
  561. }
  562. //std::cout << " " << norm(vert) << " ";
  563. }
  564. // std::cout << "total face centers: " << face_centers_.size()
  565. // << " scale " << scale
  566. // << " face_norm " << norm(face_centers_[0])
  567. // << " area-int " << face_area_
  568. // << std::endl;
  569. }
  570. // ********************************************************************** //
  571. // ********************************************************************** //
  572. // ********************************************************************** //
  573. void ShellGenerator::Refine() {
  574. for (auto &edge : edges_) {
  575. auto p0 = vertices_[edge[0]];
  576. auto p1 = vertices_[edge[1]];
  577. std::vector<double> new_point = {
  578. (p0[0]+p1[0])/2.0,
  579. (p0[1]+p1[1])/2.0,
  580. (p0[2]+p1[2])/2.0};
  581. vertices_.push_back(new_point);
  582. edge.push_back(vertices_.size()-1); // the last index is for the new mid-point
  583. }
  584. std::cout << "new verts: " << vertices_.size() <<std::endl;
  585. // std::cout << "extended edges:" <<std::endl;
  586. // for (auto edge : edges_) {
  587. // std::cout<< "\t"<< edge[0]<< "\t"<< edge[1]<< "\t"<< edge[2]<<std::endl;
  588. // }
  589. refined_edges_.clear();
  590. for (auto edge : edges_) {
  591. // Important! New (refined) point goes the last!
  592. std::vector<long unsigned int> edge_a = {edge[0],edge[2]};
  593. std::vector<long unsigned int> edge_b = {edge[1],edge[2]};
  594. refined_edges_.push_back(edge_a);
  595. refined_edges_.push_back(edge_b);
  596. }
  597. // Now we need to count edges inside old faces.
  598. refined_faces_.clear();
  599. for (auto face : faces_) {
  600. auto point_a = edges_[face[0]][2];
  601. auto point_b = edges_[face[1]][2];
  602. auto point_c = edges_[face[2]][2];
  603. // std::cout << "\tedges_old: " <<face[0]<<" "<<face[1]<<" "<<face[2]<<" "<<std::endl;
  604. // std::cout << "\tpoints_old_edge0: " <<edges_[face[0]][0]<<" "<<edges_[face[0]][1]<<" "<<edges_[face[0]][2]<<" "<<std::endl;
  605. // std::cout << "\tpoints_old_edge0: " <<edges_[face[1]][0]<<" "<<edges_[face[1]][1]<<" "<<edges_[face[1]][2]<<" "<<std::endl;
  606. // std::cout << "\tpoints_old_edge0: " <<edges_[face[2]][0]<<" "<<edges_[face[2]][1]<<" "<<edges_[face[2]][2]<<" "<<std::endl;
  607. // std::cout<<"\trefined points: "<<point_a<<" "<<point_b<<" "<<point_c<<std::endl;
  608. std::vector<long unsigned int> edge_c = {point_a, point_b};
  609. std::vector<long unsigned int> edge_a = {point_b, point_c};
  610. std::vector<long unsigned int> edge_b = {point_c, point_a};
  611. refined_edges_.push_back(edge_a);
  612. auto edge_a_index = refined_edges_.size()-1;
  613. refined_edges_.push_back(edge_b);
  614. auto edge_b_index = refined_edges_.size()-1;
  615. refined_edges_.push_back(edge_c);
  616. auto edge_c_index = refined_edges_.size()-1;
  617. /*
  618. // /\ contrcloсkwise
  619. // c 1
  620. // 0 b
  621. // /__a___\ edge_a
  622. // /\ /\
  623. // c \ / 0
  624. // 1 \ / b
  625. // edge_0a /__0a__\/__1a__\ edge_1a
  626. //
  627. // remember! In edge_0a the refined point is [1], etc.
  628. */
  629. auto edge_0a = refined_edges_[2*face[0]];
  630. auto edge_1a = refined_edges_[2*face[0]+1];
  631. auto edge_0b = refined_edges_[2*face[1]];
  632. auto edge_1b = refined_edges_[2*face[1]+1];
  633. auto edge_0c = refined_edges_[2*face[2]];
  634. auto edge_1c = refined_edges_[2*face[2]+1];
  635. auto edge_0a_index = 2*face[0];
  636. auto edge_1a_index = 2*face[0]+1;
  637. auto edge_0b_index = 2*face[1];
  638. auto edge_1b_index = 2*face[1]+1;
  639. auto edge_0c_index = 2*face[2];
  640. auto edge_1c_index = 2*face[2]+1;
  641. // Orient:
  642. // Try contrcloсkwise:
  643. bool isClockwise = false, is_b_swapped = false, is_c_swapped=false;
  644. if (edge_0a[0]!=edge_1c[0]) {
  645. edge_1c.swap(edge_0c);
  646. is_c_swapped = !is_c_swapped;
  647. }
  648. if (edge_1a[0]!=edge_0b[0]) {
  649. edge_0b.swap(edge_1b);
  650. is_b_swapped = !is_b_swapped;
  651. }
  652. if (edge_1b[0]!=edge_0c[0]) {
  653. isClockwise = true;
  654. //Try clockwise:
  655. if (edge_0a[0]!=edge_1b[0]) {
  656. edge_1b.swap(edge_0b);
  657. is_b_swapped = !is_b_swapped;
  658. }
  659. if (edge_1a[0]!=edge_0c[0]) {
  660. edge_0c.swap(edge_1c);
  661. is_c_swapped = !is_c_swapped;
  662. }
  663. if (edge_1c[0]!=edge_0b[0])
  664. throw std::invalid_argument("Error! Unable to orient edges of refined face!\n");
  665. }
  666. if (is_b_swapped) {
  667. edge_1b_index = 2*face[1];
  668. edge_0b_index = 2*face[1]+1;
  669. }
  670. if (is_c_swapped) {
  671. edge_1c_index = 2*face[2];
  672. edge_0c_index = 2*face[2]+1;
  673. }
  674. /*
  675. // /\ clockwise
  676. // b 1
  677. // 0 c
  678. // /__a___\ edge_a
  679. // /\ /\
  680. // b \ / 0
  681. // 1 \ / c
  682. // edge_0a /__0a__\/__1a__\ edge_1a
  683. //
  684. */
  685. //Build new facets:
  686. // if isClockwise
  687. std::vector<long unsigned int> face1({edge_0a_index, edge_1b_index, edge_c_index});
  688. std::vector<long unsigned int> face2({edge_1a_index, edge_0c_index, edge_b_index});
  689. std::vector<long unsigned int> face3({edge_0b_index, edge_1c_index, edge_a_index});
  690. std::vector<long unsigned int> face4({edge_a_index, edge_b_index, edge_c_index});
  691. if (!isClockwise) {
  692. face1 = std::vector<long unsigned int>({edge_0a_index, edge_1c_index, edge_b_index});
  693. face2 = std::vector<long unsigned int>({edge_1a_index, edge_0b_index, edge_c_index});
  694. face3 = std::vector<long unsigned int>({edge_1b_index, edge_0c_index, edge_a_index});
  695. face4 = std::vector<long unsigned int>({edge_a_index, edge_b_index, edge_c_index});
  696. }
  697. // std::cout<< "\tface1\t"<< face1[0]<< "\t"<< face1[1]<< "\t"<< face1[2]<<std::endl;
  698. // std::cout<< "\tface2\t"<< face2[0]<< "\t"<< face2[1]<< "\t"<< face2[2]<<std::endl;
  699. // std::cout<< "\tface3\t"<< face3[0]<< "\t"<< face3[1]<< "\t"<< face3[2]<<std::endl;
  700. // std::cout<< "\tface4\t"<< face4[0]<< "\t"<< face4[1]<< "\t"<< face4[2]<<std::endl;
  701. refined_faces_.push_back(face1);
  702. refined_faces_.push_back(face2);
  703. refined_faces_.push_back(face3);
  704. refined_faces_.push_back(face4);
  705. // std::cout<<"ref edges size: " << refined_edges_.size()<< std::endl;
  706. // std::cout << "Face1 points: "<< refined_edges_[face1[0]][0]
  707. // << " " << refined_edges_[face1[0]][1] << " -- "
  708. // << refined_edges_[face1[1]][0]
  709. // << " " << refined_edges_[face1[1]][1] << " -- "
  710. // << refined_edges_[face1[2]][0]
  711. // << " " << refined_edges_[face1[2]][1] << std::endl;
  712. } // end for faces_
  713. std::cout << "new edges: " << refined_edges_.size() <<std::endl;
  714. std::cout << "new faces: " << refined_faces_.size() <<std::endl;
  715. edges_.clear();
  716. edges_ = refined_edges_;
  717. // std::cout << "edges:" <<std::endl;
  718. // for (auto edge : edges_) {
  719. // std::cout<< " "<< edge[0]<< "\t"<< edge[1]<<std::endl;
  720. // }
  721. faces_.clear();
  722. faces_ = refined_faces_;
  723. //Rescale(1.0);
  724. //GenerateEdges();
  725. // GenerateFaces();
  726. }
  727. // ********************************************************************** //
  728. // ********************************************************************** //
  729. // ********************************************************************** //
  730. void ShellGenerator::GenerateFacesInit() {
  731. faces_.clear();
  732. for (unsigned int i = 0; i < edges_.size(); ++i) {
  733. const auto ie = edges_[i];
  734. for(unsigned int j = i + 1; j < edges_.size(); ++j) {
  735. const auto je = edges_[j];
  736. for(unsigned int k = j + 1; k < edges_.size(); ++k) {
  737. const auto ke = edges_[k];
  738. std::set<long unsigned int> edges = {ie[0],ie[1],
  739. je[0],je[1],
  740. ke[0],ke[1]};
  741. if (edges.size() != 3) continue;
  742. std::vector<long unsigned int> face({i,j,k});
  743. // std::cout << ie[0]<<"-"<<ie[1] << ":"
  744. // << je[0]<<"-"<<je[1] << ":"
  745. // << ke[0]<<"-"<<ke[1]
  746. // << std::endl;
  747. // std::cout << face[0]<<"-"<<face[1] << "-"<<face[2]<<std::endl;
  748. faces_.push_back(face);
  749. }
  750. }
  751. }
  752. std::cout << "Faces: "<< faces_.size() <<std::endl;
  753. }
  754. // ********************************************************************** //
  755. // ********************************************************************** //
  756. // ********************************************************************** //
  757. void ShellGenerator::GenerateEdgesInit() {
  758. std::cout << "Vertices: "<< vertices_.size() <<std::endl;
  759. edges_.clear();
  760. EvalEdgeLength();
  761. for (unsigned int i = 0; i < vertices_.size(); ++i)
  762. for(unsigned int j = i + 1; j < vertices_.size(); ++j) {
  763. //std::cout << i<< " " << j<< " == "<< dist(vertices_[i],vertices_[j]) <<std::endl;
  764. if (dist(vertices_[i],vertices_[j]) > 1.000001*edge_length_) continue;
  765. std::vector<long unsigned int> edge = {i,j};
  766. // std::cout << i<< " " << j << " : i=(";
  767. // for (auto v : vertices_[i]) std::cout << v <<",";
  768. // std::cout<<") j=(";
  769. // for (auto v : vertices_[j]) std::cout << v <<",";
  770. // std::cout<<")"<<std::endl;
  771. edges_.push_back(edge);
  772. }
  773. std::cout << "Edges: "<< edges_.size() <<std::endl;
  774. }
  775. // ********************************************************************** //
  776. // ********************************************************************** //
  777. // ********************************************************************** //
  778. void ShellGenerator::EvalEdgeLength() {
  779. auto p0 = vertices_[0];
  780. std::vector<double> zero(p0.size(), 0.0);
  781. double min_dist = 42.0*dist(zero, p0);
  782. for (auto point : vertices_) {
  783. if (point == p0) continue;
  784. double new_dist = dist(p0, point);
  785. if (new_dist < min_dist) min_dist = new_dist;
  786. }
  787. //std::cout << "Edge length = " << min_dist << std::endl;
  788. edge_length_ = min_dist;
  789. }
  790. // ********************************************************************** //
  791. // ********************************************************************** //
  792. // ********************************************************************** //
  793. double ShellGenerator::dist(std::vector<double> a, std::vector<double> b) {
  794. unsigned int len = a.size();
  795. if (b.size() != len)
  796. throw std::invalid_argument("Error! Vector need to be the same size!\n");
  797. double distance = 0.0;
  798. for (unsigned int i = 0; i<len; ++i) {
  799. distance += pow2(a[i]-b[i]);
  800. }
  801. return std::sqrt(distance);
  802. }
  803. // ********************************************************************** //
  804. // ********************************************************************** //
  805. // ********************************************************************** //
  806. // @brief set up regular icosahedron
  807. void ShellGenerator::SetInitialVerticesIcosahedron() {
  808. double a = 0.0;
  809. double b = 1.0;
  810. double c = (1+std::sqrt(5.0))/2.0;
  811. std::vector< std::vector<double> > points = {
  812. {a, b, c},
  813. {a, b,-c},
  814. {a,-b, c},
  815. {a,-b,-c},
  816. { b, c,a},
  817. { b,-c,a},
  818. {-b, c,a},
  819. {-b,-c,a},
  820. { c,a, b},
  821. {-c,a, b},
  822. { c,a,-b},
  823. {-c,a,-b}
  824. };
  825. vertices_ = std::move(points);
  826. //Rescale(1.0);
  827. //std::vector< std::vector<double> > points_debug = {{1,0,0},{-1,0,0}};
  828. //std::vector< std::vector<double> > points_debug = {{0,1,0},{0,-1,0}};
  829. //std::vector< std::vector<double> > points_debug = {{1,1,0},{1,-1,0},{-1,-1,0},{-1,1,0}};
  830. //std::vector< std::vector<double> > points_debug = {{0,1,1},{0,1,-1},{0,-1,-1},{0,-1,1}};
  831. //std::vector< std::vector<double> > points_debug = {};
  832. // std::vector< std::vector<double> > points_debug = {{0,0,1},{0,0,-1}};
  833. //vertices_ = std::move(points_debug);
  834. // for (auto v : vertices_) {
  835. // for (auto p : v)
  836. // std::cout<< p<<std::endl;
  837. // }
  838. }
  839. // ********************************************************************** //
  840. // ********************************************************************** //
  841. // ********************************************************************** //
  842. // @brief set up regular icosahedron
  843. void ShellGenerator::SetInitialVerticesTetrahedron() {
  844. double a = 1.0;
  845. double b = 1.0;
  846. double c = 1.0;
  847. std::vector< std::vector<double> > points = {
  848. {a, b, c},
  849. {a, -b,-c},
  850. {-a,-b, c},
  851. {-a, b,-c}
  852. };
  853. vertices_ = std::move(points);
  854. //Rescale(1.0);
  855. //vertices_ = std::move(points_debug);
  856. // for (auto v : vertices_) {
  857. // for (auto p : v)
  858. // std::cout<< p<<std::endl;
  859. // }
  860. }
  861. // ********************************************************************** //
  862. // ********************************************************************** //
  863. // ********************************************************************** //
  864. void ShellGenerator::Init() {
  865. SetInitialVerticesIcosahedron();
  866. //SetInitialVerticesTetrahedron();
  867. GenerateEdgesInit();
  868. GenerateFacesInit();
  869. }
  870. } // end of namespace read_spectra