PageRenderTime 47ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/src/lib/library/factory.cpp

https://gitlab.com/philipclaude/avro2
C++ | 312 lines | 247 code | 41 blank | 24 comment | 83 complexity | 50cdf01a16b2bb9125e79430c91a0414 MD5 | raw file
  1. //
  2. // avro - Adaptive Voronoi Remesher
  3. //
  4. // Copyright 2017-2022, Philip Claude Caplan
  5. // All rights reserved
  6. //
  7. // Licensed under The GNU Lesser General Public License, version 2.1
  8. // See http://www.opensource.org/licenses/lgpl-2.1.php
  9. //
  10. #include "adaptation/metric.h"
  11. #include "common/directory.h"
  12. #include "geometry/egads/context.h"
  13. #include "geometry/egads/model.h"
  14. #include "library/ckf.h"
  15. #include "library/egads.h"
  16. #include "library/factory.h"
  17. #include "library/field.h"
  18. #include "library/meshb.h"
  19. #include "library/metric.h"
  20. #include "library/tesseract.h"
  21. #include "mesh/mesh.h"
  22. #include "mesh/points.h"
  23. #include <fstream>
  24. namespace avro
  25. {
  26. namespace library
  27. {
  28. std::shared_ptr<MetricAttachment>
  29. get_metric( const std::string& name , Points& points , bool& is_analytic ,
  30. const std::vector<real_t>& params ) {
  31. // default to discrete metric field
  32. is_analytic = false;
  33. // get the file extension
  34. std::string ext = get_file_ext(name);
  35. // if there is a file extension, read the mesh
  36. if (ext == "sol" || ext == "solb") {
  37. // read the file
  38. std::shared_ptr<MetricAttachment> pfld = std::make_shared<MetricAttachment>(points);
  39. pfld->from_solb(name);
  40. return pfld;
  41. }
  42. is_analytic = true;
  43. if (name == "Uniform") {
  44. avro_assert(params.size() == 2);
  45. coord_t dim = 0;
  46. real_t h = 1;
  47. if (params.size() > 0) {
  48. dim = coord_t(params[0]);
  49. h = params[1];
  50. }
  51. MetricField_Uniform analytic(dim,h);
  52. return std::make_shared<MetricAttachment>(analytic,points);
  53. }
  54. if (name == "Linear-2d") {
  55. MetricField_UGAWG_Linear2d analytic;
  56. return std::make_shared<MetricAttachment>(analytic,points);
  57. }
  58. if (name == "Linear-3d") {
  59. MetricField_UGAWG_Linear analytic;
  60. return std::make_shared<MetricAttachment>(analytic,points);
  61. }
  62. if (name == "Polar1") {
  63. MetricField_UGAWG_Polar1 analytic;
  64. return std::make_shared<MetricAttachment>(analytic,points);
  65. }
  66. if (name == "Polar2") {
  67. MetricField_UGAWG_Polar2 analytic;
  68. return std::make_shared<MetricAttachment>(analytic,points);
  69. }
  70. if (name == "Linear-4d") {
  71. real_t hmin = MetricField_Tesseract_Linear::hmin_default;
  72. if (params.size() > 0) hmin = params[0];
  73. MetricField_Tesseract_Linear analytic(hmin);
  74. return std::make_shared<MetricAttachment>(analytic,points);
  75. }
  76. if (name == "RotatingBL-3d") {
  77. MetricField_Cube_RotatingBoundaryLayer analytic;
  78. return std::make_shared<MetricAttachment>(analytic,points);
  79. }
  80. if (name == "RotatingBL-4d") {
  81. MetricField_Tesseract_RotatingBoundaryLayer analytic;
  82. return std::make_shared<MetricAttachment>(analytic,points);
  83. }
  84. if (name == "MovingCylinder-4d") {
  85. MetricField_Tesseract_MovingCylinder analytic;
  86. return std::make_shared<MetricAttachment>(analytic,points);
  87. }
  88. if (name == "Wave-3d") {
  89. MetricField_Cube_Wave analytic;
  90. return std::make_shared<MetricAttachment>(analytic,points);
  91. }
  92. if (name == "Wave-4d") {
  93. MetricField_Tesseract_Wave analytic;
  94. return std::make_shared<MetricAttachment>(analytic,points);
  95. }
  96. avro_assert_not_reached;
  97. return nullptr;
  98. }
  99. std::shared_ptr<Model>
  100. get_geometry( const std::string& name , bool& curved ) {
  101. // get the file extension
  102. std::string ext = get_file_ext(name);
  103. // check if this is an egads file
  104. if (ext == "egads" || ext == "legads") {
  105. curved = true;
  106. std::shared_ptr<EGADS::Model> pmodel = std::make_shared<EGADS::Model>(name);
  107. return pmodel;
  108. }
  109. // lookup the geometry in the library
  110. std::shared_ptr<Model> pmodel = std::make_shared<Model>(0);
  111. std::shared_ptr<Body> pbody = nullptr;
  112. if (name == "tesseract" || name == "tesseract-closingwall" || name == "tesseract-expansion") {
  113. curved = false;
  114. std::vector<real_t> c(4,0.5);
  115. std::vector<real_t> lengths(4,1.0);
  116. std::shared_ptr<Model> pmodel = std::make_shared<Model>(3);
  117. pbody = std::make_shared<library::Tesseract>(c,lengths);
  118. library::Tesseract& body = static_cast<library::Tesseract&>(*pbody);
  119. if (name == "tesseract-closingwall") {
  120. body.map_to( &library::Tesseract::closingwall);
  121. }
  122. else if (name == "tesseract-expansion") {
  123. body.map_to( &library::Tesseract::expansion );
  124. }
  125. }
  126. if (name == "box") {
  127. curved = false;
  128. real_t x0[3] = {0,0,0};
  129. std::shared_ptr<EGADS::Model> emodel = std::make_shared<EGADS::Model>(2);
  130. const EGADS::Context* context = &emodel->context();
  131. std::vector<real_t> lengths(3,1);
  132. pbody = std::make_shared<EGADS::Cube>(context,lengths,x0);
  133. emodel->add_body(pbody);
  134. emodel->build();
  135. pmodel = emodel;
  136. }
  137. if (name == "square") {
  138. curved = false;
  139. //real_t x0[3] = {0.5,0.5,0.};
  140. std::shared_ptr<EGADS::Model> emodel = std::make_shared<EGADS::Model>(1);
  141. std::vector<real_t> lengths(2,1);
  142. const EGADS::Context* context = &emodel->context();
  143. pbody = std::make_shared<EGADS::Cube>(context,lengths);
  144. emodel->add_body(pbody);
  145. emodel->build();
  146. pmodel = emodel;
  147. }
  148. avro_assert( pbody != nullptr );
  149. pmodel->add_body(pbody);
  150. return pmodel;
  151. }
  152. std::shared_ptr<Mesh>
  153. get_mesh( const std::string& name , std::shared_ptr<TopologyBase>& ptopology , coord_t number ) {
  154. // get the file extension
  155. std::string ext = get_file_ext(name);
  156. // if there is a file extension, read the mesh
  157. if (ext == "mesh" || ext == "meshb") {
  158. std::shared_ptr<Mesh> pmesh = std::make_shared<meshb>(name);
  159. ptopology = pmesh->retrieve_ptr<Simplex>(0);
  160. printf("mesh has %lu topologies\n",pmesh->nb_topologies());
  161. if (pmesh->nb_topologies() > 1) {
  162. // if there is more than one topology in the meshb file, add them as children to the first one
  163. for (index_t k=1;k<pmesh->nb_topologies();k++)
  164. static_cast<Topology<Simplex>*>(ptopology.get())->add_child( pmesh->retrieve_ptr<Simplex>(k) );
  165. }
  166. return pmesh;
  167. }
  168. if (ext == "avro" || ext == "json") {
  169. std::ifstream file(name);
  170. nlohmann::json jm;
  171. file >> jm;
  172. coord_t dim = jm["dim"];
  173. number = jm["number"];
  174. std::shared_ptr<Mesh> pmesh = std::make_shared<Mesh>(number,dim);
  175. index_t nb_ghost = 1;
  176. try {
  177. nb_ghost = jm["nb_ghost"];
  178. }
  179. catch (...) {
  180. printf("[warning] could not read number of ghost points, setting to 1\n");
  181. }
  182. std::vector<real_t> vertices = jm["vertices"];
  183. index_t nb_vertices = vertices.size() / dim;
  184. for (index_t k = 0; k < nb_vertices; k++) {
  185. pmesh->points().create( vertices.data() + k*dim );
  186. }
  187. if (jm["type"] == "simplex") {
  188. ptopology = std::make_shared<Topology<Simplex>>(pmesh->points(),number);
  189. std::vector<index_t> simplices = jm["elements"];
  190. index_t nb_simplices = simplices.size()/(number+1);
  191. printf("nb_simplices = %lu\n",nb_simplices);
  192. printf("nb_vertices = %lu\n",pmesh->points().nb());
  193. for (index_t k = 0; k < nb_simplices; k++) {
  194. bool ghost = false;
  195. std::vector<index_t> simplex( simplices.data() + k*(number+1) , simplices.data() + (k+1)*(number+1) );
  196. for (index_t j = 0; j < simplex.size(); j++)
  197. if (simplex[j] < nb_ghost) ghost = true;
  198. if (ghost) continue;
  199. ptopology->add( simplex.data(),simplex.size());
  200. }
  201. }
  202. else {
  203. std::string s = jm["type"];
  204. printf("unsupported element type %s\n",s.c_str());
  205. avro_implement;
  206. }
  207. pmesh->add(ptopology);
  208. return pmesh;
  209. }
  210. if (ext.empty()) {
  211. // check if this is a memory address
  212. if (name.substr(0,2) == "0x") {
  213. unsigned long address = std::stoul(name,0,16);
  214. Mesh* mesh0 = (Mesh*) address;
  215. std::vector<const TopologyBase*> topologies;
  216. mesh0->retrieve(topologies);
  217. avro_assert( topologies.size() > 0 );
  218. index_t maxnumber = 0;
  219. const TopologyBase* topology = nullptr;
  220. for (index_t k = 0; k < topologies.size(); k++) {
  221. //printf("topology(%lu) number = %u with %lu elements\n",k,topologies[k]->number(),topologies[k]->nb());
  222. if (topologies[k]->number()<=maxnumber) continue;
  223. maxnumber = topologies[k]->number();
  224. topology = topologies[k];
  225. }
  226. printf("determined mesh number = %lu, using topology with %lu elements\n",maxnumber,topology->nb());
  227. std::shared_ptr<Mesh> pmesh = std::make_shared<Mesh>(maxnumber,mesh0->points().dim());
  228. mesh0->points().copy( pmesh->points() );
  229. printf("topology has %lu fields to copy\n",topology->fields().nb());
  230. printf("adding mesh with %lu points\n",pmesh->points().nb());
  231. ptopology = nullptr;
  232. for (index_t k = 0;k < mesh0->nb_topologies(); k++) {
  233. if (mesh0->topology_ptr(k).get() == topology) {
  234. ptopology = mesh0->topology_ptr(k);
  235. break;
  236. }
  237. }
  238. avro_assert( ptopology!=nullptr );
  239. printf("topology type = %s\n",ptopology->type_name().c_str());
  240. pmesh->add( ptopology );
  241. return pmesh;
  242. }
  243. }
  244. // if no file extension, it must be a mesh in the library
  245. std::vector<std::string> s = split(name,"-");
  246. if (s[0] == "CKF" or s[0] == "CKF-simplex") {
  247. // count how many hyphens there are to read the dimensions
  248. index_t offset = 1;
  249. if (s[1] == "simplex") offset = 2;
  250. number = s.size() - offset;
  251. std::vector<real_t> lens(number,1.0);
  252. std::vector<index_t> dims(number,0);
  253. for (coord_t i=0;i<number;i++)
  254. dims[i] = unstringify<index_t>(s[i+offset]);
  255. std::shared_ptr<Mesh> pmesh = std::make_shared<Mesh>(number,number);
  256. std::shared_ptr<Topology<Simplex>> ptopology_ckf = std::make_shared<CKF_Triangulation>(dims);
  257. ptopology_ckf->orient(); // make positive volumes
  258. ptopology_ckf->points().copy( pmesh->points() );
  259. ptopology = ptopology_ckf;
  260. pmesh->add(ptopology_ckf);
  261. return pmesh;
  262. }
  263. if (s[0] == "CKF-cube") {
  264. avro_implement;
  265. }
  266. printf("cannot find mesh %s\n",name.c_str());
  267. avro_assert_not_reached;
  268. return nullptr;
  269. }
  270. } // programs
  271. } // avro