shell-generator.cc 38 KB

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