Lemma is an Electromagnetics API
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

hantenna_mex.cpp 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. /* MyMEXFunction
  2. * Adds second input to each
  3. * element of first input
  4. * a = MyMEXFunction(a,b);
  5. */
  6. #include "mex.hpp"
  7. #include "mexAdapter.hpp"
  8. #include "MatlabDataArray.hpp"
  9. #include "LemmaCore"
  10. #include "FDEM1D"
  11. #include "timer.h"
  12. #include <Eigen/Core>
  13. #if defined(__clang__)
  14. /* Clang/LLVM. ---------------------------------------------- */
  15. const char* compiler = "clang";
  16. const char* ver = __VERSION__;
  17. #elif defined(__ICC) || defined(__INTEL_COMPILER)
  18. /* Intel ICC/ICPC. ------------------------------------------ */
  19. const char* compiler = "icpc";
  20. const char* ver = __VERSION__;
  21. #elif defined(__GNUC__) || defined(__GNUG__)
  22. /* GNU GCC/G++. --------------------------------------------- */
  23. const char* compiler = "gcc (GCC) ";// __VERSION__;
  24. const char* ver = __VERSION__;
  25. #elif defined(_MSC_VER)
  26. /* Microsoft Visual Studio. --------------------------------- */
  27. const char* compiler = "msvc ";
  28. const int ver = _MSC_FULL_VER;
  29. #elif defined(__PGI)
  30. /* Portland Group PGCC/PGCPP. ------------------------------- */
  31. const char* compiler = "pgc";
  32. #endif
  33. using namespace Lemma;
  34. using namespace matlab::data;
  35. using matlab::mex::ArgumentList;
  36. std::vector<Real> readinpfile(const std::string& fname);
  37. std::vector<std::string> readinpfile2(const std::string& fname);
  38. class MexFunction : public matlab::mex::Function {
  39. public:
  40. void operator()(ArgumentList outputs, ArgumentList inputs) {
  41. const char *buildString = __DATE__ ", " __TIME__;
  42. std::cout
  43. << "===========================================================================\n"
  44. << "Lemma " << LEMMA_VERSION << "\n"
  45. << "[" << compiler << " " << ver << " " << buildString << "]\n"
  46. << "This program is part of Lemma, a geophysical modelling and inversion API. \n"
  47. << " This Source Code Form is subject to the terms of the Mozilla Public\n"
  48. << " License, v. 2.0. If a copy of the MPL was not distributed with this\n"
  49. << " file, You can obtain one at http://mozilla.org/MPL/2.0/. \n"
  50. << "Copyright (C) 2018 Lemma Software \n"
  51. << "More information may be found at: https://lemmasoftware.org\n"
  52. << " info@lemmasoftware.org\n"
  53. << "===========================================================================\n\n"
  54. << "Hantenna calculates the harmonic H field from polygonal wire loop sources\n";
  55. // TODO add this
  56. //checkArguments(outputs, inputs);
  57. // TODO, add this to check arguments and formalize
  58. if (inputs.size() < 4) {
  59. std::cout << "usage: hantenna(trans.inp cond.inp points.inp config.inp) \n";
  60. ArrayFactory ef;
  61. outputs[0] = ef.createCharArray("Insufficient inputs");
  62. return;
  63. //exit(EXIT_SUCCESS);
  64. }
  65. #ifdef LEMMAUSEOMP
  66. std::cout << "OpenMP is using " << omp_get_max_threads() << " threads" << std::endl;
  67. #endif
  68. /*
  69. std::vector<Real> Trans = readinpfile(std::string(inputs[1]));
  70. std::vector<Real> CondMod = readinpfile(std::string(inputs[2]));
  71. std::vector<Real> Points = readinpfile(std::string(inputs[3]));
  72. std::vector<std::string> config = readinpfile2(std::string(inputs[4]));
  73. */
  74. // Let's fix this inputs thing
  75. matlab::data::CharArray charVector2 = inputs[0];
  76. std::string TransFile = charVector2.toAscii();
  77. std::vector<Real> Trans = readinpfile( "trans.inp" );
  78. std::vector<std::string> config = readinpfile2("config.inp");
  79. std::vector<Real> CondMod = readinpfile("cond.inp");
  80. std::vector<Real> Points = readinpfile("points.inp");
  81. //////////////////////////////////////
  82. // Define transmitter
  83. auto trans = PolygonalWireAntenna::NewSP();
  84. trans->SetNumberOfPoints((int)(Trans[0]));
  85. int ip=1;
  86. for ( ; ip<=(int)(Trans[0])*2; ip+=2) {
  87. trans->SetPoint(ip/2, Vector3r (Trans[ip], Trans[ip+1], -1e-3));
  88. //trans->SetPoint(ip/2, Vector3r (Trans[ip], Trans[ip+1], 50.));
  89. }
  90. trans->SetNumberOfFrequencies(1);
  91. trans->SetFrequency(0, Trans[ip]);
  92. trans->SetCurrent(Trans[ip+1]);
  93. trans->SetMinDipoleRatio(atof(config[1].c_str()));
  94. trans->SetMinDipoleMoment(atof(config[2].c_str()));
  95. trans->SetMaxDipoleMoment(atof(config[3].c_str()));
  96. /////////////////////////////////////
  97. // Field calculations
  98. auto receivers = FieldPoints::NewSP();
  99. int nx = (int)Points[0];
  100. int ny = (int)Points[1];
  101. int nz = (int)Points[2];
  102. Real ox = Points[3];
  103. Real oy = Points[4];
  104. Real oz = Points[5];
  105. Vector3r loc;
  106. VectorXr dx(nx-1);
  107. VectorXr dy(ny-1);
  108. VectorXr dz(nz-1);
  109. ip = 6;
  110. int ir = 0;
  111. for ( ; ip <6+nx-1; ++ip) {
  112. dx[ir] = Points[ip];
  113. ++ir;
  114. }
  115. ir = 0;
  116. for ( ; ip <6+ny-1+nx-1; ++ip) {
  117. dy[ir] = Points[ip];
  118. ++ir;
  119. }
  120. ir = 0;
  121. for ( ; ip <6+nz-1+ny-1+nx-1; ++ip) {
  122. dz[ir] = Points[ip];
  123. ++ir;
  124. }
  125. receivers->SetNumberOfPoints(nx*ny*nz);
  126. ir = 0;
  127. Real pz = oz;
  128. for (int iz=0; iz<nz; ++iz) {
  129. Real py = oy;
  130. for (int iy=0; iy<ny; ++iy) {
  131. Real px = ox;
  132. for (int ix=0; ix<nx; ++ix) {
  133. loc << px, py, pz;
  134. receivers->SetLocation(ir, loc);
  135. if (ix < nx-1) px += dx[ix];
  136. ++ ir;
  137. }
  138. if (iy<ny-1) py += dy[iy];
  139. }
  140. if (iz<nz-1) pz += dz[iz];
  141. }
  142. ////////////////////////////////////
  143. // Define model
  144. auto earth = LayeredEarthEM::NewSP();
  145. VectorXcr sigma;
  146. VectorXr thick;
  147. earth->SetNumberOfLayers(static_cast<int>(CondMod[0])+1);
  148. sigma.resize(static_cast<int>(CondMod[0])+1); sigma(0) = 0; // airlayer
  149. thick.resize(static_cast<int>(CondMod[0])-1);
  150. int ilay=1;
  151. for ( ; ilay/2<CondMod[0]-1; ilay+=2) {
  152. sigma(ilay/2+1) = 1./CondMod[ilay];
  153. thick(ilay/2) = CondMod[ilay+1];
  154. }
  155. sigma(ilay/2+1) = 1./ CondMod[ilay];
  156. earth->SetLayerConductivity(sigma);
  157. if (thick.size() > 0) earth->SetLayerThickness(thick);
  158. auto EmEarth = EMEarth1D::NewSP();
  159. EmEarth->AttachWireAntenna(trans);
  160. EmEarth->AttachLayeredEarthEM(earth);
  161. EmEarth->AttachFieldPoints(receivers);
  162. EmEarth->SetFieldsToCalculate(H);
  163. EmEarth->SetHankelTransformMethod(string2Enum<HANKELTRANSFORMTYPE>(config[0]));
  164. ///////////////////////////////////////////////
  165. // Keep track of time
  166. jsw_timer timer;
  167. timer.begin();
  168. clock_t launch = clock();
  169. EmEarth->CalculateWireAntennaFields(false); // false=status bar, doesn't work in Matlab well
  170. Real paTime = timer.end();
  171. std::cout << "\n\n===========================================\ncalc. real time: " << paTime/60. << "\t[m]\n";
  172. std::cout << "calc. user time: " << (clock()-launch)/CLOCKS_PER_SEC/60. << "\t[CPU m]"
  173. << std::endl;
  174. ////////////////////////////////////////////////////////////////////
  175. // This is kind of ugly, but the Matlab conversion is really picky
  176. // Convert C++ arrays to Matlab
  177. ArrayFactory f;
  178. StructArray S = f.createStructArray({ 3,1 }, { "Component", "Data", "Units" });
  179. S[0]["Component"] = f.createCharArray("H_x");
  180. S[0]["Units"] = f.createCharArray("A/m");
  181. Eigen::Array<Complex, Eigen::Dynamic, 1> Hx = receivers->GetHfield(0).row(0).array();
  182. std::vector<Complex> Hxv = std::vector<Complex>(Hx.begin(), Hx.end());
  183. matlab::data::TypedArray<Complex> Hxm = f.createArray<Complex>({1, Hxv.size()}, Hxv.data(), Hxv.data()+Hxv.size());
  184. S[0]["Data"] = std::move(Hxm);
  185. S[1]["Component"] = f.createCharArray("H_y");
  186. S[1]["Units"] = f.createCharArray("A/m");
  187. Eigen::Array<Complex, Eigen::Dynamic, 1> Hy = receivers->GetHfield(0).row(1).array();
  188. std::vector<Complex> Hyv = std::vector<Complex>(Hy.begin(), Hy.end());
  189. matlab::data::TypedArray<Complex> Hym = f.createArray<Complex>({1, Hyv.size()}, Hyv.data(), Hyv.data()+Hyv.size());
  190. S[1]["Data"] = std::move(Hym);
  191. S[2]["Component"] = f.createCharArray("H_z");
  192. S[2]["Units"] = f.createCharArray("A/m");
  193. Eigen::Array<Complex, Eigen::Dynamic, 1> Hz = receivers->GetHfield(0).row(2).array();
  194. std::vector<Complex> Hzv = std::vector<Complex>(Hz.begin(), Hz.end());
  195. matlab::data::TypedArray<Complex> Hzm = f.createArray<Complex>({1, Hzv.size()}, Hzv.data(), Hzv.data()+Hzv.size());
  196. S[2]["Data"] = std::move(Hzm);
  197. outputs[0] = std::move(S);
  198. ////////////////////////////////////
  199. // Report, file write is s l o w
  200. /*
  201. std::fstream hrep("hfield.yaml", std::ios::out);
  202. std::fstream hreal("hfield.dat", std::ios::out);
  203. hrep << *EmEarth << std::endl;
  204. hrep.close();
  205. hreal << "// Right hand coordinate system, z is positive down\n";
  206. hreal << "// x[m]\ty[m]\tz[m]\tRe(Hx[A/m])\tRe(Hy[A/m])\tRe(Hz[A/m])\tIm(Hx)\tIm(Hy)\tIm(Hz)\n";
  207. hreal.precision(8);
  208. int i=0;
  209. for (int iz=0; iz<nz; ++iz) {
  210. for (int iy=0; iy<ny; ++iy) {
  211. for (int ix=0; ix<nx; ++ix) {
  212. hreal << receivers->GetLocation(i).transpose() << "\t";
  213. hreal << receivers->GetHfield(0, i).transpose() << "\n"; // ( complex, notation )
  214. //hreal << receivers->GetHfield(0, i).transpose().real() << "\t";
  215. //hreal << receivers->GetHfield(0, i).transpose().imag() << "\n";
  216. ++i;
  217. }
  218. }
  219. }
  220. hreal.close();
  221. */
  222. // Demo stuff
  223. /*
  224. const double offSet = inputs[0][0];
  225. TypedArray<double> doubleArray = std::move(inputs[1]);
  226. for (auto& elem : doubleArray) {
  227. elem += offSet;
  228. }
  229. outputs[0] = doubleArray;
  230. */
  231. }
  232. void checkArguments(ArgumentList outputs, ArgumentList inputs) {
  233. // Get pointer to engine
  234. std::shared_ptr<matlab::engine::MATLABEngine> matlabPtr = getEngine();
  235. // Get array factory
  236. ArrayFactory factory;
  237. // Check first input argument
  238. if (inputs[0].getType() != ArrayType::CHAR ||
  239. inputs[0].getNumberOfElements() != 1)
  240. {
  241. matlabPtr->feval(u"error",
  242. 0,
  243. std::vector<Array>({ factory.createScalar("First input must be the name of a trans.inp file") }));
  244. }
  245. // Check second input argument
  246. if (inputs[1].getType() != ArrayType::DOUBLE ||
  247. inputs[1].getType() == ArrayType::COMPLEX_DOUBLE)
  248. {
  249. matlabPtr->feval(u"error",
  250. 0,
  251. std::vector<Array>({ factory.createScalar("Input must be double array") }));
  252. }
  253. // Check number of outputs
  254. if (outputs.size() > 1) {
  255. matlabPtr->feval(u"error",
  256. 0,
  257. std::vector<Array>({ factory.createScalar("Only one output is returned") }));
  258. }
  259. }
  260. };
  261. std::vector<Real> readinpfile(const std::string& fname) {
  262. std::string buf;
  263. char dump[255];
  264. std::vector<Real> vals;
  265. std::fstream input(fname.c_str(), std::ios::in);
  266. if (input.fail()) {
  267. std::cerr << "Input file " << fname << " failed to open\n";
  268. exit(EXIT_FAILURE);
  269. }
  270. while (input >> buf) {
  271. if (buf.substr(0,2) == "//") {
  272. input.getline(dump, 255);
  273. } else {
  274. vals.push_back( atof(buf.c_str() ));
  275. }
  276. }
  277. return vals;
  278. }
  279. std::vector<std::string> readinpfile2(const std::string& fname) {
  280. std::string buf;
  281. char dump[255];
  282. std::vector<std::string> vals;
  283. std::fstream input(fname.c_str(), std::ios::in);
  284. if (input.fail()) {
  285. std::cerr << "Input file " << fname << " failed to open\n";
  286. exit(EXIT_FAILURE);
  287. }
  288. while (input >> buf) {
  289. if (buf.substr(0,2) == "//") {
  290. input.getline(dump, 255);
  291. } else {
  292. vals.push_back( std::string(buf.c_str() ));
  293. }
  294. }
  295. return vals;
  296. }