Plugins
eddy_current_e_nedelec_impl.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013-2014: G-CSC, Goethe University Frankfurt
3  * Author: Dmitry Logashenko
4  *
5  * This file is part of UG4.
6  *
7  * UG4 is free software: you can redistribute it and/or modify it under the
8  * terms of the GNU Lesser General Public License version 3 (as published by the
9  * Free Software Foundation) with the following additional attribution
10  * requirements (according to LGPL/GPL v3 §7):
11  *
12  * (1) The following notice must be displayed in the Appropriate Legal Notices
13  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14  *
15  * (2) The following notice must be displayed at a prominent place in the
16  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17  *
18  * (3) The following bibliography is recommended for citation and must be
19  * preserved in all covered files:
20  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21  * parallel geometric multigrid solver on hierarchically distributed grids.
22  * Computing and visualization in science 16, 4 (2013), 151-164"
23  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24  * flexible software system for simulating pde based models on high performance
25  * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26  *
27  * This program is distributed in the hope that it will be useful,
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30  * GNU Lesser General Public License for more details.
31  */
32 
33 /*
34  * Implementation of the class member functions templates of the complex-valued
35  * FE discretization of the eddy current model.
36  */
37 
38 /* UG4 headers: */
39 #include "common/util/provider.h"
40 #ifdef UG_FOR_LUA
42 #endif
43 
44 namespace ug{
45 namespace Electromagnetism{
46 
48 // check the grid and the shape functions
50 
51 template<typename TDomain, typename TAlgebra>
53 (
54  const std::vector<LFEID> & vLfeID,
55  bool bNonRegular
56 )
57 {
58 // check the grid
59  if (bNonRegular)
60  UG_THROW ("ERROR in EddyCurrent_E_Nedelec:"
61  " The discretization does not support hanging nodes.\n");
62 
63 // check number of the components
64  if (vLfeID.size () != 2)
65  UG_THROW ("EddyCurrent_E_Nedelec: The time-harmonic problem needs two components at every edge.");
66  /* one component for the real part and one for the imaginary part */
67 
68 // check that these are the Nedelec elements
69  if (vLfeID[0].type() != LFEID::NEDELEC || vLfeID[1].type() != LFEID::NEDELEC)
70  UG_THROW ("EddyCurrent_E_Nedelec: This discretization works with the Nedelec-elements only.");
71 }
72 
74 // assembling
76 
78 template<typename TDomain, typename TAlgebra>
79 template<typename TElem>
81 (
82  ReferenceObjectID roid,
83  int si
84 )
85 {
86 // Get the data for the subset:
87  if (m_spSubsetData->get_mu_sigma (si, m_permeability, m_conductivity))
88  UG_THROW ("Cannot get material data for subset " << si << ".");
89 
90 // Get the source for this subset
91  m_pSsJG = NULL;
92  for (size_t i = 0; i < m_vJG.size (); i++)
93  if (m_vJG[i].m_everywhere || m_vJG[i].m_ssGrp.contains (si))
94  {
95  if (m_pSsJG != NULL)
96  UG_THROW ("More than one specification of the generator current in subset " << si << ".");
97  m_pSsJG = & (m_vJG[i]);
98  }
99 }
100 
102 template<typename TDomain, typename TAlgebra>
103 template<typename TElem>
105 {
106  m_pSsJG = NULL;
107 }
108 
110 template<typename TDomain, typename TAlgebra>
111 template<typename TElem>
113 (
114  const LocalVector & u,
115  GridObject * elem,
116  ReferenceObjectID roid, // id of reference element used for assembling
117  const position_type vCornerCoords []
118 )
119 {
120 /* BEGIN code essential for the numerics */
121 
122 // compute the local matrices of the rot-rot operator:
125  static_cast<TElem*> (elem), vCornerCoords, m_rot_rot_S, m_rot_rot_M);
126 
127 /* END code essential for the numerics */
128 }
129 
131 
170 template<typename TDomain, typename TAlgebra>
171 template<size_t numEdges>
173 (
174  number perm,
175  number cond,
176  number S [2][numEdges] [2][numEdges]
177 )
178 {
179 /* BEGIN code essential for the numerics */
180 
181  cond *= m_omega;
182 
183 // the lower triange (w.r.t. the edge dofs, not the Re/Im parts)
184  for (size_t e_1 = 0; e_1 < numEdges; e_1++)
185  for (size_t e_2 = 0; e_2 <= e_1; e_2++)
186  {
187  S [_Re_][e_1] [_Re_][e_2]
188  = - (S [_Im_][e_1] [_Im_][e_2]
189  = m_rot_rot_S [e_1] [e_2] / perm);
190  S [_Re_][e_1] [_Im_][e_2]
191  = S [_Im_][e_1] [_Re_][e_2]
192  = m_rot_rot_M [e_1] [e_2] * cond;
193  }
194 // the upper triangle
195  for (size_t e_1 = 0; e_1 < numEdges - 1; e_1++)
196  for (size_t e_2 = e_1+1; e_2 < numEdges; e_2++)
197  {
198  S [_Re_][e_1] [_Re_][e_2] = S [_Re_][e_2] [_Re_][e_1];
199  S [_Re_][e_1] [_Im_][e_2] = S [_Re_][e_2] [_Im_][e_1];
200  S [_Im_][e_1] [_Im_][e_2] = S [_Im_][e_2] [_Im_][e_1];
201  S [_Im_][e_1] [_Re_][e_2] = S [_Im_][e_2] [_Re_][e_1];
202  }
203 
204 /* END code essential for the numerics */
205 }
206 
208 template<typename TDomain, typename TAlgebra>
209 template<typename TElem>
211 (
212  LocalMatrix & J,
213  const LocalVector & u,
214  GridObject * elem,
215  const position_type vCornerCoords []
216 )
217 {
220 
221  ass_elem_stiffness<NedelecT1_LDisc<TDomain, TElem>::numEdges>
222  (m_permeability, m_conductivity, S);
223 
224  for (size_t e_1 = 0; e_1 < NedelecT1_LDisc<TDomain, TElem>::numEdges; e_1++)
225  for (size_t e_2 = 0; e_2 < NedelecT1_LDisc<TDomain, TElem>::numEdges; e_2++)
226  {
227  J(_Re_, e_1, _Re_, e_2) += S [_Re_][e_1] [_Re_][e_2];
228  J(_Re_, e_1, _Im_, e_2) += S [_Re_][e_1] [_Im_][e_2];
229  J(_Im_, e_1, _Im_, e_2) += S [_Im_][e_1] [_Im_][e_2];
230  J(_Im_, e_1, _Re_, e_2) += S [_Im_][e_1] [_Re_][e_2];
231  }
232 }
233 
235 
255 template<typename TDomain, typename TAlgebra>
256 template<typename TElem>
258 (
259  LocalVector & b,
260  GridObject * elem,
261  const position_type vCornerCoords []
262 )
263 {
264  if (m_pSsJG == NULL) return; // no rhs
265 
266 // The generator current (source) at the dofs
268 
269 // Get the generator current from the grid functions
270  TElem * pElem = static_cast<TElem*> (elem);
271  for (size_t part = 0; part < 2; part++) // Re and Im
272  {
273  std::vector<DoFIndex> ind;
274  m_pSsJG->m_spGf->dof_indices (pElem, m_pSsJG->m_vFct[part], ind);
275  for (size_t e = 0; e < NedelecT1_LDisc<TDomain, TElem>::numEdges; e++)
276  vJG[e][part] = DoFRef (* (m_pSsJG->m_spGf), ind[e]);
277  }
278 
279 /* BEGIN code essential for the numerics */
280 
281 // Assemble the possibly non-zero rhs:
282  for (size_t e_1 = 0; e_1 < NedelecT1_LDisc<TDomain, TElem>::numEdges; e_1++)
283  {
284  number Re_rhs = 0, Im_rhs = 0;
285  for (size_t e_2 = 0; e_2 < NedelecT1_LDisc<TDomain, TElem>::numEdges; e_2++)
286  {
287  Re_rhs -= m_rot_rot_M[e_1][e_2] * vJG[e_2][_Im_];
288  Im_rhs -= m_rot_rot_M[e_1][e_2] * vJG[e_2][_Re_];
289  }
290  b (_Re_, e_1) += m_omega * Re_rhs; b (_Im_, e_1) += m_omega * Im_rhs;
291  }
292 
293 /* END code essential for the numerics */
294 }
295 
297 template<typename TDomain, typename TAlgebra>
298 template<typename TElem>
300 (
301  LocalVector & d, const LocalVector & u, GridObject * elem, const position_type vCornerCoords []
302 )
303 {}
304 
306 
310 template<typename TDomain, typename TAlgebra>
311 template<typename TElem>
313 (
314  LocalMatrix & J, const LocalVector & u, GridObject * elem, const position_type vCornerCoords []
315 )
316 {}
317 
319 
323 template<typename TDomain, typename TAlgebra>
324 template<typename TElem>
326 (
327  LocalVector & d, const LocalVector & u, GridObject * elem, const position_type vCornerCoords []
328 )
329 {}
330 
332 // register assembling functions
334 
336 template<typename TDomain, typename TAlgebra>
338 {
339 // get all grid element types in this dimension and below
340  typedef typename domain_traits<dim>::DimElemList ElemList;
341 
342 // switch assemble functions
343  boost::mpl::for_each<ElemList> (RegisterLocalDiscr (this));
344 }
345 
347 template<typename TDomain, typename TAlgebra>
348 template<typename TElem> // the element to register for
350 {
352 
353  this->clear_add_fct(id);
354 
355  this->set_prep_elem_loop_fct(id, & this_type::template prepare_element_loop<TElem>);
356  this->set_prep_elem_fct (id, & this_type::template prepare_element<TElem>);
357  this->set_fsh_elem_loop_fct (id, & this_type::template finish_element_loop<TElem>);
358  this->set_add_jac_A_elem_fct(id, & this_type::template ass_JA_elem<TElem>);
359  this->set_add_jac_M_elem_fct(id, & this_type::template ass_JM_elem<TElem>);
360  this->set_add_def_A_elem_fct(id, & this_type::template ass_dA_elem<TElem>);
361  this->set_add_def_M_elem_fct(id, & this_type::template ass_dM_elem<TElem>);
362  this->set_add_rhs_elem_fct (id, & this_type::template ass_rhs_elem<TElem>);
363 }
364 
366 // obtaining the parameters
368 
375 template<typename TDomain, typename TAlgebra>
377 (
378  SmartPtr<TGridFunction> spgfJG,
379  const char * cmp,
380  const char * ss_names
381 )
382 {
383  std::vector<std::string> tokens;
384 
385  if (spgfJG.invalid ())
386  UG_THROW("EddyCurrent_E_Nedelec: Invalid grid function for the generator source");
387 
388 // Data to get:
389  size_t vfctJG [2];
390  bool ew;
391  SubsetGroup ssGrp (spgfJG->approx_space()->subset_handler ());
392 
393 // Get function names:
394  std::string fctString (cmp);
395 
396 // Tokenize the strings and select functions
397  TokenizeString (fctString, tokens, ',');
398 
399  if ((int) tokens.size () != 2)
400  UG_THROW("EddyCurrent_E_Nedelec: Needed 2 components "
401  "in symbolic function names for the generator current (for Re and Im), "
402  "but given: " << cmp);
403 
404  for (size_t i = 0; i < 2; i++)
405  RemoveWhitespaceFromString (tokens [i]);
406 
407 // Get function id's by names:
408  for (int i = 0; i < 2; i++)
409  try
410  {
411  vfctJG [i] = spgfJG->fct_id_by_name (tokens[i].c_str ());
412  }
413  UG_CATCH_THROW ("EddyCurrent_E_Nedelec: Cannot find symbolic function "
414  "component for the name '" << tokens[i] << "'.");
415 
416 // Check the function space of the grid function:
417  for (int i = 0; i < 2; i++)
418  if (spgfJG->local_finite_element_id(vfctJG[i]) != LFEID(LFEID::NEDELEC, dim, 1))
419  UG_THROW ("EddyCurrent_E_Nedelec: The function space of component "
420  << tokens[i] << " of the grid function does not correspond "
421  "to the Nedelec element.");
422 
423 // Get the subsets:
424  if (ss_names == NULL)
425  ew = true;
426  else
427  {
428  ew = false;
429  std::string ssString (ss_names);
430  TokenizeString (ssString, tokens, ',');
431  for (size_t i = 0; i < tokens.size (); i++)
432  RemoveWhitespaceFromString (tokens [i]);
433  try
434  {
435  ssGrp.add (tokens);
436  }
438  ("EddyCurrent_E_Nedelec: Failed to add subsets to the source");
439  }
440 
441 // Create the source:
442  m_vJG.push_back (tGeneratorCurrent (spgfJG, vfctJG[_Re_], vfctJG[_Im_], ssGrp, ew));
443 }
444 
448 template<typename TDomain, typename TAlgebra>
451 (
452  const char * functions,
453  ConstSmartPtr<EMaterial<domain_type> > spSubsetData,
454  number frequency
455 )
456 : IElemDisc<TDomain> (functions, spSubsetData->subset_names ()),
457  m_omega (frequency),
458  m_spSubsetData (spSubsetData)
459 {
460 // check number of functions
461  if (this->num_fct () != 2)
462  UG_THROW ("Wrong number of functions: The ElemDisc 'EddyCurrent_E_Nedelec'"
463  " needs exactly 2 symbolic functions"
464  " (one for the real part and one for the imaginary one).");
465 
466 // register assemble functions
468 }
469 
470 } // end namespace Electromagnetism
471 } // end namespace ug
472 
473 /* End of File */
Class for subdomain-dependent data for the E-based formulated problems.
Definition: em_material.h:63
FE-discretization of the time-harmonic E-based formulation of the eddy current model.
Definition: eddy_current_e_nedelec.h:98
void prepare_element(const LocalVector &u, GridObject *elem, ReferenceObjectID roid, const position_type vCornerCoords[])
prepares a given element for assembling: computes the discretization of the rot-rot operator
Definition: eddy_current_e_nedelec_impl.h:113
void ass_rhs_elem(LocalVector &d, GridObject *elem, const position_type vCornerCoords[])
computes the right-hand side due to the generator currents
Definition: eddy_current_e_nedelec_impl.h:258
void ass_dA_elem(LocalVector &d, const LocalVector &u, GridObject *elem, const position_type vCornerCoords[])
computes the local defect and transfers it to the global discretization
Definition: eddy_current_e_nedelec_impl.h:300
EddyCurrent_E_Nedelec(const char *functions, ConstSmartPtr< EMaterial< domain_type > > spSubsetData, number frequency)
class constructor
Definition: eddy_current_e_nedelec_impl.h:451
void register_all_loc_discr_funcs()
registers the local assembler functions for all the elements and dimensions
Definition: eddy_current_e_nedelec_impl.h:337
void ass_JM_elem(LocalMatrix &J, const LocalVector &u, GridObject *elem, const position_type vCornerCoords[])
computes the mass matrix of a time-dependent problem
Definition: eddy_current_e_nedelec_impl.h:313
void ass_dM_elem(LocalVector &d, const LocalVector &u, GridObject *elem, const position_type vCornerCoords[])
computes the mass part of the defect of a time-dependent problem
Definition: eddy_current_e_nedelec_impl.h:326
void prepare_element_loop(ReferenceObjectID roid, int si)
prepares the loop over the elements: checks whether the parameters are set, ...
Definition: eddy_current_e_nedelec_impl.h:81
void set_generator_current(SmartPtr< TGridFunction > spgfJG, const char *cmp, const char *ss_names=NULL)
adds a generator current item to the discretization
Definition: eddy_current_e_nedelec_impl.h:377
void register_loc_discr_func()
registers the local assembler functions for a given element
Definition: eddy_current_e_nedelec_impl.h:349
void finish_element_loop()
finalizes the loop over the elements: clear the source
Definition: eddy_current_e_nedelec_impl.h:104
virtual void prepare_setting(const std::vector< LFEID > &vLfeID, bool bNonRegular)
check type of the grid and the trial space
Definition: eddy_current_e_nedelec_impl.h:53
void ass_JA_elem(LocalMatrix &J, const LocalVector &u, GridObject *elem, const position_type vCornerCoords[])
transfers the precomputed local stiffness matrix to the global discretization
Definition: eddy_current_e_nedelec_impl.h:211
void ass_elem_stiffness(number perm, number cond, number S[2][numEdges][2][numEdges])
composes the stiffness matrix of the stationary problem
Definition: eddy_current_e_nedelec_impl.h:173
Tool kit for the Whitney-1 (Nedelec) based FE discretization of the rot-rot operators.
Definition: nedelec_local_ass.h:85
static void local_stiffness_and_mass(const TDomain *domain, TElem *elem, const position_type *corners, number S[maxNumEdges][maxNumEdges], number M[maxNumEdges][maxNumEdges])
assembles the local stiffness and the mass matrices of the rot-rot operator
Definition: nedelec_local_ass.h:119
size_t num_fct() const
TDomain::position_type position_type
void add(const char *name)
static const int dim
Variant::Type type()
vector< string > TokenizeString(const char *str, const char delimiter=',')
void RemoveWhitespaceFromString(std::string &string)
#define UG_CATCH_THROW(msg)
#define UG_THROW(msg)
double number
SM_edge_weight_map< typename T::value_type, ug::BidirectionalMatrix< T > > get(edge_weight_t, ug::BidirectionalMatrix< T > const &g)
const number & DoFRef(const TMatrix &mat, const DoFIndex &iInd, const DoFIndex &jInd)
ReferenceObjectID
class for a generator current (source) in a subdomain
Definition: eddy_current_e_nedelec.h:221