45 namespace Electromagnetism{
50 template <
typename TDomain,
typename TAlgebra>
54 const char * posSsNames,
55 const char * cutSsNames,
59 : m_allSsNames ((
std::string (ssNames) +
',') + posSsNames), m_posSsNames (posSsNames), m_cutSsNames (cutSsNames),
60 m_spVertApproxSpace (vertApproxSpace),
66 m_potSolver (potSolver)
70 UG_THROW (
"NedelecLoopCurrent: Illegal vert.-centered approx. space.");
72 UG_THROW (
"NedelecLoopCurrent: Exactly one function should be defined in the vert.-centered approx. space.");
74 UG_THROW (
"NedelecLoopCurrent: The function in the vert.-centered approx. space must be defined everywhere.");
76 UG_THROW (
"NedelecLoopCurrent: Illegal solver for the auxiliary problems.");
79 std::vector<std::string> vssNames;
83 for (
size_t i = 0; i < vssNames.size(); i++)
88 for (
size_t i = 0; i < vssNames.size(); i++)
93 for (
size_t i = 0; i < vssNames.size(); i++)
106 template <
typename TDomain,
typename TAlgebra>
109 const char * fctNames,
113 m_vSrcData.push_back (
TSrcData (fctNames, I));
119 template <
typename TDomain,
typename TAlgebra>
128 if (m_vSrcData.size () == 0)
129 UG_THROW (
"NedelecLoopCurrent: No electric currents specified.");
133 UG_THROW (
"NedelecLoopCurrent: Illegal grid function specification.");
146 compute_potential (pot_u);
150 boost::mpl::for_each<ElemList>
152 * vertDD.
get (), pot_scaling));
159 pot_scaling = - pot_scaling;
162 for (
size_t i_data = 0; i_data < m_vSrcData.size (); i_data++)
170 UG_CATCH_THROW (
"NedelecLoopCurrent: Functions '" << m_vSrcData[i_data].fctNames <<
171 "' not all contained in the edge approximation space.");
174 for (
size_t i_fct = 0; i_fct < fctGrp.
size (); i_fct++)
176 UG_THROW (
"NedelecLoopCurrent: Not a Nedelec-element-based grid function specified for the source.");
179 number value = m_vSrcData[i_data].I / pot_scaling;
180 for (
size_t i_fct = 0; i_fct < fctGrp.
size (); i_fct++)
181 distribute_source_potential (* vertDD.
get (), pot_u, * edgeDD.
get (),
182 fctGrp[i_fct], value, u);
196 template <
typename TDomain,
typename TAlgebra>
197 template <
typename TElem>
211 for (
size_t i = 0; i < m_allSsGrp.size (); i++)
213 int si = m_allSsGrp [i];
214 bool in_pos = m_posSsGrp.contains (si);
216 iterator e_end = edgeDD.template end<TElem> (si);
217 for (iterator elem_iter = edgeDD.template begin<TElem> (si);
218 elem_iter != e_end; ++elem_iter)
220 TElem * pElem = *elem_iter;
222 UG_ASSERT ((edge_list.
size () == (
size_t) ref_elem_type::numEdges),
223 "Mismatch of numbers of corners and vertices of an element");
224 for (
size_t e = 0; e < (size_t) ref_elem_type::numEdges; e++)
226 Edge * pEdge = edge_list[e];
235 in_source [pEdge] = flag;
244 template <
typename TDomain,
typename TAlgebra>
256 m_outOfSource->init (pot_u.
domain().
get (), a_in_source);
260 m_auxLaplaceOp->set_level (pot_u.
grid_level ());
261 m_auxLaplaceOp->init_op_and_rhs (pot_rhs);
264 m_potSolver->
init (m_auxLaplaceOp);
267 m_potSolver->apply (pot_u, pot_rhs);
279 template <
typename TDomain,
typename TAlgebra>
297 t_edge_iter edgeIterBeg = edgeDD.
begin<
Edge> ();
298 t_edge_iter edgeIterEnd = edgeDD.
end<
Edge> ();
302 sp_mg->attach_to_edges (a_in_source);
305 boost::mpl::for_each<ElemList> (
MarkSourceEdges (
this, edgeDD, aa_in_source));
307 AttachmentAllReduce<Edge> (*sp_mg, a_in_source,
PCL_RO_BOR);
311 std::vector<size_t> vVertInd (1);
312 std::vector<DoFIndex> vEdgeInd (1);
313 for (t_edge_iter edgeIter = edgeIterBeg; edgeIter != edgeIterEnd; ++edgeIter)
315 Edge * pEdge = *edgeIter;
321 UG_THROW (
"NedelecLoopCurrent: Edge DoF distribution mismatch. Not the Nedelec-Type-1 element?");
322 if ((edge_flag = aa_in_source [pEdge]) == 0)
324 DoFRef (src_field, vEdgeInd [0]) = 0;
329 for (
size_t i = 0; i < 2; i++)
333 UG_THROW (
"NedelecLoopCurrent: Vertex DoF distribution mismatch. Not the Lagrange-Order-1 element?");
334 nd_pot [i] = src_pot [vVertInd [0]];
335 if ((edge_flag & (2 << i)) != 0)
340 DoFRef (src_field, vEdgeInd [0]) = value * (nd_pot [1] - nd_pot [0]);
344 sp_mg->detach_from_edges (a_in_source);
352 template <
typename TDomain,
typename TAlgebra>
353 template <
typename TElem>
358 number loc_A [numCorners] [numCorners]
366 UG_ASSERT (geo.num_ip () == 1,
"Only the simplest quadrature is supported here.");
369 geo.update (elem, vCornerCoords);
372 for (
size_t from_co = 0; from_co < (size_t) numCorners; from_co++)
373 for (
size_t to_co = from_co; to_co < (size_t) numCorners; to_co++)
374 loc_A [from_co] [to_co]
375 =
VecDot (geo.global_grad (0, from_co), geo.global_grad (0, to_co))
378 for (
size_t from_co = 1; from_co < (size_t) numCorners; from_co++)
379 for (
size_t to_co = 0; to_co < from_co; to_co++)
380 loc_A [from_co] [to_co] = loc_A [to_co] [from_co];
386 template <
typename TDomain,
typename TAlgebra>
387 template <
typename TElem>
392 bool bnd_flag [numCorners]
395 TElem * pElem = (TElem *) elem;
399 for (
size_t i = 0; i < (size_t) numCorners; i++)
409 template <
typename TDomain,
typename TAlgebra>
414 :
IElemDisc<TDomain> (master.m_spVertApproxSpace->name(0).c_str(), master.m_allSsNames.c_str()),
416 m_posSsGrp (master.m_spVertApproxSpace->
subset_handler (), master.m_posSsNames),
417 m_cutSsGrp (master.m_spVertApproxSpace->
subset_handler (), master.m_cutSsNames),
418 m_in_pos_subset (false)
422 UG_THROW (
"NedelecLoopCurrent: No positive direction subsets specified");
424 UG_THROW (
"NedelecLoopCurrent: No cut specified");
430 template<
typename TDomain,
typename TAlgebra>
433 const std::vector<LFEID> & vLfeID,
439 " The discretization of the auxiliary systems does not support hanging nodes.\n");
441 if (vLfeID.size () != 1)
443 " Only scalar grid functions are supported for the potential");
447 " Only Largange-1 functions are supported for the potential");
451 template<
typename TDomain,
typename TAlgebra>
462 template<
typename TDomain,
typename TAlgebra>
463 template<
typename TElem>
468 this->clear_add_fct(
id);
470 this->set_prep_elem_loop_fct(
id, & AuxLaplaceLocAss::template prepare_element_loop<TElem>);
471 this->set_prep_elem_fct (
id, & AuxLaplaceLocAss::template prepare_element<TElem>);
472 this->set_fsh_elem_loop_fct (
id, & AuxLaplaceLocAss::template finish_element_loop<TElem>);
473 this->set_add_jac_A_elem_fct(
id, & AuxLaplaceLocAss::template ass_JA_elem<TElem>);
474 this->set_add_jac_M_elem_fct(
id, & AuxLaplaceLocAss::template ass_JM_elem<TElem>);
475 this->set_add_def_A_elem_fct(
id, & AuxLaplaceLocAss::template ass_dA_elem<TElem>);
476 this->set_add_def_M_elem_fct(
id, & AuxLaplaceLocAss::template ass_dM_elem<TElem>);
477 this->set_add_rhs_elem_fct (
id, & AuxLaplaceLocAss::template ass_rhs_elem<TElem>);
481 template<
typename TDomain,
typename TAlgebra>
482 template<
typename TElem>
493 template<
typename TDomain,
typename TAlgebra>
494 template<
typename TElem>
506 number loc_A [ref_elem_type::numCorners] [ref_elem_type::numCorners];
510 for (
size_t from_co = 0; from_co < (size_t) ref_elem_type::numCorners; from_co++)
511 for (
size_t to_co = 0; to_co < (size_t) ref_elem_type::numCorners; to_co++)
512 J (_C_, from_co, _C_, to_co) += loc_A [from_co] [to_co];
516 template<
typename TDomain,
typename TAlgebra>
517 template <
typename TElem>
527 if (! m_in_pos_subset)
return;
530 bool at_cut [ref_elem_type::numCorners];
532 (elem, m_master.m_cutSsGrp, at_cut))
536 number loc_A [ref_elem_type::numCorners] [ref_elem_type::numCorners];
538 (elem, vCornerCoords, loc_A);
539 for (
size_t i = 0; i < (size_t) ref_elem_type::numCorners; i++)
540 for (
size_t j = 0; j < (size_t) ref_elem_type::numCorners; j++)
542 d (_C_, i) -= loc_A [i] [j];
550 template <
typename TDomain,
typename TAlgebra>
561 template <
typename TDomain,
typename TAlgebra>
562 template <
typename TElem>
572 const MultiGrid * mg = dom->grid().get ();
577 for (
size_t i = 0; i < m_master.m_allSsGrp.size (); i++)
579 int si = m_master.m_allSsGrp [i];
580 for (
size_t lev = 0; lev < n_levels; lev++)
583 iterator e_end = ssh->template end<TElem> (si, lev);
584 for (iterator elem_iter = ssh->template begin<TElem> (si, lev);
585 elem_iter != e_end; ++elem_iter)
587 TElem * pElem = *elem_iter;
588 for (
size_t i = 0; i < (size_t) ref_elem_type::numCorners; i++)
589 m_in_source [pElem->vertex (i)] =
true;
598 template <
typename TDomain,
typename TAlgebra>
608 const MultiGrid * mg = dom->grid().get ();
619 template <
typename TDomain,
typename TAlgebra>
627 std::vector<size_t> vVertInd (1);
630 iterator vert_end = vertDD.
end<
Vertex> ();
631 for (iterator vert_iter = vertDD.
begin<
Vertex> (); vert_iter != vert_end; ++vert_iter)
633 Vertex * pVertex = *vert_iter;
634 if (m_in_source [pVertex])
638 UG_THROW (
"NedelecLoopCurrent: Vertex DoF distribution mismatch. Not the Lagrange-Order-1 element?");
648 template <
typename TDomain,
typename TAlgebra>
656 std::vector<size_t> vVertInd (1);
659 iterator vert_end = vertDD.
end<
Vertex> ();
660 for (iterator vert_iter = vertDD.
begin<
Vertex> (); vert_iter != vert_end; ++vert_iter)
662 Vertex * pVertex = *vert_iter;
663 if (m_in_source [pVertex])
667 UG_THROW (
"NedelecLoopCurrent: Vertex DoF distribution mismatch. Not the Lagrange-Order-1 element?");
676 template <
typename TDomain,
typename TAlgebra>
684 iterator vert_end = vertDD.
end<
Vertex> ();
685 std::vector<size_t> vVertInd (1);
690 n_values = 0; ave = 0;
691 for (iterator vert_iter = vertDD.
begin<
Vertex> (); vert_iter != vert_end; ++vert_iter)
693 Vertex * pVertex = *vert_iter;
694 if (! m_in_source [pVertex])
698 UG_THROW (
"NedelecLoopCurrent: Vertex DoF distribution mismatch. Not the Lagrange-Order-1 element?");
700 ave += u [vVertInd[0]];
713 for (iterator vert_iter = vertDD.
begin<
Vertex> (); vert_iter != vert_end; ++vert_iter)
715 Vertex * pVertex = *vert_iter;
716 if (! m_in_source [pVertex])
720 u [vVertInd[0]] -= ave;
730 template <
typename TDomain,
typename TAlgebra>
731 template <
typename TElem>
751 for (
size_t i = 0; i < negSsGrp.
size (); i++)
753 int si = negSsGrp [i];
754 iterator e_end = vertDD.template end<TElem> (si);
755 for (iterator elem_iter = vertDD.template begin<TElem> (si);
756 elem_iter != e_end; ++elem_iter)
758 TElem * pElem = *elem_iter;
759 bool bnd_flag [ref_elem_type::numCorners];
767 for (
size_t co = 0; co < (size_t) ref_elem_type::numCorners; co++)
768 aCorners [co] = aaPos [pElem->vertex (co)];
771 number loc_A [ref_elem_type::numCorners] [ref_elem_type::numCorners];
775 std::vector<size_t> vVertInd (1);
776 for (
size_t i = 0; i < (size_t) ref_elem_type::numCorners; i++)
778 for (
size_t j = 0; j < (size_t) ref_elem_type::numCorners; j++)
781 UG_THROW (
"NedelecLoopCurrent: Illegal vertex-centered DoF distribution");
782 flux += loc_A [i] [j] * pot [vVertInd [0]];
size_t allreduce(const size_t &t, pcl::ReduceOperation op) const
traits< TElem >::iterator begin()
size_t inner_algebra_indices(GridObject *elem, std::vector< size_t > &ind, bool bClear=true) const
size_t inner_dof_indices(GridObject *elem, size_t fct, std::vector< DoFIndex > &ind, bool bClear=true) const
traits< TElem >::iterator end()
SmartPtr< MultiGrid > multi_grid()
FunctionGroup fct_grp_by_name(const char *names) const
const LFEID & local_finite_element_id(size_t fct) const
ConstSmartPtr< ISubsetHandler > subset_handler() const
virtual Vertex * vertex(size_t index) const
Class for local assembling of the auxiliary Laplace operator.
Definition: nedelec_source.h:280
SubsetGroup m_posSsGrp
group of the positive direction subsets
Definition: nedelec_source.h:358
void ass_JA_elem(LocalMatrix &J, const LocalVector &u, GridObject *elem, const position_type vCornerCoords[])
transfer the local stiffness matrix to the global discretization
Definition: nedelec_source_impl.h:496
void register_loc_discr_func()
Definition: nedelec_source_impl.h:464
void register_all_loc_discr_funcs()
Definition: nedelec_source_impl.h:452
SubsetGroup m_cutSsGrp
group of the surfaces at the cut
Definition: nedelec_source.h:360
virtual void prepare_setting(const std::vector< LFEID > &vLfeID, bool bNonRegular)
switches between non-regular and regular grids
Definition: nedelec_source_impl.h:432
void prepare_element_loop(ReferenceObjectID roid, int si)
Definition: nedelec_source_impl.h:484
void ass_rhs_elem(LocalVector &d, GridObject *elem, const position_type vCornerCoords[])
Definition: nedelec_source_impl.h:519
AuxLaplaceLocAss(NedelecLoopCurrent &master)
constructor
Definition: nedelec_source_impl.h:411
Helper class for assembling the local stiffness matrix of Laplacian in various routines.
Definition: nedelec_source.h:251
static void stiffness(GridObject *elem, const position_type vCornerCoords[], number loc_A[numCorners][numCorners])
Computes the local discretization of the Laplace operator.
Definition: nedelec_source_impl.h:355
Constraint that sets the problem to 0-identity out of the source.
Definition: nedelec_source.h:374
void adjust_vector(const DoFDistribution &vertDD, pot_vector_type &u)
sets to 0 all the entries of a vector that do not belong to the closure of the source subdomain
Definition: nedelec_source_impl.h:650
void adjust_matrix(const DoFDistribution &vertDD, pot_matrix_type &A)
sets to identity all the matrix rows that do not belong to the closure of the source subdomain
Definition: nedelec_source_impl.h:621
OutOfSource(NedelecLoopCurrent &master)
constructor
Definition: nedelec_source_impl.h:552
void mark_source_vertices_elem_type(const TDomain *dom)
marks the vertices belonging to elements in the source (for one element type)
Definition: nedelec_source_impl.h:564
void mark_source_vertices(const TDomain *dom)
marks the vertices belonging to elements in the source (for all element types)
Definition: nedelec_source_impl.h:600
void set_zero_average(const DoFDistribution &vertDD, pot_vector_type &u)
sets the arithmetic average of the solution vector to zero
Definition: nedelec_source_impl.h:678
Postprocessor to eliminate the kernel parts in the solution.
Definition: nedelec_source.h:547
Class for computation of loop currents.
Definition: nedelec_source.h:123
void compute(SmartPtr< GridFunction< TDomain, TAlgebra > > sp_u)
Computation of the source (only if 'init'ialized): distributes the potential.
Definition: nedelec_source_impl.h:121
SmartPtr< OutOfSource > m_outOfSource
Extension of the matrices and vectors to the whole domain.
Definition: nedelec_source.h:638
SubsetGroup m_posSsGrp
Group of the subsets of the positive direction.
Definition: nedelec_source.h:628
SubsetGroup m_cutSsGrp
Group of the surfaces of the cut of the loop.
Definition: nedelec_source.h:630
void distribute_source_potential(const DoFDistribution &vertDD, pot_vector_type &src_pot, DoFDistribution &edgeDD, size_t func, number value, vector_type &src_field)
Computes the gradient of the potential.
Definition: nedelec_source_impl.h:281
std::string m_allSsNames
Names of all the subsets of the source.
Definition: nedelec_source.h:619
std::string m_cutSsNames
Names of the surfaces of the cut of the loop.
Definition: nedelec_source.h:623
TAlgebra::vector_type vector_type
Type of Vector (for the Nedelec-element-based grid functions)
Definition: nedelec_source.h:140
void compute_potential(pot_gf_type &pot_u)
Computes the potential of the source.
Definition: nedelec_source_impl.h:246
TDomain domain_type
Type of Domain.
Definition: nedelec_source.h:129
TDomain::position_type position_type
position type
Definition: nedelec_source.h:157
std::string m_posSsNames
Names of the subsets of the positive direction.
Definition: nedelec_source.h:621
SmartPtr< AuxLaplaceLocAss > m_auxLocLaplace
Local discretization of the auxiliary equations.
Definition: nedelec_source.h:636
void set(const char *fctNames, number I)
Setting the electric current value.
Definition: nedelec_source_impl.h:108
SmartPtr< DomainDiscretization< TDomain, TPotAlgebra > > m_auxLaplaceAss
Global discretization of the auxiliary equations.
Definition: nedelec_source.h:648
NedelecLoopCurrent(const char *ssNames, const char *posSsNames, const char *cutSsNames, SmartPtr< ApproximationSpace< TDomain > > vertApproxSpace, SmartPtr< ILinearOperatorInverse< pot_vector_type > > potSolver)
Constructor.
Definition: nedelec_source_impl.h:52
void get_flux_of_pot(const TDomain &domain, const pot_vector_type &pot, const DoFDistribution &vertDD, number &flux)
Computes the flux of of the gradient of the potential over the cut (for one type of elements)
Definition: nedelec_source_impl.h:733
void mark_source_edges(const DoFDistribution &edgeDD, aa_edge_flag_type &in_source)
Marks edges that belong to the loop source domain (for one type of elements)
Definition: nedelec_source_impl.h:199
Grid::EdgeAttachmentAccessor< a_edge_flag_type > aa_edge_flag_type
Definition: nedelec_source.h:163
SmartPtr< ApproximationSpace< TDomain > > m_spVertApproxSpace
Vertex-centered approximation space.
Definition: nedelec_source.h:633
SubsetGroup m_allSsGrp
Group of all the subsets of the source.
Definition: nedelec_source.h:626
SmartPtr< ILinearOperatorInverse< pot_vector_type > > m_potSolver
Solver for the auxliliary equations.
Definition: nedelec_source.h:652
SmartPtr< TDomain > domain()
SmartPtr< DoFDistribution > dof_distribution()
SmartPtr< ApproximationSpace< TDomain > > approx_space()
const GridLevel & grid_level() const
SmartPtr< DoFDistribution > dd()
void init(SmartPtr< ApproximationSpace< TDomain > > spApproxSpace, SmartPtr< DoFDistribution > spDoFDistr, bool bManage)
void attach_to_vertices(IAttachment &attachment)
void detach_from_vertices(IAttachment &attachment)
void associated_elements(traits< Vertex >::secure_container &elemsOut, TElem *e)
TDomain::position_type position_type
int get_subset_index(const char *name) const
size_t num_levels() const
geometry_traits< TGeomObj >::iterator begin()
geometry_traits< TGeomObj >::iterator end()
bool contains(const char *name) const
void remove(const char *name)
void add(const char *name)
ConstSmartPtr< ISubsetHandler > subset_handler() const
void set_subset_handler(ConstSmartPtr< ISubsetHandler > sh)
Grid::VertexAttachmentAccessor< position_attachment_type > position_accessor_type
SmartPtr< TSubsetHandler > subset_handler()
void SetAttachmentValues(TAttachmentAccessor &aaVal, TIter elemsBegin, TIter elemsEnd, const TVal &val)
vector< string > TokenizeString(const char *str, const char delimiter=',')
void RemoveWhitespaceFromString(std::string &string)
#define UG_ASSERT(expr, msg)
#define UG_CATCH_THROW(msg)
vector_t::value_type VecDot(const vector_t &v1, const vector_t &v2)
const number & DoFRef(const TMatrix &mat, const DoFIndex &iInd, const DoFIndex &jInd)
void SetDirichletRow(TMatrix &mat, const DoFIndex &ind)
SurfaceView::traits< TElem >::const_iterator const_iterator
Definition: nedelec_source.h:341
Helper class for computation of the flux of potential over the cut.
Definition: nedelec_source.h:576
Helper class for marking the edges in the source.
Definition: nedelec_source.h:212
Helper class for marking the vertices in the closure of the source subdomain.
Definition: nedelec_source.h:392
Structure for keeping electric current data.
Definition: nedelec_source.h:606
function ProblemDisc new(problemDesc, dom)