Plugins
Loading...
Searching...
No Matches
nedelec_source_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
41
42#include "nedelec_local_ass.h"
43
44namespace ug{
45namespace Electromagnetism{
46
50template <typename TDomain, typename TAlgebra>
52(
53 const char * ssNames,
54 const char * posSsNames,
55 const char * cutSsNames,
56 SmartPtr<ApproximationSpace<TDomain> > vertApproxSpace,
58)
59: m_allSsNames ((std::string (ssNames) + ',') + posSsNames), m_posSsNames (posSsNames), m_cutSsNames (cutSsNames),
60 m_spVertApproxSpace (vertApproxSpace),
61 m_auxLocLaplace (new AuxLaplaceLocAss (*this)),
62 m_outOfSource (new OutOfSource (*this)),
63 m_zeroAverage (new ZeroAverage (m_outOfSource)),
64 m_auxLaplaceAss (new DomainDiscretization<TDomain, TPotAlgebra> (vertApproxSpace)),
65 m_auxLaplaceOp (new AssembledLinearOperator<TPotAlgebra> (SmartPtr<IAssemble<TPotAlgebra> >(m_auxLaplaceAss))),
66 m_potSolver (potSolver)
67{
68// Check the parameters:
69 if (m_spVertApproxSpace.invalid ())
70 UG_THROW ("NedelecLoopCurrent: Illegal vert.-centered approx. space.");
71 if (m_spVertApproxSpace->num_fct () != 1)
72 UG_THROW ("NedelecLoopCurrent: Exactly one function should be defined in the vert.-centered approx. space.");
73 if (! m_spVertApproxSpace->is_def_everywhere (0))
74 UG_THROW ("NedelecLoopCurrent: The function in the vert.-centered approx. space must be defined everywhere.");
75 if (m_potSolver.invalid ())
76 UG_THROW ("NedelecLoopCurrent: Illegal solver for the auxiliary problems.");
77
78// Fill the subset groups:
79 std::vector<std::string> vssNames;
80 ConstSmartPtr<subset_handler_type> spIsh = vertApproxSpace->subset_handler ();
81
82 TokenizeString (m_allSsNames, vssNames);
83 for (size_t i = 0; i < vssNames.size(); i++)
84 RemoveWhitespaceFromString (vssNames [i]);
85 m_allSsGrp.set_subset_handler (spIsh); m_allSsGrp.add (vssNames);
86
87 TokenizeString (m_posSsNames, vssNames);
88 for (size_t i = 0; i < vssNames.size(); i++)
89 RemoveWhitespaceFromString (vssNames [i]);
90 m_posSsGrp.set_subset_handler (spIsh); m_posSsGrp.add (vssNames);
91
92 TokenizeString (m_cutSsNames, vssNames);
93 for (size_t i = 0; i < vssNames.size(); i++)
94 RemoveWhitespaceFromString (vssNames [i]);
95 m_cutSsGrp.set_subset_handler (spIsh); m_cutSsGrp.add (vssNames);
96
97// Compose the global discretization of the auxiliary equations:
101}
102
106template <typename TDomain, typename TAlgebra>
108(
109 const char * fctNames,
110 number I
111)
112{
113 m_vSrcData.push_back (TSrcData (fctNames, I));
114}
115
119template <typename TDomain, typename TAlgebra>
121(
123)
124{
125 typedef typename domain_traits<WDim>::DimElemList ElemList;
126
127// Do we have data to compute?
128 if (m_vSrcData.size () == 0)
129 UG_THROW ("NedelecLoopCurrent: No electric currents specified.");
130
131// Check the grid function:
132 if (sp_u.invalid ())
133 UG_THROW ("NedelecLoopCurrent: Illegal grid function specification.");
134
135// Get the DoF distributions:
136 GridFunction<TDomain, TAlgebra> & u = * sp_u.get ();
138 const GridLevel g_lev (u.grid_level ());
139 SmartPtr<DoFDistribution> vertDD = m_spVertApproxSpace->dof_distribution (g_lev);
140
141// Compute the potential of the source:
142 pot_gf_type pot_u (m_spVertApproxSpace, g_lev);
143# ifdef UG_PARALLEL
144 pot_u.set_storage_type (PST_CONSISTENT);
145# endif
146 compute_potential (pot_u);
147
148// Compute the normalization factor of the potential (to scale the current to 1)
149 number pot_scaling;
150 boost::mpl::for_each<ElemList>
151 (GetFluxOfPotential (this, * m_spVertApproxSpace->domain().get (), pot_u,
152 * vertDD.get (), pot_scaling));
153# ifdef UG_PARALLEL
154 {
155 pcl::ProcessCommunicator proc_comm;
156 pot_scaling = proc_comm.allreduce (pot_scaling, PCL_RO_SUM);
157 }
158# endif
159 pot_scaling = - pot_scaling;
160
161// Loop over the source data
162 for (size_t i_data = 0; i_data < m_vSrcData.size (); i_data++)
163 {
164 // Get the component indices:
165 FunctionGroup fctGrp;
166 try
167 {
168 fctGrp = u.fct_grp_by_name (m_vSrcData[i_data].fctNames.c_str ());
169 }
170 UG_CATCH_THROW ("NedelecLoopCurrent: Functions '" << m_vSrcData[i_data].fctNames <<
171 "' not all contained in the edge approximation space.");
172
173 // Check the functions
174 for (size_t i_fct = 0; i_fct < fctGrp.size (); i_fct++)
175 if (u.local_finite_element_id(fctGrp[i_fct]).type () != LFEID::NEDELEC)
176 UG_THROW ("NedelecLoopCurrent: Not a Nedelec-element-based grid function specified for the source.");
177
178 // Compute the gradients of the potential
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);
183 }
184}
185
196template <typename TDomain, typename TAlgebra>
197template <typename TElem>
199(
200 const DoFDistribution & edgeDD,
201 aa_edge_flag_type & in_source
202)
203{
204 typedef typename reference_element_traits<TElem>::reference_element_type ref_elem_type;
205 typedef typename DoFDistribution::traits<TElem>::const_iterator iterator;
206
207 const ISubsetHandler * pIsh = edgeDD.subset_handler().get ();
208 Grid::edge_traits::secure_container edge_list;
209
210// Loop over the source subsets:
211 for (size_t i = 0; i < m_allSsGrp.size (); i++)
212 {
213 int si = m_allSsGrp [i];
214 bool in_pos = m_posSsGrp.contains (si);
215 // Loop over all the elements of the given type in the subset
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)
219 {
220 TElem * pElem = *elem_iter;
221 pIsh->grid()->associated_elements (edge_list, pElem);
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++)
225 {
226 Edge * pEdge = edge_list[e];
227 char flag = 1;
228 if (in_pos)
229 {
230 if (m_cutSsGrp.contains (pIsh->get_subset_index (pEdge->vertex (0))))
231 flag |= 2;
232 if (m_cutSsGrp.contains (pIsh->get_subset_index (pEdge->vertex (1))))
233 flag |= 4;
234 }
235 in_source [pEdge] = flag;
236 }
237 }
238 }
239}
240
244template <typename TDomain, typename TAlgebra>
246(
247 pot_gf_type & pot_u
248)
249{
250 pot_gf_type pot_rhs (pot_u.approx_space (), pot_u.dof_distribution ());
251
252// Prepare the attachment for the flags:
253 MultiGrid * mg = pot_u.dd()->multi_grid().get ();
254 a_vert_flag_type a_in_source;
255 mg->attach_to_vertices (a_in_source);
256 m_outOfSource->init (pot_u.domain().get (), a_in_source);
257
258// Assemble the matrix of the auxiliary problem:
259 pot_u.set (0.0);
260 m_auxLaplaceOp->set_level (pot_u.grid_level ());
261 m_auxLaplaceOp->init_op_and_rhs (pot_rhs);
262
263// Initizlize the solver:
264 m_potSolver->init (m_auxLaplaceOp);
265
266// Assemble and solve the Laplace equation:
267 m_potSolver->apply (pot_u, pot_rhs);
268
269// Release the attachment:
270 mg->detach_from_vertices (a_in_source);
271}
272
279template <typename TDomain, typename TAlgebra>
281(
282 const DoFDistribution & vertDD,
283 pot_vector_type & src_pot,
284 DoFDistribution & edgeDD,
285 size_t func,
286 number value,
287 vector_type & src_field
288)
289{
291
292// The full-dim. grid element types for this dimension:
293 typedef typename domain_traits<WDim>::DimElemList ElemList;
294
295// Multigrid and iterators:
296 SmartPtr<MultiGrid> sp_mg = edgeDD.multi_grid ();
297 t_edge_iter edgeIterBeg = edgeDD.begin<Edge> ();
298 t_edge_iter edgeIterEnd = edgeDD.end<Edge> ();
299
300// Mark the edges in the source:
301 a_edge_flag_type a_in_source;
302 sp_mg->attach_to_edges (a_in_source);
303 aa_edge_flag_type aa_in_source (*sp_mg, a_in_source);
304 SetAttachmentValues (aa_in_source, edgeIterBeg, edgeIterEnd, 0);
305 boost::mpl::for_each<ElemList> (MarkSourceEdges (this, edgeDD, aa_in_source));
306# ifdef UG_PARALLEL
307 AttachmentAllReduce<Edge> (*sp_mg, a_in_source, PCL_RO_BOR);
308# endif
309
310// Compute the gradient:
311 std::vector<size_t> vVertInd (1);
312 std::vector<DoFIndex> vEdgeInd (1);
313 for (t_edge_iter edgeIter = edgeIterBeg; edgeIter != edgeIterEnd; ++edgeIter)
314 {
315 Edge * pEdge = *edgeIter;
316 char edge_flag;
317 number nd_pot [2];
318
319 // Get the edge DoF and check whether the edge is in the source:
320 if (edgeDD.inner_dof_indices (pEdge, func, vEdgeInd) != 1)
321 UG_THROW ("NedelecLoopCurrent: Edge DoF distribution mismatch. Not the Nedelec-Type-1 element?");
322 if ((edge_flag = aa_in_source [pEdge]) == 0)
323 { // we are not in the source
324 DoFRef (src_field, vEdgeInd [0]) = 0;
325 continue;
326 }
327
328 // Get the values at the ends:
329 for (size_t i = 0; i < 2; i++)
330 {
331 Vertex * pVertex = pEdge->vertex (i);
332 if (vertDD.inner_algebra_indices (pVertex, vVertInd) != 1)
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)
336 nd_pot [i] += 1.0; // the jump of the potential at the cut
337 }
338
339 // Compute the gradient:
340 DoFRef (src_field, vEdgeInd [0]) = value * (nd_pot [1] - nd_pot [0]);
341 }
342
343// Release the attachment:
344 sp_mg->detach_from_edges (a_in_source);
345}
346
347/*----- Assembling the auxiliary Poisson problems 1: class AuxLaplaceLocAss -----*/
348
352template <typename TDomain, typename TAlgebra>
353template <typename TElem>
355(
356 GridObject * elem,
357 const position_type vCornerCoords [],
358 number loc_A [numCorners] [numCorners]
359)
360{
362
363// request the finite element geometry
364 TFEGeom & geo = GeomProvider<TFEGeom>::get ();
365 // we assume that this is the simplest discretization:
366 UG_ASSERT (geo.num_ip () == 1, "Only the simplest quadrature is supported here.");
367
368// initialize the fe geometry
369 geo.update (elem, vCornerCoords);
370
371// compute the upper triangle of the local stiffness matrix
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))
376 * geo.weight (0);
377// use the symmetry
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];
381}
382
386template <typename TDomain, typename TAlgebra>
387template <typename TElem>
389(
390 GridObject * elem,
391 const SubsetGroup & bndGrp,
392 bool bnd_flag [numCorners]
393)
394{
395 TElem * pElem = (TElem *) elem;
396 const ISubsetHandler * pIsh = bndGrp.subset_handler().get ();
397 bool bnd = false;
398
399 for (size_t i = 0; i < (size_t) numCorners; i++)
400 if ((bnd_flag [i] = bndGrp.contains (pIsh->get_subset_index (pElem->vertex (i)))))
401 bnd = true;
402 return bnd;
403}
404
409template <typename TDomain, typename TAlgebra>
411(
412 NedelecLoopCurrent & master
413)
414: IElemDisc<TDomain> (master.m_spVertApproxSpace->name(0).c_str(), master.m_allSsNames.c_str()),
415 m_master (master),
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)
419{
420// check the data
421 if (m_posSsGrp.empty ())
422 UG_THROW ("NedelecLoopCurrent: No positive direction subsets specified");
423 if (m_cutSsGrp.empty ())
424 UG_THROW ("NedelecLoopCurrent: No cut specified");
425// register assemble functions
427}
428
429// check the basis and the grid
430template<typename TDomain, typename TAlgebra>
432(
433 const std::vector<LFEID> & vLfeID,
434 bool bNonRegular
435)
436{
437 if (bNonRegular)
438 UG_THROW ("NedelecLoopCurrent:"
439 " The discretization of the auxiliary systems does not support hanging nodes.\n");
440
441 if (vLfeID.size () != 1)
442 UG_THROW ("NedelecLoopCurrent:"
443 " Only scalar grid functions are supported for the potential");
444
445 if (vLfeID[0].type() != LFEID::LAGRANGE || vLfeID[0].order() != 1)
446 UG_THROW ("NedelecLoopCurrent:"
447 " Only Largange-1 functions are supported for the potential");
448}
449
450// register the local assembler functions for all the elements and dimensions
451template<typename TDomain, typename TAlgebra>
453{
454// get all grid element types in this dimension and below
455 typedef typename domain_traits<WDim>::DimElemList ElemList;
456
457// switch assemble functions
458 boost::mpl::for_each<ElemList> (RegisterLocalDiscr (this));
459}
460
461// register the local assembler functions for a given element
462template<typename TDomain, typename TAlgebra>
463template<typename TElem> // the element to register for
465{
467
468 this->clear_add_fct(id);
469
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>);
478}
479
480// prepares the loop over the elements: check whether we are in the positive subset
481template<typename TDomain, typename TAlgebra>
482template<typename TElem>
484(
485 ReferenceObjectID roid, // [in] only elements with this roid are looped over
486 int si // [in] and only in this subdomain
487)
488{
489 m_in_pos_subset = m_posSsGrp.contains (si);
490}
491
493template<typename TDomain, typename TAlgebra>
494template<typename TElem>
496(
497 LocalMatrix & J,
498 const LocalVector & u,
499 GridObject * elem,
500 const position_type vCornerCoords []
501)
502{
503 typedef typename reference_element_traits<TElem>::reference_element_type ref_elem_type;
504
505// assemble the local matrix
506 number loc_A [ref_elem_type::numCorners] [ref_elem_type::numCorners];
508
509// add the local matrix to the global one
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];
513}
514
515// computes the local right-hand side
516template<typename TDomain, typename TAlgebra>
517template <typename TElem>
519(
520 LocalVector & d,
521 GridObject * elem,
522 const position_type vCornerCoords []
523)
524{
525 typedef typename reference_element_traits<TElem>::reference_element_type ref_elem_type;
526
527 if (! m_in_pos_subset) return; // rhs is nonzero only in one subset
528
529// assemble the local matrix
530 bool at_cut [ref_elem_type::numCorners];
532 (elem, m_master.m_cutSsGrp, at_cut))
533 return; // no corners on the cut
534
535// assemble the local matrix and compose the right-hand side of it
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++)
541 if (at_cut [j])
542 d (_C_, i) -= loc_A [i] [j]; // to simulate the jump of the potential
543}
544
545/*----- Assembling the auxiliary Poisson problems 2: class OutOfSource -----*/
546
550template <typename TDomain, typename TAlgebra>
557
561template <typename TDomain, typename TAlgebra>
562template <typename TElem>
564(
565 const TDomain * dom
566)
567{
568 typedef typename reference_element_traits<TElem>::reference_element_type ref_elem_type;
569 typedef typename geometry_traits<TElem>::const_iterator iterator;
570
571// Get the multigrid and the subset handler:
572 const MultiGrid * mg = dom->grid().get ();
573 const MGSubsetHandler * ssh = dom->subset_handler().get ();
574 size_t n_levels = mg->num_levels ();
575
576// Loop over the source subsets:
577 for (size_t i = 0; i < m_master.m_allSsGrp.size (); i++)
578 {
579 int si = m_master.m_allSsGrp [i];
580 for (size_t lev = 0; lev < n_levels; lev++)
581 {
582 // Loop over all the elements of the given type in the subset
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)
586 {
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;
590 }
591 }
592 }
593}
594
598template <typename TDomain, typename TAlgebra>
600(
601 const TDomain * dom
602)
603{
604// The full-dim. grid element types for this dimension:
605 typedef typename domain_traits<WDim>::DimElemList ElemList;
606
607// Reset the flags:
608 const MultiGrid * mg = dom->grid().get ();
609 SetAttachmentValues (m_in_source, mg->begin<Vertex> (), mg->end<Vertex> (), false);
610
611// Mark the vertices:
612 boost::mpl::for_each<ElemList> (MarkSourceVertices (this, dom));
613}
614
619template <typename TDomain, typename TAlgebra>
621(
622 const DoFDistribution & vertDD,
623 pot_matrix_type & A
624)
625{
627 std::vector<size_t> vVertInd (1);
628
629// Loop over all the vertices out of the source
630 iterator vert_end = vertDD.end<Vertex> ();
631 for (iterator vert_iter = vertDD.begin<Vertex> (); vert_iter != vert_end; ++vert_iter)
632 {
633 Vertex * pVertex = *vert_iter;
634 if (m_in_source [pVertex])
635 continue; // the vertex is in the source
636
637 if (vertDD.inner_algebra_indices (pVertex, vVertInd) != 1)
638 UG_THROW ("NedelecLoopCurrent: Vertex DoF distribution mismatch. Not the Lagrange-Order-1 element?");
639
640 SetDirichletRow (A, vVertInd[0]);
641 }
642}
643
648template <typename TDomain, typename TAlgebra>
650(
651 const DoFDistribution & vertDD,
652 pot_vector_type & u
653)
654{
656 std::vector<size_t> vVertInd (1);
657
658// Loop over all the vertices out of the source
659 iterator vert_end = vertDD.end<Vertex> ();
660 for (iterator vert_iter = vertDD.begin<Vertex> (); vert_iter != vert_end; ++vert_iter)
661 {
662 Vertex * pVertex = *vert_iter;
663 if (m_in_source [pVertex])
664 continue; // the vertex is in the source
665
666 if (vertDD.inner_algebra_indices (pVertex, vVertInd) != 1)
667 UG_THROW ("NedelecLoopCurrent: Vertex DoF distribution mismatch. Not the Lagrange-Order-1 element?");
668
669 u [vVertInd[0]] = 0;
670 }
671}
672
676template <typename TDomain, typename TAlgebra>
678(
679 const DoFDistribution & vertDD,
680 pot_vector_type & u
681)
682{
684 iterator vert_end = vertDD.end<Vertex> ();
685 std::vector<size_t> vVertInd (1);
686 size_t n_values;
687 number ave;
688
689// Loop over all the vertices in the source and compute the average
690 n_values = 0; ave = 0;
691 for (iterator vert_iter = vertDD.begin<Vertex> (); vert_iter != vert_end; ++vert_iter)
692 {
693 Vertex * pVertex = *vert_iter;
694 if (! m_in_source [pVertex])
695 continue; // the vertex is out of the source
696
697 if (vertDD.inner_algebra_indices (pVertex, vVertInd) != 1)
698 UG_THROW ("NedelecLoopCurrent: Vertex DoF distribution mismatch. Not the Lagrange-Order-1 element?");
699
700 ave += u [vVertInd[0]];
701 n_values++;
702 }
703# ifdef UG_PARALLEL
704 {
705 pcl::ProcessCommunicator proc_comm;
706 ave = proc_comm.allreduce (ave, PCL_RO_SUM);
707 n_values = proc_comm.allreduce (n_values, PCL_RO_SUM);
708 }
709# endif
710 ave /= n_values;
711
712// Subtract the average from the components
713 for (iterator vert_iter = vertDD.begin<Vertex> (); vert_iter != vert_end; ++vert_iter)
714 {
715 Vertex * pVertex = *vert_iter;
716 if (! m_in_source [pVertex])
717 continue; // the vertex is out of the source
718
719 vertDD.inner_algebra_indices (pVertex, vVertInd);
720 u [vVertInd[0]] -= ave;
721 }
722}
723
724/*----- Computation of the flux of the potential over the cut -----*/
725
730template <typename TDomain, typename TAlgebra>
731template <typename TElem>
733(
734 const domain_type & domain,
735 const pot_vector_type & pot,
736 const DoFDistribution & vertDD,
737 number & flux
738)
739{
740 typedef typename reference_element_traits<TElem>::reference_element_type ref_elem_type;
741 typedef typename DoFDistribution::traits<TElem>::const_iterator iterator;
742
743// Get the positions of the grid points:
744 const typename TDomain::position_accessor_type & aaPos = domain.position_accessor ();
745
746// Get the 'negative' subset indices
747 SubsetGroup negSsGrp (m_allSsGrp);
748 negSsGrp.remove (m_posSsGrp);
749
750// Loop the elements in the subset group:
751 for (size_t i = 0; i < negSsGrp.size (); i++)
752 {
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)
757 {
758 TElem * pElem = *elem_iter;
759 bool bnd_flag [ref_elem_type::numCorners];
760
761 // Check whether we are at the cut
762 if (! LocLaplaceA<TElem>::bnd_corners (pElem, m_cutSsGrp, bnd_flag))
763 continue; // this is not the case
764
765 // Get the corner positions:
766 position_type aCorners [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)];
769
770 // Assemble the local Laplacian:
771 number loc_A [ref_elem_type::numCorners] [ref_elem_type::numCorners];
772 LocLaplaceA<TElem>::stiffness (pElem, aCorners, loc_A);
773
774 // Compute the local contributions to the flux:
775 std::vector<size_t> vVertInd (1);
776 for (size_t i = 0; i < (size_t) ref_elem_type::numCorners; i++)
777 if (bnd_flag [i]) // consider only the corners at the cut
778 for (size_t j = 0; j < (size_t) ref_elem_type::numCorners; j++)
779 {
780 if (vertDD.inner_algebra_indices (pElem->vertex (j), vVertInd) != 1)
781 UG_THROW ("NedelecLoopCurrent: Illegal vertex-centered DoF distribution");
782 flux += loc_A [i] [j] * pot [vVertInd [0]];
783 }
784 }
785 }
786}
787
788} // end namespace Electromagnetism
789} // end namespace ug
790
791/* End of File */
T * get()
size_t allreduce(const size_t &t, pcl::ReduceOperation op) const
traits< TElem >::iterator begin()
traits< TElem >::iterator end()
SmartPtr< MultiGrid > multi_grid()
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
const LFEID & local_finite_element_id(size_t fct) const
FunctionGroup fct_grp_by_name(const char *names) 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
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
size_t size() const
static TGeom & get()
SmartPtr< ApproximationSpace< TDomain > > approx_space()
SmartPtr< TDomain > domain()
SmartPtr< DoFDistribution > dof_distribution()
const GridLevel & grid_level() const
void init(SmartPtr< ApproximationSpace< TDomain > > spApproxSpace, SmartPtr< DoFDistribution > spDoFDistr, bool bManage)
SmartPtr< DoFDistribution > dd()
void attach_to_vertices(IAttachment &attachment)
void detach_from_vertices(IAttachment &attachment)
void associated_elements(traits< Vertex >::secure_container &elemsOut, TElem *e)
int get_subset_index(const char *name) const
Grid * grid() const
SpaceType type() 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)
bool empty() const
void add(const char *name)
ConstSmartPtr< ISubsetHandler > subset_handler() const
size_t size() const
void set_subset_handler(ConstSmartPtr< ISubsetHandler > sh)
PST_CONSISTENT
SmartPtr< TSubsetHandler > subset_handler()
void SetAttachmentValues(TAttachmentAccessor &aaVal, TIter elemsBegin, TIter elemsEnd, const TVal &val)
#define PCL_RO_SUM
#define PCL_RO_BOR
Variant::Type type()
vector< string > TokenizeString(const char *str, const char delimiter=',')
void RemoveWhitespaceFromString(std::string &string)
#define UG_ASSERT(expr, msg)
#define UG_CATCH_THROW(msg)
#define UG_THROW(msg)
double number
vector_t::value_type VecDot(const vector_t &v1, const vector_t &v2)
ReferenceObjectID
const number & DoFRef(const TMatrix &mat, const DoFIndex &iInd, const DoFIndex &jInd)
void SetDirichletRow(TMatrix &mat, const DoFIndex &ind)
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)