45 namespace Electromagnetism{
51 template<
typename TDomain,
typename TAlgebra>
54 const std::vector<LFEID> & vLfeID,
60 UG_THROW (
"ERROR in EddyCurrent_E_Nedelec:"
61 " The discretization does not support hanging nodes.\n");
64 if (vLfeID.size () != 2)
65 UG_THROW (
"EddyCurrent_E_Nedelec: The time-harmonic problem needs two components at every edge.");
70 UG_THROW (
"EddyCurrent_E_Nedelec: This discretization works with the Nedelec-elements only.");
78 template<
typename TDomain,
typename TAlgebra>
79 template<
typename TElem>
87 if (m_spSubsetData->get_mu_sigma (si, m_permeability, m_conductivity))
88 UG_THROW (
"Cannot get material data for subset " << si <<
".");
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))
96 UG_THROW (
"More than one specification of the generator current in subset " << si <<
".");
97 m_pSsJG = & (m_vJG[i]);
102 template<
typename TDomain,
typename TAlgebra>
103 template<
typename TElem>
110 template<
typename TDomain,
typename TAlgebra>
111 template<
typename TElem>
125 static_cast<TElem*
> (elem), vCornerCoords, m_rot_rot_S, m_rot_rot_M);
170 template<
typename TDomain,
typename TAlgebra>
171 template<
size_t numEdges>
176 number S [2][numEdges] [2][numEdges]
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++)
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;
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++)
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];
208 template<
typename TDomain,
typename TAlgebra>
209 template<
typename TElem>
221 ass_elem_stiffness<NedelecT1_LDisc<TDomain, TElem>::numEdges>
222 (m_permeability, m_conductivity, S);
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++)
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];
255 template<
typename TDomain,
typename TAlgebra>
256 template<
typename TElem>
264 if (m_pSsJG == NULL)
return;
270 TElem * pElem =
static_cast<TElem*
> (elem);
271 for (
size_t part = 0; part < 2; part++)
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]);
282 for (
size_t e_1 = 0; e_1 < NedelecT1_LDisc<TDomain, TElem>::numEdges; e_1++)
284 number Re_rhs = 0, Im_rhs = 0;
285 for (
size_t e_2 = 0; e_2 < NedelecT1_LDisc<TDomain, TElem>::numEdges; e_2++)
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_];
290 b (_Re_, e_1) += m_omega * Re_rhs; b (_Im_, e_1) += m_omega * Im_rhs;
297 template<
typename TDomain,
typename TAlgebra>
298 template<
typename TElem>
310 template<
typename TDomain,
typename TAlgebra>
311 template<
typename TElem>
323 template<
typename TDomain,
typename TAlgebra>
324 template<
typename TElem>
336 template<
typename TDomain,
typename TAlgebra>
347 template<
typename TDomain,
typename TAlgebra>
348 template<
typename TElem>
353 this->clear_add_fct(
id);
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>);
375 template<
typename TDomain,
typename TAlgebra>
380 const char * ss_names
383 std::vector<std::string> tokens;
386 UG_THROW(
"EddyCurrent_E_Nedelec: Invalid grid function for the generator source");
391 SubsetGroup ssGrp (spgfJG->approx_space()->subset_handler ());
394 std::string fctString (cmp);
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);
404 for (
size_t i = 0; i < 2; i++)
408 for (
int i = 0; i < 2; i++)
411 vfctJG [i] = spgfJG->fct_id_by_name (tokens[i].c_str ());
413 UG_CATCH_THROW (
"EddyCurrent_E_Nedelec: Cannot find symbolic function "
414 "component for the name '" << tokens[i] <<
"'.");
417 for (
int i = 0; i < 2; i++)
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.");
424 if (ss_names == NULL)
429 std::string ssString (ss_names);
431 for (
size_t i = 0; i < tokens.size (); i++)
438 (
"EddyCurrent_E_Nedelec: Failed to add subsets to the source");
442 m_vJG.push_back (
tGeneratorCurrent (spgfJG, vfctJG[_Re_], vfctJG[_Im_], ssGrp, ew));
448 template<
typename TDomain,
typename TAlgebra>
452 const char * functions,
456 :
IElemDisc<TDomain> (functions, spSubsetData->subset_names ()),
458 m_spSubsetData (spSubsetData)
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).");
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
TDomain::position_type position_type
void add(const char *name)
vector< string > TokenizeString(const char *str, const char delimiter=',')
void RemoveWhitespaceFromString(std::string &string)
#define UG_CATCH_THROW(msg)
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)
Definition: eddy_current_e_nedelec.h:189
class for a generator current (source) in a subdomain
Definition: eddy_current_e_nedelec.h:221