Galerkin FEM for elliptic PDEs
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.

LinearMag.cpp 9.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  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 03/21/2016 02:10:08 PM
  11. * @author Trevor Irons (ti)
  12. * @email tirons@egi.utah.edu
  13. * @copyright Copyright (c) 2016, University of Utah
  14. * @copyright Copyright (c) 2016, Lemma Software, LLC
  15. */
  16. #include "LinearMag.h"
  17. namespace Lemma {
  18. // ==================== FRIEND METHODS =====================
  19. std::ostream &operator << (std::ostream &stream, const LinearMag &ob) {
  20. stream << ob.Serialize() << "\n";
  21. return stream;
  22. }
  23. // ==================== LIFECYCLE =======================
  24. //--------------------------------------------------------------------------------------
  25. // Class: LinearMag
  26. // Method: LinearMag
  27. // Description: constructor (protected)
  28. //--------------------------------------------------------------------------------------
  29. LinearMag::LinearMag (const ctor_key& key) : FEM4EllipticPDE(key) {
  30. } // ----- end of method LinearMag::LinearMag (constructor) -----
  31. //--------------------------------------------------------------------------------------
  32. // Class: LinearMag
  33. // Method: LinearMag
  34. // Description: DeSerializing constructor (protected)
  35. //--------------------------------------------------------------------------------------
  36. LinearMag::LinearMag (const YAML::Node& node, const ctor_key& key) : FEM4EllipticPDE(node, key) {
  37. } // ----- end of method LinearMag::LinearMag (constructor) -----
  38. //--------------------------------------------------------------------------------------
  39. // Class: LinearMag
  40. // Method: New()
  41. // Description: public constructor
  42. //--------------------------------------------------------------------------------------
  43. std::shared_ptr<LinearMag> LinearMag::NewSP() {
  44. return std::make_shared<LinearMag>( ctor_key() );
  45. }
  46. //--------------------------------------------------------------------------------------
  47. // Class: LinearMag
  48. // Method: ~LinearMag
  49. // Description: destructor (protected)
  50. //--------------------------------------------------------------------------------------
  51. LinearMag::~LinearMag () {
  52. } // ----- end of method LinearMag::~LinearMag (destructor) -----
  53. //--------------------------------------------------------------------------------------
  54. // Class: LinearMag
  55. // Method: Serialize
  56. //--------------------------------------------------------------------------------------
  57. YAML::Node LinearMag::Serialize ( ) const {
  58. YAML::Node node = FEM4EllipticPDE::Serialize();;
  59. node.SetTag( this->GetName() );
  60. // FILL IN CLASS SPECIFICS HERE
  61. node["B0"] = B0;
  62. return node;
  63. } // ----- end of method LinearMag::Serialize -----
  64. //--------------------------------------------------------------------------------------
  65. // Class: LinearMag
  66. // Method: DeSerialize
  67. //--------------------------------------------------------------------------------------
  68. std::shared_ptr<LinearMag> LinearMag::DeSerialize ( const YAML::Node& node ) {
  69. if ( node.Tag() != "LinearMag") {
  70. throw DeSerializeTypeMismatch( "LinearMag", node.Tag() );
  71. }
  72. return std::make_shared<LinearMag>( node, ctor_key() );
  73. } // ----- end of method LinearMag::DeSerialize -----
  74. //--------------------------------------------------------------------------------------
  75. // Class: LinearMag
  76. // Method: SetInducingMagField
  77. //--------------------------------------------------------------------------------------
  78. void LinearMag::SetInducingMagField ( const Real& intensity, const Real& inc,
  79. const Real& dec, const MAGUNITS& U ) {
  80. B0(0) = intensity * std::cos(inc) * std::cos(dec); // northing
  81. B0(1) = intensity * std::cos(inc) * std::sin(dec); // easting
  82. B0(2) = intensity * std::sin(inc); // z
  83. ScaleB0(U);
  84. return ;
  85. } // ----- end of method LinearMag::SetInducingMagField -----
  86. //--------------------------------------------------------------------------------------
  87. // Class: LinearMag
  88. // Method: SetInducingMagFieldVector
  89. //--------------------------------------------------------------------------------------
  90. void LinearMag::SetInducingMagFieldVector ( const Vector3r& BB0, const MAGUNITS& U ) {
  91. B0 = BB0;
  92. ScaleB0(U);
  93. return ;
  94. } // ----- end of method LinearMag::SetInducingMagFieldVector -----
  95. //--------------------------------------------------------------------------------------
  96. // Class: LinearMag
  97. // Method: ScaleB0
  98. //--------------------------------------------------------------------------------------
  99. void LinearMag::ScaleB0 ( const MAGUNITS& U ) {
  100. switch ( U ) {
  101. case TESLA:
  102. break;
  103. case NANOTESLA:
  104. B0 *= 1e-9;
  105. break;
  106. case GAUSS:
  107. B0 *= 1e-4;
  108. break;
  109. }
  110. return ;
  111. } // ----- end of method LinearMag::ScaleB0 -----
  112. //--------------------------------------------------------------------------------------
  113. // Class: LinearMag
  114. // Method: CalculateRHS
  115. //--------------------------------------------------------------------------------------
  116. void LinearMag::CalculateRHS ( const std::string& susName ) {
  117. std::cout << "Calculating RHS...";
  118. std::cout.flush();
  119. if ( !vtkGrid->GetCellData()->GetScalars(susName.c_str()) ) {
  120. std::string err("No cell data by name ");
  121. err.append(susName);
  122. throw std::runtime_error(err.c_str());
  123. }
  124. if (!vtkGrid->GetNumberOfPoints()) {
  125. throw std::runtime_error("Number of points zero in input grid!");
  126. }
  127. vtkDoubleArray* G = vtkDoubleArray::New();
  128. G->SetNumberOfComponents(1);
  129. G->SetNumberOfTuples( vtkGrid->GetNumberOfPoints() );
  130. G->SetName("G");
  131. //g.resize(vtkGrid->GetNumberOfPoints());
  132. VectorXr GG = VectorXr::Zero( vtkGrid->GetNumberOfPoints() );
  133. // Iterate over all the points or all of the cells?
  134. for (int ic=0; ic < vtkGrid->GetNumberOfCells(); ++ic) {
  135. if ( vtkGrid->GetCell(ic)->GetNumberOfPoints() != 4 ) {
  136. throw std::runtime_error("Non-tetrahedral mesh encountered!");
  137. }
  138. Real cellSus = vtkGrid->GetCellData()->GetScalars(susName.c_str())->GetTuple(ic)[0];
  139. Eigen::Matrix<Real, 4, 4> C = Eigen::Matrix<Real, 4, 4>::Zero() ;
  140. for (int ii=0; ii<4; ++ii) {
  141. double* pts = vtkGrid->GetCell(ic)->GetPoints()->GetPoint(ii);
  142. C(ii, 0) = 1;
  143. C(ii, 1) = pts[0];
  144. C(ii, 2) = pts[1];
  145. C(ii, 3) = pts[2];
  146. }
  147. /* The indices */
  148. vtkIdList* Ids = vtkGrid->GetCell(ic)->GetPointIds();
  149. int ID[4];
  150. ID[0] = Ids->GetId(0);
  151. ID[1] = Ids->GetId(1);
  152. ID[2] = Ids->GetId(2);
  153. ID[3] = Ids->GetId(3);
  154. /* the 4 faces of the tetrahedra
  155. ID[0] ID[1] ID[2]
  156. ID[0] ID[1] ID[3]
  157. ID[0] ID[2] ID[3]
  158. ID[1] ID[2] ID[3]
  159. */
  160. // Face 0, ID 0,1,2
  161. Eigen::Matrix<Real, 3, 2> CC = Eigen::Matrix<Real, 3, 2>::Ones() ;
  162. CC.col(1) = C.row(0).tail<3>() - C.row(1).tail<3>();
  163. CC.col(2) = C.row(0).tail<3>() - C.row(2).tail<3>();
  164. Vector3r nhat = CC.col(1).cross(CC.col(2));
  165. nhat.array() /= nhat.norm();
  166. Real flux = cellSus*nhat.dot(B0);
  167. GG(ID[0]) += flux;
  168. GG(ID[1]) += flux;
  169. GG(ID[2]) += flux;
  170. // Face 1, ID 0,1,3
  171. {
  172. CC.col(1) = C.row(0).tail<3>() - C.row(1).tail<3>();
  173. CC.col(2) = C.row(0).tail<3>() - C.row(3).tail<3>();
  174. Vector3r nhat = CC.col(1).cross(CC.col(2));
  175. nhat.array() /= nhat.norm();
  176. Real flux = cellSus*nhat.dot(B0);
  177. GG(ID[0]) += flux;
  178. GG(ID[1]) += flux;
  179. GG(ID[3]) += flux;
  180. }
  181. // Face 2, ID 0,2,3
  182. {
  183. CC.col(1) = C.row(0).tail<3>() - C.row(2).tail<3>();
  184. CC.col(2) = C.row(0).tail<3>() - C.row(3).tail<3>();
  185. Vector3r nhat = CC.col(1).cross(CC.col(2));
  186. nhat.array() /= nhat.norm();
  187. Real flux = cellSus*nhat.dot(B0);
  188. GG(ID[0]) += flux;
  189. GG(ID[2]) += flux;
  190. GG(ID[3]) += flux;
  191. }
  192. // Face 3, ID 1,2,3
  193. {
  194. CC.col(1) = C.row(1).tail<3>() - C.row(2).tail<3>();
  195. CC.col(2) = C.row(1).tail<3>() - C.row(3).tail<3>();
  196. Vector3r nhat = CC.col(1).cross(CC.col(2));
  197. nhat.array() /= nhat.norm();
  198. Real flux = cellSus*nhat.dot(B0);
  199. GG(ID[1]) += flux;
  200. GG(ID[2]) += flux;
  201. GG(ID[3]) += flux;
  202. }
  203. }
  204. for (int ip=0; ip<vtkGrid->GetNumberOfPoints(); ++ip) {
  205. G->InsertTuple1( ip, GG(ip) );
  206. }
  207. vtkGrid->GetPointData()->AddArray( G );
  208. vtkGrid->GetPointData()->SetScalars( G );
  209. std::cout << "finished" << std::endl;
  210. return ;
  211. } // ----- end of method LinearMag::CalculateRHS -----
  212. } // ----- end of Lemma name -----