3D EM based on Schur decomposition
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

EMSchur3D.h 35KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824
  1. /* This file is part of Lemma, a geophysical modelling and inversion API.
  2. * More information is available at http://lemmasoftware.org
  3. */
  4. /* This Source Code Form is subject to the terms of the Mozilla Public
  5. * License, v. 2.0. If a copy of the MPL was not distributed with this
  6. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  7. */
  8. /**
  9. * @file
  10. * @date 02/19/2015 01:10:39 PM
  11. * @version $Id$
  12. * @author Trevor Irons (ti)
  13. * @email Trevor.Irons@Lemmasoftware.org
  14. * @copyright Copyright (c) 2015, XRI Geophysics, LLC
  15. * @copyright Copyright (c) 2011, 2015, 2017, 2018 Trevor Irons
  16. * @copyright Copyright (c) 2011, Colorado School of Mines
  17. */
  18. #ifndef EMSCHUR3D_INC
  19. #define EMSCHUR3D_INC
  20. #include "EMSchur3DBase.h"
  21. #include "bicgstab.h"
  22. #ifdef HAVE_SUPERLU
  23. #include "Eigen/SuperLUSupport"
  24. #endif
  25. #ifdef HAVE_UMFPACK
  26. #include <Eigen/UmfPackSupport>
  27. #endif
  28. #ifdef HAVE_PASTIX
  29. #include <Eigen/PaStiXSupport>
  30. #endif
  31. #ifdef HAVE_PARDISO
  32. #include <Eigen/PardisoSupport>
  33. #endif
  34. //#include "CSymSimplicialCholesky.h"
  35. namespace Lemma {
  36. /**
  37. \brief Templated concrete classes of EMSChur3DBase.
  38. \details
  39. */
  40. template < class Solver >
  41. class EMSchur3D : public EMSchur3DBase {
  42. friend std::ostream &operator << (std::ostream &stream, const EMSchur3D &ob) {
  43. stream << ob.Serialize() << "\n"; // End of doc
  44. return stream;
  45. }
  46. //friend std::ostream &operator<<(std::ostream &stream,
  47. // const EMSchur3D &ob);
  48. public:
  49. // ==================== LIFECYCLE =======================
  50. /**
  51. * @copybrief LemmaObject::New()
  52. * @copydetails LemmaObject::New()
  53. */
  54. static std::shared_ptr< EMSchur3D > NewSP() {
  55. return std::make_shared< EMSchur3D<Solver> >( ctor_key() );
  56. }
  57. /** Default protected constructor, use New */
  58. explicit EMSchur3D ( const ctor_key& key ) : EMSchur3DBase( key ), CSolver( nullptr ) {
  59. }
  60. /** Locked DeDerializing constructor, use factory DeSerialize method*/
  61. EMSchur3D (const YAML::Node& node, const ctor_key& key): EMSchur3DBase(node, key), CSolver( nullptr ) {
  62. }
  63. /** Default protected destructor, use Delete */
  64. virtual ~EMSchur3D () {
  65. // TODO delete arrays
  66. }
  67. /**
  68. * Uses YAML to serialize this object.
  69. * @return a YAML::Node
  70. */
  71. YAML::Node Serialize() const {
  72. YAML::Node node = EMSchur3DBase::Serialize();
  73. //node["NumberOfLayers"] = NumberOfLayers;
  74. node.SetTag( this->GetName() );
  75. return node;
  76. }
  77. /**
  78. * Constructs an object from a YAML::Node.
  79. */
  80. static EMSchur3D* DeSerialize(const YAML::Node& node);
  81. // ==================== OPERATORS =======================
  82. // ==================== OPERATIONS =======================
  83. /** Solves a single source problem. This method is thread safe.
  84. * @param[in] Source is the source term for generating primary fields
  85. * @param[in] isource is the source index
  86. */
  87. void SolveSource( std::shared_ptr<DipoleSource> Source , const int& isource);
  88. /** Builds the solver for the C matrix */
  89. void BuildCDirectSolver( );
  90. // ==================== ACCESS =======================
  91. virtual std::string GetName() const {
  92. return this->CName;
  93. }
  94. // ==================== INQUIRY =======================
  95. protected:
  96. // ==================== LIFECYCLE =======================
  97. private:
  98. /** Copy constructor */
  99. EMSchur3D( const EMSchur3D& ) = delete;
  100. // ==================== DATA MEMBERS =========================
  101. /** The templated solver for C */
  102. Solver* CSolver;
  103. Eigen::SparseMatrix<Complex> Csym;
  104. static constexpr auto CName = "EMSchur3D";
  105. }; // ----- end of class EMSchur3D -----
  106. ////////////////////////////////////////////////////////////////////////////////////////
  107. // Implimentation and Specialisations //
  108. ////////////////////////////////////////////////////////////////////////////////////////
  109. //--------------------------------------------------------------------------------------
  110. // Class: EMSchur3D
  111. // Method: SolveSource
  112. //--------------------------------------------------------------------------------------
  113. template < class Solver >
  114. void EMSchur3D<Solver>::SolveSource ( std::shared_ptr<DipoleSource> Source, const int& isource ) {
  115. std::cout << "In vanilla SolveSource" << std::endl;
  116. // figure out which omega we are working with
  117. int iw = -1;
  118. for (int iiw=0; iiw<Omegas.size(); ++iiw) {
  119. if (Omegas[iiw] - Source->GetAngularFrequency(0) < 1e-3 ) {
  120. iw = iiw;
  121. }
  122. }
  123. if (iw == -1) {
  124. std::cerr << "FREQUENCY DOOM IN EMSchur3D::SolveSource \n";
  125. exit(EXIT_FAILURE);
  126. }
  127. ///////////////////////////////////
  128. // Set up primary fields
  129. // TODO, this is a little stupid as they all share the same points. We need to extend
  130. // EmEARTH to be able to input a grid so that points are not explicitly needed like
  131. // this. This requires some care as calcs are made on faces.
  132. // Alternatively, the bins function of ReceiverPoints could be extended quite easily.
  133. // This may be the way to do this.
  134. //Lemma::ReceiverPoints* dpoint = Lemma::ReceiverPoints::New();
  135. std::shared_ptr< FieldPoints > dpoint = FieldPoints::NewSP();
  136. FillPoints(dpoint);
  137. PrimaryField(Source, dpoint);
  138. std::cout << "Done with primary field" << std::endl;
  139. // Allocate a ton of memory
  140. VectorXcr Phi = VectorXcr::Zero(uns);
  141. VectorXcr ms(unx+uny+unz); // mu sigma
  142. // Vector potential (A) Vector and phi
  143. VectorXcr Se = VectorXcr::Zero(unx+uny+unz);
  144. //VectorXcr A = VectorXcr::Zero(unx+uny+unz);
  145. VectorXcr E = VectorXcr::Zero(unx+uny+unz);
  146. VectorXcr E0 = VectorXcr::Zero(unx+uny+unz);
  147. // Lets get cracking
  148. std::cout << "Filling source terms" << std::endl;
  149. FillSourceTerms(ms, Se, E0, dpoint, Omegas[iw]);
  150. std::cout << "Done source terms" << std::endl;
  151. /////////////////////////////////////////////////
  152. // LOG File
  153. std::string logfile (ResFile);
  154. logfile += to_string(isource) + std::string(".log");
  155. ofstream logio(logfile.c_str());
  156. std::cout << "just logging, TODO fix source" << std::endl;
  157. // logio << *Source << std::endl;
  158. logio << *Grid << std::endl;
  159. logio << *LayModel << std::endl;
  160. std::cout << "dun logging" << std::endl;
  161. // solve for RHS
  162. int max_it(nx*ny*nz), iter_done(0);
  163. Real tol(3e-16), errorn(0);
  164. logio << "solving RHS for source " << isource << std::endl;
  165. // TODO, this is stupid, try and get rid of this copy!
  166. //Eigen::SparseMatrix<Complex> Cc = Cvec[iw];
  167. jsw_timer timer;
  168. jsw_timer timer2;
  169. timer.begin();
  170. timer2.begin();
  171. /////////////////////////////////////////
  172. // Solve for RHS
  173. //CSolver[iw].setMaxIterations(750);
  174. Eigen::initParallel();
  175. std::cout << "Eigen using " << Eigen::nbThreads( ) << " threads" << std::endl;
  176. VectorXcr A = CSolver[iw].solve(Se);
  177. // // Solve Real system instead
  178. // The Real system is quasi-definite, though an LDLT decomposition exists, CHOLMOD doesn't find it.
  179. // An LU can be done on this, but compute performance is very similiar to the complex system, and diagonal pivoting
  180. // cannot be assumed to be best, hurting solve time.
  181. // /* EXPERIMENTAL */
  182. // VectorXr b2 = VectorXr::Zero(2*(unx+uny+unz));
  183. // b2.head(unx+uny+unz) = Se.real();
  184. // b2.tail(unx+uny+unz) = Se.imag();
  185. // VectorXr A2 = CReSolver[iw].solve(b2);
  186. // A.real() = A2.head( unx+uny+unz );
  187. // A.imag() = -A2.tail( unx+uny+unz ); // Due to decomp. negative!
  188. // /* END EXPERIMENTAL */
  189. VectorXcr ADiv = D*A; // ADiv == RHS == D C^I Se
  190. //VectorXcr Error = ((Cc.selfadjointView<Eigen::Lower>()*A).array() - Se.array());
  191. VectorXcr Error = ((Cvec[iw]*A).array() - Se.array());
  192. /*
  193. #if LOWER==1
  194. std::cout << "Using Eigen::Lower to calculate Error" << std::endl;
  195. VectorXcr Error = ((Cvec[iw].selfadjointView<Eigen::Lower>()*A).array() - Se.array());
  196. #elif UPPER==1
  197. std::cout << "Using Eigen::Upper to calculate Error" << std::endl;
  198. VectorXcr Error = ((Cvec[iw].selfadjointView<Eigen::Upper>()*A).array() - Se.array());
  199. #endif
  200. */
  201. logio << "|| Div(A) || = " << ADiv.norm()
  202. << "\tInital solution error="<< Error.norm() // Iteritive info
  203. // << "\tSolver reported error="<< CSolver[iw].error() // Iteritive info
  204. << "\ttime " << timer.end() / 60. << " [m] "
  205. // << CSolver[iw].iterations() << " iterations"
  206. << std::endl;
  207. //VectorXcr ADivMAC = ADiv.array() * MAC.array().cast<Complex>();
  208. //logio << "|| Div(A) || on MAC grid " << ADivMAC.norm() << std::endl;
  209. /////////////////////
  210. // Solve for Phi
  211. logio << "Solving for Phi " << std::flush;
  212. timer.begin();
  213. tol = 1e-30;
  214. int success(2);
  215. success = implicitbicgstab(D, idx, ms, ADiv, Phi, CSolver[iw], max_it, tol, errorn, iter_done, logio);
  216. //Phi.array() *= MAC.array().cast<Complex>(); // remove phi from air regions
  217. /* Restart if necessary */
  218. /*
  219. int nrestart(1);
  220. // TODO send MAC to implicitbicgstab?
  221. while (success == 2 && nrestart < 18 && iter_done > 1) {
  222. success = implicitbicgstab(D, idx, ms, ADiv, Phi, CSolver[iw], max_it, tol, errorn, iter_done, logio);
  223. //Phi.array() *= MAC.array().cast<Complex>(); // remove phi from air regions
  224. nrestart += 1;
  225. }
  226. */
  227. logio << "Implicit BiCGStab solution in " << iter_done << " iterations."
  228. << " with error " << std::setprecision(8) << std::scientific << errorn << std::endl;
  229. logio << "time "<< timer.end()/60. << " [m]" << std::endl;
  230. E = ms.array()*(D.transpose()*Phi).array(); // Temp, field due to charge
  231. /////////////////////////////////////
  232. // Compute A
  233. /////////////////////////////////////
  234. logio << "Solving for A using phi" << std::endl;
  235. std::cout << "Solving for A" << std::endl;
  236. max_it = nx*ny*nz;
  237. tol = 5e-16;
  238. errorn = 0;
  239. iter_done = 0;
  240. timer.begin();
  241. A = CSolver[iw].solve( (Se-E).eval() ); // UmfPack requires eval?
  242. VectorXcr ADiv2 = D*A;
  243. //logio << "|| Div(A) || = " << ADiv2.norm() ;
  244. //" in " << iter_done << " iterations"
  245. //<< " with error " << errorn << "\t";
  246. // Report error of solutions
  247. //Error = ((Cc.selfadjointView<Eigen::Lower>()*A).array() + E.array() - Se.array());
  248. /*
  249. #if LOWER==1
  250. std::cout << "Using Eigen::Lower to calculate Error" << std::endl;
  251. Error = ((Cvec[iw].selfadjointView<Eigen::Lower>()*A).array() + E.array() - Se.array());
  252. #elif UPPER==1
  253. std::cout << "Using Eigen::Upper to calculate Error" << std::endl;
  254. Error = ((Cvec[iw].selfadjointView<Eigen::Upper>()*A).array() + E.array() - Se.array());
  255. #endif
  256. */
  257. Error = ((Cvec[iw]*A).array() + E.array() - Se.array());
  258. // << "\tSolver reported error="<< CSolver[iw].error() // Iteritive info
  259. // << "\ttime " << timer.end() / 60. << " [m] "
  260. // << CSolver[iw].iterations() << " iterations"
  261. logio << "|| Div(A) || = " << ADiv2.norm()
  262. << "\tSolution error="<< Error.norm() // Iteritive info
  263. // << "\tSolver reported error="<< CSolver[iw].error() // Iteritive info
  264. << "\ttime " << timer.end() / 60. << " [m] "
  265. // << CSolver[iw].iterations() << " iterations"
  266. << std::endl << std::endl;
  267. logio << std::fixed << std::setprecision(2) << "\ttime " << timer.end()/60. << "\ttotal time " << timer2.end()/60. << std::endl;
  268. logio.close();
  269. //////////////////////////////////////
  270. // Update Fields and report
  271. E.array() = Complex(0,-Omegas[iw])*A.array() - (D.transpose()*Phi).array(); // Secondary Field Only
  272. VectorXcr B = StaggeredGridCurl(A);
  273. WriteVTKResults( ResFile+ to_string(isource), A, Se, E0, E , Phi, ADiv, ADiv2, B);
  274. //dpoint->Delete();
  275. return ;
  276. } // ----- end of method EMSchur3D::SolveSource -----
  277. //--------------------------------------------------------------------------------------
  278. // Class: EMSchur3DBase
  279. // Method: BuildCDirectSolver
  280. //--------------------------------------------------------------------------------------
  281. template < class Solver >
  282. void EMSchur3D<Solver>::BuildCDirectSolver ( ) {
  283. CSolver = new Solver[Omegas.size()];
  284. for (int iw=0; iw<Omegas.size(); ++iw) {
  285. jsw_timer timer;
  286. timer.begin();
  287. /* Complex system */
  288. /*
  289. std::cout << "Generic solver pattern analyzing C_" << iw << ",";
  290. std::cout.flush();
  291. CSolver[iw].analyzePattern( Cvec[iw].selfadjointView< Eigen::Lower>() );
  292. std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  293. // factorize
  294. timer.begin();
  295. std::cout << "Generic solver factorising C_" << iw << ", ";
  296. std::cout.flush();
  297. CSolver[iw].factorize( Cvec[iw].selfadjointView< Eigen::Lower>() );
  298. */
  299. std::cerr << "No solver Specified!" << iw << ",";
  300. exit(EXIT_FAILURE);
  301. //CSolver[iw].compute( Cvec[iw].selfadjointView< Eigen::Lower>() );
  302. std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  303. }
  304. }
  305. #ifdef HAVE_SUPERLU
  306. template<>
  307. void EMSchur3D< Eigen::SuperLU<Eigen::SparseMatrix<Complex, SPARSEMAJOR> > >::BuildCDirectSolver() {
  308. CSolver = new Eigen::SuperLU<Eigen::SparseMatrix<Complex, SPARSEMAJOR> > [Omegas.size()];
  309. for (int iw=0; iw<Omegas.size(); ++iw) {
  310. jsw_timer timer;
  311. timer.begin();
  312. /* SuperLU */
  313. // Recommended values for symmetric mode
  314. CSolver[iw].options().DiagPivotThresh = 0.01;
  315. CSolver[iw].options().SymmetricMode = YES;
  316. CSolver[iw].options().ColPerm = MMD_AT_PLUS_A;
  317. //CSolver[iw].options().Trans = NOTRANS;
  318. //CSolver[iw].options().ConditionNumber = NO;
  319. //std::cout << "SuperLU options:\n";
  320. //std::cout << "\tPivot Threshold: " << CSolver[iw].options().DiagPivotThresh << std::endl;
  321. //std::cout << "\tSymmetric mode: " << CSolver[iw].options().SymmetricMode << std::endl;
  322. //std::cout << "\tEquilibrate: " << CSolver[iw].options().Equil << std::endl;
  323. //std::cout << "\tCol Permutation: " << CSolver[iw].options().ColPerm << std::endl;
  324. //std::cout << "\tTrans: " << CSolver[iw].options().Trans << std::endl;
  325. //std::cout << "\tCondition Number: " << CSolver[iw].options().ConditionNumber << std::endl;
  326. /* Complex system */
  327. std::cout << "SuperLU pattern analyzing C_" << iw << ",";
  328. std::cout.flush();
  329. CSolver[iw].analyzePattern( Cvec[iw].selfadjointView< Eigen::Lower>() );
  330. std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  331. // factorize
  332. timer.begin();
  333. std::cout << "SuperLU factorising C_" << iw << ", ";
  334. std::cout.flush();
  335. CSolver[iw].factorize( Cvec[iw].selfadjointView< Eigen::Lower>() );
  336. std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  337. }
  338. }
  339. #endif
  340. template<>
  341. void EMSchur3D< Eigen::SparseLU<Eigen::SparseMatrix<Complex, SPARSEMAJOR>, Eigen::COLAMDOrdering<int> > >::BuildCDirectSolver() {
  342. CSolver = new Eigen::SparseLU<Eigen::SparseMatrix<Complex, SPARSEMAJOR>, Eigen::COLAMDOrdering<int> > [Omegas.size()];
  343. for (int iw=0; iw<Omegas.size(); ++iw) {
  344. jsw_timer timer;
  345. timer.begin();
  346. //CSolver[iw].isSymmetric(true);
  347. //CSolver[iw].setPivotThreshold(0.0); // OK for symmetric complex systems with real and imaginary positive definite parts.
  348. // // but our imaginary part is negative definite
  349. //http://www.ams.org/journals/mcom/1998-67-224/S0025-5718-98-00978-8/S0025-5718-98-00978-8.pdf
  350. /* Complex system */
  351. std::cout << "SparseLU pattern analyzing C_" << iw << ",";
  352. std::cout.flush();
  353. //CSolver[iw].analyzePattern( Cvec[iw].selfadjointView< Eigen::Lower>() );
  354. CSolver[iw].analyzePattern( Cvec[iw] );
  355. std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  356. // factorize
  357. timer.begin();
  358. std::cout << "SparseLU factorising C_" << iw << ", ";
  359. std::cout.flush();
  360. //CSolver[iw].factorize( Cvec[iw].selfadjointView< Eigen::Lower>() );
  361. CSolver[iw].factorize( Cvec[iw] ); //.selfadjointView< Eigen::Lower>() );
  362. std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  363. }
  364. }
  365. #ifdef HAVE_PARDISO
  366. template<>
  367. void EMSchur3D< Eigen::PardisoLU<Eigen::SparseMatrix<Complex, SPARSEMAJOR> > >::BuildCDirectSolver() {
  368. CSolver = new Eigen::PardisoLU<Eigen::SparseMatrix<Complex, SPARSEMAJOR> > [Omegas.size()];
  369. for (int iw=0; iw<Omegas.size(); ++iw) {
  370. jsw_timer timer;
  371. timer.begin();
  372. //CSolver[iw].pardisoParameterArray()[2] = 28; // OMP_NUM_THREADS?
  373. /* Complex system */
  374. std::cout << "PardisoLU pattern analyzing C_" << iw << ",";
  375. std::cout.flush();
  376. CSolver[iw].analyzePattern( Cvec[iw].selfadjointView< Eigen::Lower>() );
  377. std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  378. // factorize
  379. timer.begin();
  380. std::cout << "PardisoLU factorising C_" << iw << ", ";
  381. std::cout.flush();
  382. CSolver[iw].factorize( Cvec[iw].selfadjointView< Eigen::Lower>() );
  383. std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  384. }
  385. }
  386. template<>
  387. void EMSchur3D< Eigen::PardisoLDLT<Eigen::SparseMatrix<Complex, SPARSEMAJOR>, Eigen::Symmetric > >::BuildCDirectSolver() {
  388. CSolver = new Eigen::PardisoLDLT<Eigen::SparseMatrix<Complex, SPARSEMAJOR>, Eigen::Symmetric > [Omegas.size()];
  389. for (int iw=0; iw<Omegas.size(); ++iw) {
  390. jsw_timer timer;
  391. timer.begin();
  392. //CSolver[iw].pardisoParameterArray()[2] = 28; // OMP_NUM_THREADS?
  393. //Eigen::SparseMatrix<Complex> Csym = Cvec[iw].selfadjointView< Eigen::Lower >();
  394. /* Complex system */
  395. std::cout << "PardisoLDLT pattern analyzing C_" << iw << ",";
  396. std::cout.flush();
  397. //CSolver[iw].analyzePattern( Cvec[iw].selfadjointView< Eigen::Lower>() );
  398. CSolver[iw].analyzePattern( Cvec[iw] );
  399. std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  400. // factorize
  401. timer.begin();
  402. std::cout << "PardisoLDLT factorising C_" << iw << ", ";
  403. std::cout.flush();
  404. //CSolver[iw].factorize( Cvec[iw].selfadjointView< Eigen::Lower>() );
  405. CSolver[iw].factorize( Cvec[iw] );
  406. std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  407. }
  408. }
  409. #endif
  410. #ifdef HAVE_UMFPACK
  411. // Umfpack only seems to work when LOWER and UPPER are set to 1. Workarounds this have not been found.
  412. template<>
  413. void EMSchur3D< Eigen::UmfPackLU<Eigen::SparseMatrix<Complex, SPARSEMAJOR> > >::BuildCDirectSolver() {
  414. CSolver = new Eigen::UmfPackLU<Eigen::SparseMatrix<Complex, SPARSEMAJOR> > [Omegas.size()];
  415. for (int iw=0; iw<Omegas.size(); ++iw) {
  416. jsw_timer timer;
  417. timer.begin();
  418. /* Complex system */
  419. std::cout << "UmfPackLU pattern analyzing C_" << iw << ",";
  420. std::cout.flush();
  421. // Doesn't work, seg faults in solve
  422. //Eigen::SparseMatrix<Complex> Csym = Cvec[iw].selfadjointView< Eigen::Lower >();
  423. // Compiler errors get thrown with the view setting, good performance if LOWER and UPPER are set
  424. // CSolver[iw].analyzePattern( Cvec[iw].selfadjointView< Eigen::Lower>() ); // Compiler error
  425. CSolver[iw].analyzePattern( Cvec[iw] ); // requires LOWER=1 UPPER=1, double memory
  426. // CSolver[iw].analyzePattern( Csym ); // seg faults
  427. std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  428. // factorize
  429. timer.begin();
  430. std::cout << "UmfPackLU factorising C_" << iw << ", ";
  431. std::cout.flush();
  432. // CSolver[iw].factorize( Cvec[iw].selfadjointView< Eigen::Lower>() );
  433. CSolver[iw].factorize( Cvec[iw] );
  434. // CSolver[iw].factorize( Csym );
  435. std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  436. }
  437. }
  438. #endif
  439. // template<>
  440. // void EMSchur3D< Eigen::CholmodSupernodalLLT< Eigen::SparseMatrix<Complex, SPARSEMAJOR>, Eigen::Lower > > ::BuildCDirectSolver() {
  441. // CSolver = new Eigen::CholmodSupernodalLLT< Eigen::SparseMatrix<Complex, SPARSEMAJOR>, Eigen::Lower > [Omegas.size()];
  442. // for (int iw=0; iw<Omegas.size(); ++iw) {
  443. // Csym = Cvec[iw].selfadjointView<Eigen::Lower>();
  444. // jsw_timer timer;
  445. // timer.begin();
  446. // /* Complex system */
  447. // std::cout << "CholmodSupernodalLLT pattern analyzing C_" << iw << ",";
  448. // std::cout.flush();
  449. // CSolver[iw].analyzePattern( Csym );
  450. // std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  451. // /* factorize */
  452. // timer.begin();
  453. // std::cout << "CholmodSupernodalLLT factorising C_" << iw << ", ";
  454. // std::cout.flush();
  455. // CSolver[iw].factorize( Csym );
  456. // std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  457. // }
  458. // }
  459. // template<>
  460. // void EMSchur3D< Eigen::CSymSimplicialLLT< Eigen::SparseMatrix<Complex, SPARSEMAJOR>, Eigen::Lower, Eigen::NaturalOrdering<int> > > ::BuildCDirectSolver() {
  461. // CSolver = new Eigen::CSymSimplicialLLT< Eigen::SparseMatrix<Complex, SPARSEMAJOR>, Eigen::Lower, Eigen::NaturalOrdering<int> > [Omegas.size()];
  462. // for (int iw=0; iw<Omegas.size(); ++iw) {
  463. // Csym = Cvec[iw].selfadjointView<Eigen::Lower>();
  464. // jsw_timer timer;
  465. // timer.begin();
  466. // /* Complex system */
  467. // std::cout << "CSymSimplicialLLT<NaturalOrdering> pattern analyzing C_" << iw << ",";
  468. // std::cout.flush();
  469. // CSolver[iw].analyzePattern( Csym );
  470. // std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  471. // /* factorize */
  472. // timer.begin();
  473. // std::cout << "CSymSimplicialLLT<NaturalOrdering> factorising C_" << iw << ", ";
  474. // std::cout.flush();
  475. // CSolver[iw].factorize( Csym );
  476. // std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  477. // }
  478. // }
  479. //
  480. // template<>
  481. // void EMSchur3D< Eigen::CSymSimplicialLLT< Eigen::SparseMatrix<Complex, SPARSEMAJOR>, Eigen::Lower, Eigen::AMDOrdering<int> > > ::BuildCDirectSolver() {
  482. // CSolver = new Eigen::CSymSimplicialLLT< Eigen::SparseMatrix<Complex, SPARSEMAJOR>, Eigen::Lower, Eigen::AMDOrdering<int> > [Omegas.size()];
  483. // for (int iw=0; iw<Omegas.size(); ++iw) {
  484. // //Csym = Cvec[iw].selfadjointView<Eigen::Lower>();
  485. // jsw_timer timer;
  486. // timer.begin();
  487. // /* Complex system */
  488. // std::cout << "CSymSimplicialLLT<AMDOrdering> pattern analyzing C_" << iw << ",";
  489. // std::cout.flush();
  490. // CSolver[iw].analyzePattern( Cvec[iw] );
  491. // std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  492. // /* factorize */
  493. // timer.begin();
  494. // std::cout << "CSymSimplicialLLT<AMDOrdering> factorising C_" << iw << ", ";
  495. // std::cout.flush();
  496. // CSolver[iw].factorize( Cvec[iw] );
  497. // std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  498. // }
  499. // }
  500. //
  501. // template<>
  502. // void EMSchur3D< Eigen::CSymSimplicialLDLT< Eigen::SparseMatrix<Complex, SPARSEMAJOR>, Eigen::Lower, Eigen::AMDOrdering<int> > > ::BuildCDirectSolver() {
  503. // CSolver = new Eigen::CSymSimplicialLDLT< Eigen::SparseMatrix<Complex, SPARSEMAJOR>, Eigen::Lower, Eigen::AMDOrdering<int> > [Omegas.size()];
  504. // for (int iw=0; iw<Omegas.size(); ++iw) {
  505. // Csym = Cvec[iw].selfadjointView<Eigen::Lower>();
  506. // jsw_timer timer;
  507. // timer.begin();
  508. // /* Complex system */
  509. // std::cout << "CSymSimplicialLDLT<AMDOrdering> pattern analyzing C_" << iw << ",";
  510. // std::cout.flush();
  511. // CSolver[iw].analyzePattern( Csym );
  512. // std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  513. // /* factorize */
  514. // timer.begin();
  515. // std::cout << "CSymSimplicialLDLT<AMDOrdering> factorising C_" << iw << ", ";
  516. // std::cout.flush();
  517. // CSolver[iw].factorize( Csym );
  518. // std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  519. // }
  520. // }
  521. template<>
  522. void EMSchur3D< Eigen::BiCGSTAB<Eigen::SparseMatrix<Complex, SPARSEMAJOR>, Eigen::IncompleteLUT<Complex> > > ::BuildCDirectSolver() {
  523. CSolver = new Eigen::BiCGSTAB<Eigen::SparseMatrix<Complex, SPARSEMAJOR>, Eigen::IncompleteLUT<Complex> > [Omegas.size()];
  524. for (int iw=0; iw<Omegas.size(); ++iw) {
  525. //Csym = Cvec[iw].selfadjointView<Eigen::Lower>();
  526. CSolver[iw].preconditioner().setDroptol(1e-5); //1e-5); // 1e-12
  527. CSolver[iw].preconditioner().setFillfactor(1e1); // 1e2
  528. jsw_timer timer;
  529. timer.begin();
  530. /* Complex system */
  531. std::cout << "BiCGSTAB(ILU) pattern analyzing C_" << iw << ",";
  532. std::cout.flush();
  533. //CSolver[iw].analyzePattern( Csym );
  534. CSolver[iw].analyzePattern( Cvec[iw]);
  535. std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  536. /* factorize */
  537. timer.begin();
  538. std::cout << "BiCGSTAB(ILU) factorising C_" << iw << ", ";
  539. std::cout.flush();
  540. //CSolver[iw].factorize( Csym );
  541. CSolver[iw].factorize( Cvec[iw] );
  542. std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  543. }
  544. }
  545. template<>
  546. void EMSchur3D< Eigen::BiCGSTAB< Eigen::SparseMatrix<Complex, SPARSEMAJOR> > > ::BuildCDirectSolver() {
  547. CSolver = new Eigen::BiCGSTAB< Eigen::SparseMatrix<Complex, SPARSEMAJOR> > [Omegas.size()];
  548. for (int iw=0; iw<Omegas.size(); ++iw) {
  549. Csym = Cvec[iw].selfadjointView<Eigen::Lower>();
  550. jsw_timer timer;
  551. timer.begin();
  552. /* Complex system */
  553. std::cout << "BiCGSTAB pattern analyzing C_" << iw << ",";
  554. std::cout.flush();
  555. CSolver[iw].analyzePattern( Csym );
  556. std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  557. // factorize
  558. timer.begin();
  559. std::cout << "BiCGSTAB factorising C_" << iw << ", ";
  560. std::cout.flush();
  561. CSolver[iw].factorize( Csym );
  562. std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  563. }
  564. }
  565. template<>
  566. void EMSchur3D< Eigen::LeastSquaresConjugateGradient< Eigen::SparseMatrix<Complex, SPARSEMAJOR> > > ::BuildCDirectSolver() {
  567. CSolver = new Eigen::LeastSquaresConjugateGradient< Eigen::SparseMatrix<Complex, SPARSEMAJOR> > [Omegas.size()];
  568. for (int iw=0; iw<Omegas.size(); ++iw) {
  569. Csym = Cvec[iw].selfadjointView<Eigen::Lower>();
  570. jsw_timer timer;
  571. timer.begin();
  572. /* Complex system */
  573. std::cout << "LeastSquaresConjugateGradient pattern analyzing C_" << iw << ",";
  574. std::cout.flush();
  575. CSolver[iw].analyzePattern( Csym );
  576. std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  577. // factorize
  578. timer.begin();
  579. std::cout << "LeastSquaresConjugateGradient factorising C_" << iw << ", ";
  580. std::cout.flush();
  581. CSolver[iw].factorize( Csym );
  582. std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  583. }
  584. }
  585. template<>
  586. void EMSchur3D< Eigen::ConjugateGradient<Eigen::SparseMatrix<Complex, SPARSEMAJOR>, Eigen::Lower > > ::BuildCDirectSolver() {
  587. CSolver = new Eigen::ConjugateGradient<Eigen::SparseMatrix<Complex, SPARSEMAJOR>, Eigen::Lower > [Omegas.size()];
  588. for (int iw=0; iw<Omegas.size(); ++iw) {
  589. //Csym = Cvec[iw].selfadjointView<Eigen::Lower>();
  590. jsw_timer timer;
  591. timer.begin();
  592. /* Complex system */
  593. std::cout << "ConjugateGradient pattern analyzing C_" << iw << ",";
  594. std::cout.flush();
  595. CSolver[iw].analyzePattern( Cvec[iw] );
  596. std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  597. // factorize
  598. timer.begin();
  599. std::cout << "ConjugateGradient factorising C_" << iw << ", ";
  600. std::cout.flush();
  601. CSolver[iw].factorize( Cvec[iw] );
  602. std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  603. }
  604. }
  605. template<>
  606. void EMSchur3D< Eigen::ConjugateGradient<Eigen::SparseMatrix<Complex, SPARSEMAJOR>, Eigen::Lower, Eigen::IncompleteCholesky<Complex> > > ::BuildCDirectSolver() {
  607. CSolver = new Eigen::ConjugateGradient<Eigen::SparseMatrix<Complex, SPARSEMAJOR>, Eigen::Lower, Eigen::IncompleteCholesky<Complex> > [Omegas.size()];
  608. for (int iw=0; iw<Omegas.size(); ++iw) {
  609. //Csym = Cvec[iw].selfadjointView<Eigen::Lower>();
  610. jsw_timer timer;
  611. timer.begin();
  612. /* Complex system */
  613. std::cout << "ConjugateGradient<IncompleteCholesky> pattern analyzing C_" << iw << ",";
  614. std::cout.flush();
  615. CSolver[iw].analyzePattern( Cvec[iw] );
  616. std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  617. // factorize
  618. timer.begin();
  619. std::cout << "ConjugateGradient<IncompleteCholesky> factorising C_" << iw << ", ";
  620. std::cout.flush();
  621. CSolver[iw].factorize( Cvec[iw] );
  622. std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  623. }
  624. }
  625. // template<>
  626. // void EMSchur3D< Eigen::PastixLLT<Eigen::SparseMatrix<Complex, SPARSEMAJOR>, Eigen::Lower > > ::BuildCDirectSolver() {
  627. // CSolver = new Eigen::PastixLLT<Eigen::SparseMatrix<Complex, SPARSEMAJOR>, Eigen::Lower > [Omegas.size()];
  628. // //MPI_Init(NULL, NULL);
  629. // for (int iw=0; iw<Omegas.size(); ++iw) {
  630. // //Csym = Cvec[iw].selfadjointView<Eigen::Lower>();
  631. // jsw_timer timer;
  632. // timer.begin();
  633. // /* Complex system */
  634. // std::cout << "PaStiX LLT pattern analyzing C_" << iw << ",";
  635. // std::cout.flush();
  636. // CSolver[iw].analyzePattern( Cvec[iw] );
  637. // std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  638. // // factorize
  639. // timer.begin();
  640. // std::cout << "PaStiX LLT factorising C_" << iw << ", ";
  641. // std::cout.flush();
  642. // CSolver[iw].factorize( Cvec[iw] );
  643. // std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  644. // }
  645. // }
  646. //
  647. // template<>
  648. // void EMSchur3D< Eigen::PastixLDLT<Eigen::SparseMatrix<Complex, SPARSEMAJOR>, Eigen::Lower > > ::BuildCDirectSolver() {
  649. // CSolver = new Eigen::PastixLDLT<Eigen::SparseMatrix<Complex, SPARSEMAJOR>, Eigen::Lower > [Omegas.size()];
  650. // //MPI_Init(NULL, NULL);
  651. // for (int iw=0; iw<Omegas.size(); ++iw) {
  652. // //Csym = Cvec[iw].selfadjointView<Eigen::Lower>();
  653. // jsw_timer timer;
  654. // timer.begin();
  655. // /* Complex system */
  656. // std::cout << "PaStiX LDLT pattern analyzing C_" << iw << ",";
  657. // std::cout.flush();
  658. // CSolver[iw].analyzePattern( Cvec[iw] );
  659. // std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  660. // // factorize
  661. // timer.begin();
  662. // std::cout << "PaStiX LDLT factorising C_" << iw << ", ";
  663. // std::cout.flush();
  664. // CSolver[iw].factorize( Cvec[iw] );
  665. // std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  666. // std::cout << "INFO " << CSolver[iw].info( ) << std::endl;
  667. // }
  668. // }
  669. //
  670. #ifdef HAVE_PASTIX
  671. template<>
  672. void EMSchur3D< Eigen::PastixLU<Eigen::SparseMatrix<Complex, SPARSEMAJOR>, true > > ::BuildCDirectSolver() {
  673. CSolver = new Eigen::PastixLU<Eigen::SparseMatrix<Complex, SPARSEMAJOR>, true > [Omegas.size()];
  674. for (int iw=0; iw<Omegas.size(); ++iw) {
  675. jsw_timer timer;
  676. timer.begin();
  677. /* Complex system */
  678. std::cout << "PastixLU pattern analyzing C_" << iw << ",";
  679. std::cout.flush();
  680. CSolver[iw].analyzePattern( Cvec[iw].selfadjointView< Eigen::Lower>() );
  681. //CSolver[iw].analyzePattern( Cvec[iw] );
  682. std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  683. // factorize
  684. timer.begin();
  685. std::cout << "PastixLU factorising C_" << iw << ", ";
  686. std::cout.flush();
  687. CSolver[iw].factorize( Cvec[iw].selfadjointView< Eigen::Lower>() );
  688. //CSolver[iw].factorize( Cvec[iw] );
  689. std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
  690. }
  691. }
  692. #endif
  693. } // ----- end of Lemma name -----
  694. #endif // ----- #ifndef EMSCHUR3D_INC -----