Loading [MathJax]/extensions/tex2jax.js
Plugins
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
nedelec_project_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
42
43#include "nedelec_local_ass.h"
44
45namespace ug{
46namespace Electromagnetism{
47
51template <typename TDomain, typename TAlgebra>
53(
54 SmartPtr<EMaterial<TDomain> > emMatherial,
55 SmartPtr<ApproximationSpace<TDomain> > vertApproxSpace,
57)
58: m_spEmMaterial (emMatherial),
59 m_spVertApproxSpace (vertApproxSpace),
60 m_bDampDVFs (true),
61 m_auxLocLaplace (new AuxLaplaceLocAss (*this)),
62 m_auxLaplaceRHS (new AuxLaplaceRHS (*this)),
63 m_auxLaplaceAss (new DomainDiscretization<TDomain, TPotAlgebra> (vertApproxSpace)),
64 m_auxLaplaceOp (new AssembledLinearOperator<TPotAlgebra> (SmartPtr<IAssemble<TPotAlgebra> >(m_auxLaplaceAss))),
65 m_potSolver (potSolver)
66{
67// Check the parameters:
68 if (m_spEmMaterial.invalid ())
69 UG_THROW ("NedelecProject: Object of the matherial properties not specified.");
70 if (m_spVertApproxSpace.invalid ())
71 UG_THROW ("NedelecProject: Illegal vert.-centered approx. space.");
72 if (m_spVertApproxSpace->num_fct () != 1)
73 UG_THROW ("NedelecProject: Exactly one function should be defined in the vert.-centered approx. space.");
74 if (! m_spVertApproxSpace->is_def_everywhere (0))
75 UG_THROW ("NedelecProject: The function in the vert.-centered approx. space must be defined everywhere.");
76 if (m_potSolver.invalid ())
77 UG_THROW ("NedelecProject: Illegal solver for the auxiliary problems.");
78
79// Compose the global discretization of the auxiliary equations:
83}
84
88template <typename TDomain, typename TAlgebra>
90(
91 vector_type & vec
92)
93{
95
96 if ((u_ptr = dynamic_cast<GridFunction<TDomain, TAlgebra> *> (&vec)) == 0)
97 UG_THROW ("NedelecProject::apply: Specify a grid function, not a vector!");
98
99 FunctionGroup fctGrp (u_ptr->dof_distribution_info ());
100 fctGrp.add_all ();
101 apply (*u_ptr, fctGrp);
102}
103
107template <typename TDomain, typename TAlgebra>
109(
111 const char * fct_names
112)
113{
114// Get the function indices:
115 FunctionGroup fctGrp;
116 try
117 {
118 fctGrp = u.fct_grp_by_name (fct_names);
119 }
120 UG_CATCH_THROW ("NedelecProject: Functions '" << fct_names << "' not all contained in the edge approximation space.");
121
122// Project:
123 apply (u, fctGrp);
124}
125
129template <typename TDomain, typename TAlgebra>
131(
133 const FunctionGroup & fctGrp
134)
135{
136// Check the data:
137 if (! m_spEmMaterial->finalized ())
138 UG_THROW ("NedelecProject: The material data structure has not been finalized.");
139
140// Get the domain:
141 SmartPtr<domain_type> domain = u.domain ();
142 if (domain.get () != m_spVertApproxSpace->domain().get ())
143 UG_THROW ("NedelecProject: The approximation spaces are based on different domains.");
144
145// Check the function indices:
146 for (size_t i_fct = 0; i_fct < fctGrp.size (); i_fct++)
147 if (u.local_finite_element_id(fctGrp[i_fct]).type () != LFEID::NEDELEC)
148 UG_THROW ("NedelecProject: Not a Nedelec-element-based grid function specified for the projection.");
149
150// Get the DoF distributions:
152 SmartPtr<DoFDistribution> vertDD = m_spVertApproxSpace->dof_distribution (u.grid_level ());
153
154// Create temporary grid functions for the auxiliary problem
155 pot_gf_type aux_rhs (m_spVertApproxSpace, vertDD);
156 pot_gf_type aux_cor (m_spVertApproxSpace, vertDD);
157
158// Assemble the matrix of the auxiliary problem:
159 aux_cor.set (0.0);
160 m_auxLaplaceOp->set_level (u.grid_level ());
161 m_auxLaplaceOp->init (aux_cor);
162
163// Initizlize the solver:
164 m_potSolver->init (m_auxLaplaceOp);
165
166// Compute the Dirichlet vector fields:
167 if (m_bDampDVFs)
168 {
169 alloc_DVFs (* domain.get (), aux_rhs);
170 compute_DVFs (aux_rhs);
171 compute_DVF_potential_coeffs (* domain.get (), * vertDD.get ());
172 }
173
174// Project every function:
175 for (size_t i_fct = 0; i_fct < fctGrp.size (); i_fct++)
176 project_func (domain, edgeDD, u, fctGrp[i_fct], vertDD, aux_rhs, aux_cor);
177
178// Release the Dirichlet vector fields:
179 if (m_bDampDVFs)
180 {
181 for (size_t i = 0; i < m_DVF_phi.size (); i++)
182 delete m_DVF_phi [i];
183 m_DVF_phi.resize (0);
184 }
185}
186
190template <typename TDomain, typename TAlgebra>
192(
194 const char * u_fct_name,
196)
197{
198// Check the data:
199 if (sp_u.invalid ())
200 UG_THROW ("NedelecProject: Illegal input grid function specification.");
201 GridFunction<TDomain, TAlgebra> & u = * sp_u.get ();
202
203 if (sp_div.invalid ())
204 UG_THROW ("NedelecProject: Illegal output grid function specification.");
205 pot_vector_type & div = * sp_div.get ();
206
207 if (! m_spEmMaterial->finalized ())
208 UG_THROW ("The material data structure has not been finalized.");
209
210// Get the domain:
211 SmartPtr<domain_type> domain = u.domain ();
212 if (domain.get () != m_spVertApproxSpace->domain().get ())
213 UG_THROW ("NedelecProject: The approximation spaces are based on different domains.");
214
215// Get the function index of the vector field:
216 size_t u_fct;
217 try
218 {
219 u_fct = u.fct_id_by_name (u_fct_name);
220 }
221 UG_CATCH_THROW (" Function '" << u_fct_name << "' not contained in the edge approximation space.");
222
224 UG_THROW ("NedelecProject: Not a Nedelec-element-based input grid function.");
225
226// Get the DoF distributions:
228 SmartPtr<DoFDistribution> vertDD = sp_div->dof_distribution ();
229 if (vertDD.get () != m_spVertApproxSpace->dof_distribution(u.grid_level ()).get ())
230 UG_THROW ("NedelecProject: DoFDistribution mismatch, illegal output grid function.");
231
232// Compute the weak divergence:
234 assemble_div (* domain.get(), * edgeDD.get(), u, u_fct, * vertDD.get(), div, charge);
235# ifdef UG_PARALLEL
237# endif
238}
239
245template <typename TDomain, typename TAlgebra>
247(
248 const SmartPtr<TDomain> & domain,
249 const SmartPtr<DoFDistribution> & edgeDD,
250 vector_type & u,
251 size_t fct,
252 const SmartPtr<DoFDistribution> & vertDD,
253 pot_gf_type & aux_rhs,
254 pot_gf_type & aux_cor
255)
256{
258
259//--- Compute the correction due to the divergence:
260
261# ifdef UG_PARALLEL
262 aux_cor.set_storage_type (PST_CONSISTENT);
263# endif
264
265 aux_cor.set (0.0);
266
267// 1. Compute the weak div:
268 assemble_div (* domain.get(), * edgeDD.get(), u, fct, * vertDD.get(), aux_rhs, charge);
269// 2. Correct the divergence in the right-hand side:
270 m_auxLaplaceRHS->set_base_conductor (-1);
271 m_auxLaplaceAss->adjust_solution (aux_rhs, vertDD);
272// 3. Solve the auxiliary system:
273 m_auxLaplaceAss->adjust_solution (aux_cor, vertDD);
274 m_potSolver->apply (aux_cor, aux_rhs);
275// 4. Damp the Dirichlet vector fields:
276 if (m_bDampDVFs)
277 damp_DVFs (aux_cor, charge);
278// 5. Merge the correction into the solution:
279 distribute_cor (* domain.get(), * edgeDD.get(), u, fct, * vertDD.get(), aux_cor);
280}
281
286template <typename TDomain, typename TAlgebra>
287template <typename TElem>
289(
290 const TDomain & domain,
291 const DoFDistribution & edgeDD,
292 const vector_type & u,
293 size_t fct,
294 const DoFDistribution & vertDD,
295 pot_vector_type & div
296)
297{
298 typedef typename reference_element_traits<TElem>::reference_element_type ref_elem_type;
299 typedef typename DoFDistribution::traits<TElem>::const_iterator iterator;
300
301// Get the conductor distribution and the positions of the grid points:
302 const std::vector<int> & cond_index = m_spEmMaterial->base_conductor_index ();
303 const typename TDomain::position_accessor_type & aaPos = domain.position_accessor ();
304
305// Arrays for the indices in the vectors:
306 std::vector<DoFIndex> vEdgeInd (ref_elem_type::numEdges);
307 std::vector<size_t> vVertInd (ref_elem_type::numCorners);
308
309// Loop over all subsets representing insulators:
310 for (int si = 0; si < vertDD.num_subsets (); si++)
311 if (cond_index [si] == -1)
312 {
313 // Loop over all the elements of the given type in the subset
314 iterator e_end = vertDD.template end<TElem> (si);
315 for (iterator elem_iter = vertDD.template begin<TElem> (si);
316 elem_iter != e_end; ++elem_iter)
317 {
318 TElem * pElem = *elem_iter;
322
323 // Compute the local weak divergence matrix:
324 position_type aCorners [ref_elem_type::numCorners];
325 for (size_t co = 0; co < (size_t) ref_elem_type::numCorners; co++)
326 aCorners [co] = aaPos [pElem->vertex (co)];
328 (number (*) [ref_elem_type::numEdges]) & (B (0,0)));
329
330 // Compute the local contribution to the weak divergence:
331 if (edgeDD.dof_indices (pElem, fct, vEdgeInd) != (size_t) ref_elem_type::numEdges)
332 UG_THROW ("NedelecProject: Edge DoF distribution mismatch. Not the Nedelec-Type-1 element?");
333 for (size_t i = 0; i < (size_t) ref_elem_type::numEdges; i++)
334 loc_u [i] = DoFRef (u, vEdgeInd [i]);
335 MatVecMult (loc_div, B, loc_u);
336
337 // Add the local contribution to the global vector:
338 if (vertDD.algebra_indices (pElem, vVertInd) != (size_t) ref_elem_type::numCorners)
339 UG_THROW ("NedelecProject: Vertex DoF distribution mismatch. Not the Lagrange-Order-1 element?");
340 for (size_t i = 0; i < (size_t) ref_elem_type::numCorners; i++)
341 div [vVertInd [i]] += loc_div [i];
342 }
343 }
344}
345
355template <typename TDomain, typename TAlgebra>
356template <typename TElem>
358(
359 const DoFDistribution & vertDD,
360 pot_vector_type & div,
362)
363{
364 typedef typename reference_element_traits<TElem>::reference_element_type ref_elem_type;
365 typedef typename DoFDistribution::traits<TElem>::const_iterator iterator;
366
367 const std::vector<int> & base_cond = m_spEmMaterial->base_conductors ();
368 if (base_cond.size () == 0) return; // no conductors
369
370 std::vector<size_t> vVertInd (ref_elem_type::numCorners);
371 const std::vector<int> & base_cond_index = m_spEmMaterial->base_conductor_index ();
372 int ci;
373
374// Loop over all subsets representing conductors:
375 for (int si = 0; si < vertDD.num_subsets (); si++)
376 if ((ci = base_cond_index [si]) >= 0)
377 {
378 number & charge_entry = charge [ci];
379
380 // Loop over all the elements of the given type in the subset
381 iterator e_end = vertDD.template end<TElem> (si);
382 for (iterator elem_iter = vertDD.template begin<TElem> (si);
383 elem_iter != e_end; ++elem_iter)
384 {
385 TElem * pElem = *elem_iter;
386 if (vertDD.algebra_indices (pElem, vVertInd) != (size_t) ref_elem_type::numCorners)
387 UG_THROW ("NedelecProject: Vertex DoF distribution mismatch. Not the Lagrange-Order-1 element?");
388 for (size_t i = 0; i < (size_t) ref_elem_type::numCorners; i++)
389 {
390 number & div_entry = div [vVertInd [i]];
391 charge_entry += div_entry;
392 div_entry = 0;
393 }
394 }
395 }
396}
397
402template <typename TDomain, typename TAlgebra>
404(
405 const TDomain & domain,
406 const DoFDistribution & edgeDD,
407 const vector_type & u,
408 size_t fct,
409 const DoFDistribution & vertDD,
410 pot_vector_type & div,
412)
413{
414// The full-dim. grid element types for this dimension:
415 typedef typename domain_traits<WDim>::DimElemList ElemList;
416
417 const std::vector<int> & base_cond = m_spEmMaterial->base_conductors ();
418 charge.resize (base_cond.size ());
419 if (charge.size () != 0)
420 charge = 0.0;
421
422# ifdef UG_PARALLEL
424# endif
425
426 div.set (0.0);
427// Compute the divergence for all the types of the elements:
428 boost::mpl::for_each<ElemList> (WeakDiv (this, domain, edgeDD, u, fct, vertDD, div));
429// Clear the entries at all the points in the closure of the conductors:
430 boost::mpl::for_each<ElemList> (ClearDivInConductors (this, vertDD, div, charge));
431
432#ifdef UG_PARALLEL
433// Sum up the charges over the processes
434 if (charge.size () != 0)
435 {
436 pcl::ProcessCommunicator proc_comm;
438 sum.resize (charge.size ());
439 proc_comm.allreduce (&(charge.at(0)), &(sum.at(0)), charge.size (), PCL_RO_SUM);
440 charge = sum;
441 }
442#endif
443}
444
459template <typename TDomain, typename TAlgebra>
461(
462 const TDomain & domain,
463 const DoFDistribution & edgeDD,
464 vector_type & u,
465 size_t fct,
466 const DoFDistribution & vertDD,
467 const pot_vector_type & cor
468)
469{
470// Iterator over edges
471 typedef DoFDistribution::traits<Edge>::const_iterator t_edge_iterator;
472
473#ifdef UG_PARALLEL
474 if (! u.has_storage_type (PST_CONSISTENT))
475 UG_THROW ("Consistent storage type is expected for the grid function to project.")
476#endif
477
478// Arrays for the indices in the vectors:
479 std::vector<size_t> vVertInd (1);
480 std::vector<DoFIndex> vEdgeInd (1);
481
482// Loop over edges:
483 t_edge_iterator iterEnd = edgeDD.end<Edge> ();
484 for (t_edge_iterator iter = edgeDD.begin<Edge> (); iter != iterEnd; iter++)
485 {
486 number corner_val [2];
487 Edge * pEdge = *iter;
488
489 // Get the potential the ends of the edge:
490 for (size_t i = 0; i < 2; i++)
491 {
492 // Get the multiindices
493 if (vertDD.inner_algebra_indices (pEdge->vertex(i), vVertInd) != 1)
494 UG_THROW ("NedelecProject:"
495 "More than one DoF per vertex for the auxiliary systems.");
496
497 // Set the Dirichlet entry
498 corner_val [i] = cor [vVertInd[0]];
499 }
500
501 // Compute the gradient:
502 if (edgeDD.inner_dof_indices (pEdge, fct, vEdgeInd) != 1)
503 UG_THROW ("NedelecProject:"
504 "More than one DoF per edge. Not the Nedelec-Type-1 element?");
505 DoFRef (u, vEdgeInd[0])
506 -= corner_val [1] - corner_val [0];
507 }
508}
509
514template <typename TDomain, typename TAlgebra>
516(
517 const TDomain & domain,
518 pot_gf_type & aux_rhs
519)
520{
521 const DoFDistribution * vertDD = aux_rhs.dof_distribution().get ();
522 const std::vector<int> & cond_index = m_spEmMaterial->base_conductor_index ();
523 const std::vector<int> & base_cond = m_spEmMaterial->base_conductors ();
524 size_t n_cond = base_cond.size ();
525 std::vector<char> grounded (n_cond); // a logical array; do not replace char->bool to avoid problems with MPI!
526
527 for (size_t i = 0; i < n_cond; i++) grounded [i] = 0; // false
528
529// Exclude grounded conductors
530 if (m_spDirichlet.valid ())
531 {
532 typedef DoFDistribution::traits<Edge>::const_iterator t_edge_iterator;
533
534 const grid_type * grid = domain.grid().get ();
535 const subset_handler_type * ss_handler = domain.subset_handler().get ();
536 Grid::volume_traits::secure_container volume_list;
537
538 SubsetGroup dirichlet_ssgrp (domain.subset_handler());
539 m_spDirichlet->get_dirichlet_subsets (dirichlet_ssgrp);
540
541 // Loop the Dirichlet subsets
542 for (size_t j = 0; j < dirichlet_ssgrp.size (); j++)
543 {
544 int si = dirichlet_ssgrp [j];
545
546 // Loop the Dirichlet edges in the subset
547 //TODO: Requires a parallelization!
548 t_edge_iterator iterEnd = vertDD->end<Edge> (si);
549 for (t_edge_iterator iter = vertDD->begin<Edge> (si); iter != iterEnd; iter++)
550 {
551 // Loop the adjacent volumes
552 ((grid_type*) grid)->associated_elements (volume_list, *iter);
553 for (size_t v = 0; v < volume_list.size (); v++)
554 {
555 int v_b_cnd;
556 if ((v_b_cnd = cond_index [ss_handler->get_subset_index (volume_list [v])]) < 0)
557 continue;
558 grounded [v_b_cnd] = 1; // true
559 }
560 }
561 }
562# ifdef UG_PARALLEL
563 /* The base conductors are well-defined over the parallel
564 * architechture. For that, we only need to summarize the flags.
565 */
566 pcl::ProcessCommunicator proc_comm;
567 std::vector<char> loc_grounded = grounded;
568 proc_comm.allreduce (loc_grounded, grounded, PCL_RO_LOR);
569# endif
570 }
571
572// Allocate memory for the conductors
573 m_DVF_phi.resize (n_cond);
574 for (size_t i = 0; i < n_cond; i++)
575 if (grounded [i])
576 m_DVF_phi [i] = NULL; // the conductor is grounded, skip it
577 else
578 m_DVF_phi [i] = new pot_gf_type (aux_rhs.approx_space (), aux_rhs.dof_distribution ());
579}
580
584template <typename TDomain, typename TAlgebra>
586(
587 pot_gf_type & aux_rhs //< grid function for the auxiliary rhs
588)
589{
590 for (size_t i = 0; i < m_DVF_phi.size (); i++)
591 {
592 pot_gf_type * phi = m_DVF_phi [i];
593 if (phi == NULL) continue; // a grounded conductor
594
595 // 1. Compose the right-hand side:
596 m_auxLaplaceRHS->set_base_conductor (i);
597# ifdef UG_PARALLEL
598 aux_rhs.set_storage_type (PST_ADDITIVE);
599# endif
600 aux_rhs.set (0.0);
601 m_auxLaplaceAss->adjust_solution (aux_rhs, aux_rhs.dof_distribution ());
602 // 2. Solve the auxiliary system:
603# ifdef UG_PARALLEL
604 phi->set_storage_type (PST_CONSISTENT);
605# endif
606 phi->set (0.0);
607 m_auxLaplaceAss->adjust_solution (*phi, phi->dof_distribution ());
608 m_potSolver->apply (*phi, aux_rhs);
609 }
610}
611
615template <typename TDomain, typename TAlgebra>
617(
618 const TDomain & domain,
619 DoFDistribution & vertDD
620)
621{
622// The full-dim. grid element types for this dimension:
623 typedef typename domain_traits<WDim>::DimElemList ElemList;
624
625// Prepare the matrix for the potential coefficients:
626 size_t num_b_cond = m_DVF_phi.size ();
627 m_potCoeff.resize (num_b_cond, num_b_cond, false);
628 if (num_b_cond <= 0) return; // nothing to do: no conductors
629
630// Get the base conductor indices at vertices (set -2 for insulators, -1 for grounded conductors)
631 SmartPtr<MultiGrid> sp_mg = vertDD.multi_grid ();
632 a_vert_cond_type a_vert_base_cond;
633 sp_mg->attach_to_vertices (a_vert_base_cond);
634 aa_vert_cond_type vert_base_cond (*sp_mg, a_vert_base_cond);
635 SetAttachmentValues (vert_base_cond, vertDD.begin<Vertex>(), vertDD.end<Vertex>(), -2);
636
637 boost::mpl::for_each<ElemList> (MarkCondVert (this, vertDD, vert_base_cond));
638
639# ifdef UG_PARALLEL
640 AttachmentAllReduce<Vertex> (*sp_mg, a_vert_base_cond, PCL_RO_MAX);
641# endif
642
643// Compute the capacity matrix
644 m_potCoeff = 0.0;
645
646 boost::mpl::for_each<ElemList> (IntegrateDivDVF
647 (this, domain, vertDD, vert_base_cond, m_potCoeff));
648
649 sp_mg->detach_from_vertices (a_vert_base_cond); // we do not need the attachment any more
650
651# ifdef UG_PARALLEL
652 {
653 // Only the lower triangular part is assemble, but for simplicity, we
654 // reduce the whole matrix (as it should be relatively small)
655 pcl::ProcessCommunicator proc_comm;
657 sum.resize (m_potCoeff.num_rows (), m_potCoeff.num_cols (), false);
658 proc_comm.allreduce (&(m_potCoeff.at(0,0)), &(sum.at(0,0)),
659 m_potCoeff.num_rows () * m_potCoeff.num_cols (), PCL_RO_SUM);
660 m_potCoeff = sum;
661 }
662# endif
663
664 for (size_t i = 0; i < num_b_cond; i++)
665 if (m_DVF_phi [i] == NULL)
666 m_potCoeff (i, i) = 1; // set the matrix to identity for the grounded conductors
667 else
668 for (size_t j = i + 1; j < num_b_cond; j++)
669 m_potCoeff (i, j) = m_potCoeff (j, i); // use the symmetry in the lower triangular part
670
671// Invert the capacity matrix to get the potential coefficients
672 Invert (m_potCoeff);
673}
674
678template <typename TDomain, typename TAlgebra>
680(
681 pot_vector_type & cor,
682 const DenseVector<VariableArray1<number> > & charge
683)
684{
685 DenseVector<VariableArray1<number> > factor = m_potCoeff * charge;
686
687 for (size_t i = 0; i < m_DVF_phi.size (); i++)
688 if (m_DVF_phi [i] != NULL) // skip grounded conductors
689 VecScaleAdd (cor, 1.0, cor, factor [i], * (pot_vector_type *) m_DVF_phi [i]);
690}
691
699template <typename TDomain, typename TAlgebra>
700template <typename TElem>
702(
703 DoFDistribution & vertDD,
704 aa_vert_cond_type & vert_base_cond
705)
706{
707 typedef typename reference_element_traits<TElem>::reference_element_type ref_elem_type;
708 typedef typename DoFDistribution::traits<TElem>::const_iterator iterator;
709
710 int base_cond_ind;
711
712// Get the conductor distribution and the positions of the grid points:
713 const std::vector<int> & cond_index = m_spEmMaterial->base_conductor_index ();
714
715// Array for the indices in the vectors:
716 std::vector<size_t> vVertInd (ref_elem_type::numCorners);
717
718// Loop over all subsets representing conductors:
719 for (int si = 0; si < vertDD.num_subsets (); si++)
720 if ((base_cond_ind = cond_index [si]) >= 0)
721 {
722 // Mark the grounded conductors with -1 (insulators are marked with -2)
723 if (m_DVF_phi [base_cond_ind] == NULL)
724 base_cond_ind = -1;
725
726 // Loop over all the elements of the given type in the subset
727 iterator e_end = vertDD.template end<TElem> (si);
728 for (iterator elem_iter = vertDD.template begin<TElem> (si);
729 elem_iter != e_end; ++elem_iter)
730 {
731 TElem * pElem = *elem_iter;
732 for (size_t co = 0; co < (size_t) ref_elem_type::numCorners; co++)
733 vert_base_cond [pElem->vertex (co)] = base_cond_ind;
734 }
735 }
736}
737
743template <typename TDomain, typename TAlgebra>
744template <typename TElem>
746(
747 const TDomain & domain,
748 const DoFDistribution & vertDD,
749 const aa_vert_cond_type & vert_base_cond,
751)
752{
753 typedef typename reference_element_traits<TElem>::reference_element_type ref_elem_type;
754 typedef typename DoFDistribution::traits<TElem>::const_iterator iterator;
755
756// Get the positions of the grid points:
757 const typename TDomain::position_accessor_type & aaPos = domain.position_accessor ();
758
759// Get the conductor distribution and the positions of the grid points:
760 const std::vector<int> & cond_index = m_spEmMaterial->base_conductor_index ();
761
762// Array for the indices in the vectors:
763 std::vector<size_t> vVertInd (ref_elem_type::numCorners);
764
765// Loop over all subsets representing insulators:
766 for (int si = 0; si < vertDD.num_subsets (); si++)
767 if (cond_index [si] == -2) // we loop over INSULATORS! (>= -1 are conductors)
768 {
769 // Loop over all the elements of the given type in the subset
770 iterator e_end = vertDD.template end<TElem> (si);
771 for (iterator elem_iter = vertDD.template begin<TElem> (si);
772 elem_iter != e_end; ++elem_iter)
773 {
774 TElem * pElem = *elem_iter;
775 size_t corner_cond [ref_elem_type::numCorners];
776 bool cond_bnd_flag;
777
778 // get the indices in the vectors:
779 cond_bnd_flag = false;
780 for (size_t co = 0; co < (size_t) ref_elem_type::numCorners; co++)
781 if ((corner_cond [co] = vert_base_cond [pElem->vertex (co)]) >= 0)
782 cond_bnd_flag = true;
783 if (! cond_bnd_flag) continue; // not at a boundary of a non-grounded conductor
784
785 // get the corner positions:
786 position_type aCorners [ref_elem_type::numCorners];
787 for (size_t co = 0; co < (size_t) ref_elem_type::numCorners; co++)
788 aCorners [co] = aaPos [pElem->vertex (co)];
789
790 // assemble the local matrix
791 number loc_A [ref_elem_type::numCorners] [ref_elem_type::numCorners];
792 LocLaplaceA<TElem>::stiffness (pElem, aCorners, loc_A);
793
794 // add the contributions to the capacity matrix
795 if (vertDD.algebra_indices (pElem, vVertInd) != (size_t) ref_elem_type::numCorners)
796 UG_THROW ("NedelecProject: Vertex DoF distribution mismatch. Not the Lagrange-Order-1 element?");
797 for (int to_cond = 0; to_cond < (int) m_DVF_phi.size (); to_cond++)
798 {
799 // In this computation, C(i,j) is the charge induced by phi(j)
800 // in conductor i. The conductor i, where the charge is induced,
801 // is called 'the from-conductor', and the conductor j, whose
802 // potential induces the charge, is called 'the to-conductor'.
803 pot_vector_type * phi = m_DVF_phi [to_cond];
804 if (phi == NULL) continue; // this is a grounded conductor
805
806 for (size_t to_co = 0; to_co < (size_t) ref_elem_type::numCorners; to_co++)
807 {
808 int from_cond;
809 number phi_val = (* phi) [vVertInd [to_co]];
810 for (size_t from_co = 0; from_co < (size_t) ref_elem_type::numCorners; from_co++)
811 // Exclude inner vertices of insulators and grounded conductors, as well as the upper triangle
812 if ((from_cond = corner_cond [from_co]) >= to_cond)
813 C (from_cond, to_cond) += loc_A [from_co] [to_co] * phi_val;
814 }
815 }
816 }
817 }
818}
819
820/*----- Assembling the auxiliary Poisson problems 1: class AuxLaplaceLocAss -----*/
821
825template <typename TDomain, typename TAlgebra>
826template <typename TElem>
828(
829 GridObject * elem,
830 const position_type vCornerCoords [],
831 number loc_A [numCorners] [numCorners]
832)
833{
835
836// request the finite element geometry
837 TFEGeom & geo = GeomProvider<TFEGeom>::get ();
838 // we assume that this is the simplest discretization:
839 UG_ASSERT (geo.num_ip () == 1, "Only the simplest quadrature is supported here.");
840
841// initialize the fe geometry
842 geo.update (elem, vCornerCoords);
843
844// compute the upper triangle of the local stiffness matrix
845 for (size_t from_co = 0; from_co < (size_t) numCorners; from_co++)
846 for (size_t to_co = from_co; to_co < (size_t) numCorners; to_co++)
847 loc_A [from_co] [to_co]
848 = VecDot (geo.global_grad (0, from_co), geo.global_grad (0, to_co))
849 * geo.weight (0);
850// use the symmetry
851 for (size_t from_co = 1; from_co < (size_t) numCorners; from_co++)
852 for (size_t to_co = 0; to_co < from_co; to_co++)
853 loc_A [from_co] [to_co] = loc_A [to_co] [from_co];
854}
855
860template <typename TDomain, typename TAlgebra>
862(
863 NedelecProject & master
864)
865: IElemDisc<TDomain> (master.m_spVertApproxSpace->name(0).c_str(), master.m_spEmMaterial->subset_names()),
866 m_master (master), m_do_assemble_here (false)
867{
868// register assemble functions
870}
871
872// check the basis and the grid
873template<typename TDomain, typename TAlgebra>
875(
876 const std::vector<LFEID> & vLfeID,
877 bool bNonRegular
878)
879{
880 if (bNonRegular)
881 UG_THROW ("NedelecProject:"
882 " The discretization of the auxiliary systems does not support hanging nodes.\n");
883
884 if (vLfeID.size () != 1)
885 UG_THROW ("NedelecProject:"
886 " Only scalar grid functions are supported for the potential");
887
888 if (vLfeID[0].type() != LFEID::LAGRANGE || vLfeID[0].order() != 1)
889 UG_THROW ("NedelecProject:"
890 " Only Largange-1 functions are supported for the potential");
891}
892
893// register the local assembler functions for all the elements and dimensions
894template<typename TDomain, typename TAlgebra>
896{
897// get all grid element types in this dimension and below
898 typedef typename domain_traits<WDim>::DimElemList ElemList;
899
900// switch assemble functions
901 boost::mpl::for_each<ElemList> (RegisterLocalDiscr (this));
902}
903
904// register the local assembler functions for a given element
905template<typename TDomain, typename TAlgebra>
906template<typename TElem> // the element to register for
908{
910
911 this->clear_add_fct(id);
912 this->set_prep_elem_loop_fct(id, & AuxLaplaceLocAss::template prepare_element_loop<TElem>);
913 this->set_prep_elem_fct (id, & AuxLaplaceLocAss::template prepare_element<TElem>);
914 this->set_fsh_elem_loop_fct (id, & AuxLaplaceLocAss::template finish_element_loop<TElem>);
915 this->set_add_jac_A_elem_fct(id, & AuxLaplaceLocAss::template ass_JA_elem<TElem>);
916 this->set_add_jac_M_elem_fct(id, & AuxLaplaceLocAss::template ass_JM_elem<TElem>);
917 this->set_add_def_A_elem_fct(id, & AuxLaplaceLocAss::template ass_dA_elem<TElem>);
918 this->set_add_def_M_elem_fct(id, & AuxLaplaceLocAss::template ass_dM_elem<TElem>);
919 this->set_add_rhs_elem_fct (id, & AuxLaplaceLocAss::template ass_rhs_elem<TElem>);
920}
921
922// prepares the loop over the elements: check if the subdomain an insulator
923template<typename TDomain, typename TAlgebra>
924template<typename TElem>
926(
927 ReferenceObjectID roid, // [in] only elements with this roid are looped over
928 int si // [in] and only in this subdomain
929)
930{
931// We assemble in insulators only
932 if (m_master.m_spEmMaterial->base_conductor_index (si) == -1)
933 m_do_assemble_here = true;
934 else
935 m_do_assemble_here = false;
936}
937
939template<typename TDomain, typename TAlgebra>
940template<typename TElem>
942(
943 LocalMatrix & J,
944 const LocalVector & u,
945 GridObject * elem,
946 const position_type vCornerCoords []
947)
948{
949 if (! m_do_assemble_here) return;
950
951 typedef typename reference_element_traits<TElem>::reference_element_type ref_elem_type;
952
953// assemble the local matrix
954 number loc_A [ref_elem_type::numCorners] [ref_elem_type::numCorners];
956
957// add the local matrix to the global one
958 for (size_t from_co = 0; from_co < (size_t) ref_elem_type::numCorners; from_co++)
959 for (size_t to_co = 0; to_co < (size_t) ref_elem_type::numCorners; to_co++)
960 J (_C_, from_co, _C_, to_co) += loc_A [from_co] [to_co];
961}
962
963/*----- Assembling the auxiliary Poisson problems 2: class AuxLaplaceRHS -----*/
964
968template <typename TDomain, typename TAlgebra>
970(
971 NedelecProject & master
972)
973: m_master (master), m_base_cond (-2)
974{}
975
979template <typename TDomain, typename TAlgebra>
981(
982 pot_vector_type & u,
983 const DoFDistribution * dd
984)
985{
986 if (m_master.m_spDirichlet.invalid ())
987 return; // no Dirichlet boundaries specified
988
989 std::vector<size_t> vVertInd (1);
990
991 SubsetGroup dirichlet_ssgrp (m_master.m_spEmMaterial->subset_handler ());
992 m_master.m_spDirichlet->get_dirichlet_subsets (dirichlet_ssgrp);
993
994// Loop over the Dirichlet subsets
995 for (size_t j = 0; j < dirichlet_ssgrp.size (); j++)
996 {
997 int si = dirichlet_ssgrp [j];
998
999 // Loop the edges
1000 t_edge_iterator iterEnd = dd->end<Edge> (si);
1001 for (t_edge_iterator iter = dd->begin<Edge> (si); iter != iterEnd; iter++)
1002 {
1003 Edge * pEdge = *iter;
1004
1005 // For both the ends of the edge
1006 for(size_t i = 0; i < 2; i++)
1007 {
1008 // Get the multiindices
1009 if (dd->inner_algebra_indices (pEdge->vertex(i), vVertInd) != 1)
1010 UG_THROW ("NedelecProject:"
1011 "More than one DoF per vertex for the auxiliary systems.");
1012
1013 // Set the Dirichlet entry
1014 u [vVertInd [0]] = 0;
1015 }
1016 }
1017 }
1018}
1019
1023template <typename TDomain, typename TAlgebra>
1025(
1026 pot_matrix_type & A,
1027 const DoFDistribution * dd
1028)
1029{
1030 if (m_master.m_spDirichlet.invalid ())
1031 return; // no Dirichlet boundaries specified
1032
1033 std::vector<size_t> vVertInd (1);
1034
1035 SubsetGroup dirichlet_ssgrp (m_master.m_spEmMaterial->subset_handler ());
1036 m_master.m_spDirichlet->get_dirichlet_subsets (dirichlet_ssgrp);
1037
1038// Loop over the Dirichlet subsets
1039 for (size_t j = 0; j < dirichlet_ssgrp.size (); j++)
1040 {
1041 int si = dirichlet_ssgrp [j];
1042
1043 // Loop the edges
1044 t_edge_iterator iterEnd = dd->end<Edge> (si);
1045 for (t_edge_iterator iter = dd->begin<Edge> (si); iter != iterEnd; iter++)
1046 {
1047 Edge * pEdge = *iter;
1048
1049 // For both the ends of the edge
1050 for(size_t i = 0; i < 2; i++)
1051 {
1052 // Get the multiindices
1053 if (dd->inner_algebra_indices (pEdge->vertex(i), vVertInd) != 1)
1054 UG_THROW ("NedelecProject:"
1055 "More than one DoF per vertex for the auxiliary systems.");
1056
1057 // Set the Dirichlet row
1058 SetDirichletRow (A, vVertInd[0]);
1059 }
1060 }
1061 }
1062}
1063
1067template <typename TDomain, typename TAlgebra>
1068template <typename TElem>
1070(
1071 int si,
1072 number val,
1073 pot_vector_type & u,
1074 const DoFDistribution * dd
1075)
1076{
1077 typedef typename reference_element_traits<TElem>::reference_element_type ref_elem_type;
1078 typedef typename DoFDistribution::traits<TElem>::const_iterator t_elem_iterator;
1079
1080 std::vector<size_t> vVertInd (1);
1081
1082// Loop the elements
1083 t_elem_iterator iterEnd = dd->end<TElem> (si);
1084 for (t_elem_iterator iter = dd->begin<TElem> (si); iter != iterEnd; iter++)
1085 {
1086 TElem * pElem = *iter;
1087
1088 // Loop the corners
1089 for(size_t co = 0; co < (size_t) ref_elem_type::numCorners; co++)
1090 {
1091 // Get the multiindices
1092 if (dd->inner_algebra_indices (pElem->vertex(co), vVertInd) != 1)
1093 UG_THROW ("NedelecProject:"
1094 "More than one DoF per vertex for the auxiliary systems.");
1095
1096 // Set the value
1097 u [vVertInd [0]] = val;
1098 }
1099 }
1100}
1101
1105template <typename TDomain, typename TAlgebra>
1106template <typename TElem>
1108(
1109 int si,
1110 pot_matrix_type & A,
1111 const DoFDistribution * dd
1112)
1113{
1114 typedef typename reference_element_traits<TElem>::reference_element_type ref_elem_type;
1115 typedef typename DoFDistribution::traits<TElem>::const_iterator t_elem_iterator;
1116
1117 std::vector<size_t> vVertInd (1);
1118
1119// Loop the elements
1120 t_elem_iterator iterEnd = dd->end<TElem> (si);
1121 for (t_elem_iterator iter = dd->begin<TElem> (si); iter != iterEnd; iter++)
1122 {
1123 TElem * pElem = *iter;
1124
1125 // Loop the corners
1126 for(size_t co = 0; co < (size_t) ref_elem_type::numCorners; co++)
1127 {
1128 // Get the multiindices
1129 if (dd->inner_algebra_indices (pElem->vertex(co), vVertInd) != 1)
1130 UG_THROW ("NedelecProject:"
1131 "More than one DoF per vertex for the auxiliary systems.");
1132
1133 // Set the row
1134 SetDirichletRow (A, vVertInd[0]);
1135 }
1136 }
1137}
1138
1142template <typename TDomain, typename TAlgebra>
1144(
1145 pot_matrix_type & J,
1146 const pot_vector_type & u,
1148 int type,
1149 number time,
1151 const number s_a0
1152)
1153{
1154// Set all matrix rows at Dirichlet boundaries to identity:
1155 set_identity_Dirichlet (J, dd.get());
1156
1157// Set all matrix rows in conductors to identity:
1158 typedef typename domain_traits<WDim>::DimElemList ElemList;
1159 const std::vector<int> & base_cond = m_master.m_spEmMaterial->base_conductor_index ();
1160
1161 for (size_t si = 0; si < base_cond.size (); si++)
1162 if (base_cond [si] >= 0)
1163 boost::mpl::for_each<ElemList> (SetIdentityOnSubset (this, si, J, dd.get ()));
1164}
1165
1169template <typename TDomain, typename TAlgebra>
1171(
1172 pot_vector_type & d,
1173 const pot_vector_type & u,
1175 int type,
1176 number time,
1178 const std::vector<number> * vScaleMass,
1179 const std::vector<number> * vScaleStiff
1180)
1181{
1182// Set all entries at Dirichlet boundaries to zero:
1183 set_zero_Dirichlet (d, dd.get ());
1184
1185// Set all entries in conductors to zero:
1186 typedef typename domain_traits<WDim>::DimElemList ElemList;
1187 const std::vector<int> & base_cond = m_master.m_spEmMaterial->base_conductor_index ();
1188
1189 for (size_t si = 0; si < base_cond.size (); si++)
1190 if (base_cond [si] >= 0)
1191 boost::mpl::for_each<ElemList> (SetValueOnSubset (this, si, 0, d, dd.get ()));
1192}
1193
1197template <typename TDomain, typename TAlgebra>
1199(
1200 pot_vector_type & u,
1202 int type,
1203 number time
1204)
1205{
1206// Set all entries at Dirichlet boundaries to identity:
1207 set_zero_Dirichlet (u, dd.get ());
1208
1209// Set all entries in conductors to 0 or 1:
1210 typedef typename domain_traits<WDim>::DimElemList ElemList;
1211 const std::vector<int> & base_cond = m_master.m_spEmMaterial->base_conductor_index ();
1212
1213 for (size_t si = 0; si < base_cond.size (); si++)
1214 {
1215 int the_base_cond = base_cond [si];
1216 if (the_base_cond < 0) continue;
1217 number val = (the_base_cond == m_base_cond)? 1 : 0;
1218 boost::mpl::for_each<ElemList> (SetValueOnSubset (this, si, val, u, dd.get ()));
1219 }
1220}
1221
1222} // end namespace Electromagnetism
1223} // end namespace ug
1224
1225/* End of File */
const T * get() const
T * get()
size_t allreduce(const size_t &t, pcl::ReduceOperation op) const
traits< TElem >::iterator begin()
traits< TElem >::iterator end()
size_t dof_indices(GridObject *elem, size_t fct, std::vector< DoFIndex > &ind, bool bHang=false, bool bClear=true) const
size_t algebra_indices(GridObject *elem, std::vector< size_t > &ind, bool bClear=true) const
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
ConstSmartPtr< DoFDistributionInfo > dof_distribution_info() const
const LFEID & local_finite_element_id(size_t fct) const
size_t fct_id_by_name(const char *name) const
FunctionGroup fct_grp_by_name(const char *names) const
virtual Vertex * vertex(size_t index) const
Class for subdomain-dependent data for the E-based formulated problems.
Definition em_material.h:63
Class for local assembling of the auxiliary Laplace operator.
Definition nedelec_project.h:403
void prepare_element_loop(ReferenceObjectID roid, int si)
Definition nedelec_project_impl.h:926
virtual void prepare_setting(const std::vector< LFEID > &vLfeID, bool bNonRegular)
switches between non-regular and regular grids
Definition nedelec_project_impl.h:875
void register_loc_discr_func()
Definition nedelec_project_impl.h:907
AuxLaplaceLocAss(NedelecProject &master)
constructor
Definition nedelec_project_impl.h:862
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_project_impl.h:942
void register_all_loc_discr_funcs()
Definition nedelec_project_impl.h:895
Constraint that assembles the rhs und the bc for the auxiliary problems.
Definition nedelec_project.h:486
void adjust_defect(pot_vector_type &d, const pot_vector_type &u, ConstSmartPtr< DoFDistribution > dd, int type, number time=0.0, ConstSmartPtr< VectorTimeSeries< pot_vector_type > > vSol=SPNULL, const std::vector< number > *vScaleMass=NULL, const std::vector< number > *vScaleStiff=NULL)
sets a zero value in the defect for all conductor indices
Definition nedelec_project_impl.h:1171
void set_value_on_subset(int si, number val, pot_vector_type &u, const DoFDistribution *dd)
sets constant value on the closure of a full-dimensional subset
Definition nedelec_project_impl.h:1070
void set_identity_Dirichlet(pot_matrix_type &A, const DoFDistribution *dd)
sets identity matrix on the whole Dirichlet boundary
Definition nedelec_project_impl.h:1025
void set_identity_on_subset(int si, pot_matrix_type &A, const DoFDistribution *dd)
sets identity matrix on the closure of a full-dimensional subset
Definition nedelec_project_impl.h:1108
void set_zero_Dirichlet(pot_vector_type &u, const DoFDistribution *dd)
sets zero values on the whole Dirichlet boundary
Definition nedelec_project_impl.h:981
void adjust_jacobian(pot_matrix_type &J, const pot_vector_type &u, ConstSmartPtr< DoFDistribution > dd, int type, number time=0.0, ConstSmartPtr< VectorTimeSeries< pot_vector_type > > vSol=SPNULL, const number s_a0=1.0)
sets a unity row for all conductor indices
Definition nedelec_project_impl.h:1144
AuxLaplaceRHS(NedelecProject &master)
constructor
Definition nedelec_project_impl.h:970
void adjust_solution(pot_vector_type &u, ConstSmartPtr< DoFDistribution > dd, int type, number time=0.0)
sets the value in the solution for all conductor indices
Definition nedelec_project_impl.h:1199
Helper class for assembling the local stiffness matrix of Laplacian in various routines.
Definition nedelec_project.h:387
static void stiffness(GridObject *elem, const position_type vCornerCoords[], number loc_A[numCorners][numCorners])
Computes the local discretization of the Laplace operator.
Definition nedelec_project_impl.h:828
Projection procedure class.
Definition nedelec_project.h:72
void project_func(const SmartPtr< TDomain > &domain, const SmartPtr< DoFDistribution > &edgeDD, vector_type &u, size_t fct, const SmartPtr< DoFDistribution > &vertDD, pot_gf_type &aux_rhs, pot_gf_type &aux_cor)
Projects one function (i.e. performs the main action):
Definition nedelec_project_impl.h:247
void mark_cond_vert_elem_type(DoFDistribution &vertDD, aa_vert_cond_type &vert_base_cond)
Sets the base conductor indices for every vertex (for all elements of the same type)
Definition nedelec_project_impl.h:702
void assemble_div(const TDomain &domain, const DoFDistribution &edgeDD, const vector_type &u, size_t fct, const DoFDistribution &vertDD, pot_vector_type &div, DenseVector< VariableArray1< number > > &charge)
Assembles the weak divergence operator on the whole grid.
Definition nedelec_project_impl.h:404
void distribute_cor(const TDomain &domain, const DoFDistribution &edgeDD, vector_type &u, size_t fct, const DoFDistribution &vertDD, const pot_vector_type &cor)
Updates the grid function by the potential correction.
Definition nedelec_project_impl.h:461
SmartPtr< AuxLaplaceRHS > m_auxLaplaceRHS
Rhs and BC for the auxiliary problem.
Definition nedelec_project.h:686
SmartPtr< ApproximationSpace< TDomain > > m_spVertApproxSpace
Approximation space for the potential (vertex-centered) space.
Definition nedelec_project.h:675
void compute_DVF_potential_coeffs(const TDomain &domain, DoFDistribution &vertDD)
Computes the potential coefficients.
Definition nedelec_project_impl.h:617
TAlgebra::vector_type vector_type
Type of Vector (for the Nedelec-element-based grid functions)
Definition nedelec_project.h:89
void clear_div_in_conductors(const DoFDistribution &vertDD, pot_vector_type &div, DenseVector< VariableArray1< number > > &charge)
Sets the div operator to 0 in conductors (for all elements of the same type)
Definition nedelec_project_impl.h:358
void compute_div(SmartPtr< GridFunction< TDomain, TAlgebra > > sp_u, const char *u_fct_name, SmartPtr< GridFunction< TDomain, TPotAlgebra > > sp_div)
Computes the weak divergence in insulators.
Definition nedelec_project_impl.h:192
SmartPtr< DomainDiscretization< TDomain, TPotAlgebra > > m_auxLaplaceAss
Global discretization of the auxiliary equations.
Definition nedelec_project.h:688
SmartPtr< ILinearOperatorInverse< pot_vector_type > > m_potSolver
Solver for the auxliliary equations.
Definition nedelec_project.h:692
domain_type::subset_handler_type subset_handler_type
Type of subset handler.
Definition nedelec_project.h:84
NedelecProject(SmartPtr< EMaterial< TDomain > > emMatherial, SmartPtr< ApproximationSpace< TDomain > > vertApproxSpace, SmartPtr< ILinearOperatorInverse< pot_vector_type > > potSolver)
Constructor.
Definition nedelec_project_impl.h:53
SmartPtr< AuxLaplaceLocAss > m_auxLocLaplace
Local discretization of the auxiliary equations.
Definition nedelec_project.h:684
void apply(vector_type &vec)
Performs the projection of all functions in a grid function.
Definition nedelec_project_impl.h:90
void alloc_DVFs(const TDomain &domain, pot_gf_type &aux_rhs)
Allocates memory for the DVFs associated with the ungrounded conductors.
Definition nedelec_project_impl.h:516
TDomain::position_type position_type
position type
Definition nedelec_project.h:106
void damp_DVFs(pot_vector_type &cor, const DenseVector< VariableArray1< number > > &charge)
Damps the Dirichlet vector fields (DVFs)
Definition nedelec_project_impl.h:680
void integrate_div_DVF_elem_type(const TDomain &domain, const DoFDistribution &vertDD, const aa_vert_cond_type &vert_base_cond, DenseMatrix< VariableArray2< number > > &C)
Integrates div E over boundaries of conductors for elements of the same type.
Definition nedelec_project_impl.h:746
TDomain::grid_type grid_type
Type of Grid:
Definition nedelec_project.h:81
void compute_DVFs(pot_gf_type &aux_rhs)
Computes the Dirichlet vector fields (DVFs)
Definition nedelec_project_impl.h:586
SmartPtr< EMaterial< TDomain > > m_spEmMaterial
Properties of the matherials in the domain.
Definition nedelec_project.h:672
void weak_div_elem_type(const TDomain &domain, const DoFDistribution &edgeDD, const vector_type &u, size_t fct, const DoFDistribution &vertDD, pot_vector_type &div)
Computes the weak divergence (for all elements of the same type)
Definition nedelec_project_impl.h:289
static void local_div_matrix(const TDomain *domain, TElem *elem, const position_type *corners, number B[][numEdges])
assembles the discrete weak div operator
Definition nedelec_local_ass.h:144
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)
SpaceType type() const
void set(number w)
bool change_storage_type(ParallelStorageType type)
void set_storage_type(uint type)
size_t size() const
PST_CONSISTENT
PST_ADDITIVE
SmartPtr< TGrid > grid()
void SetAttachmentValues(TAttachmentAccessor &aaVal, TIter elemsBegin, TIter elemsEnd, const TVal &val)
#define PCL_RO_SUM
#define PCL_RO_MAX
#define PCL_RO_LOR
bool Invert(DenseMatrix< FixedArray2< double, 1, 1 > > &mat)
Variant::Type type()
#define UG_ASSERT(expr, msg)
#define UG_CATCH_THROW(msg)
#define UG_THROW(msg)
double number
void MatVecMult(vector_t_out &vOut, const matrix_t &m, const vector_t_in &v)
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)
void VecScaleAdd(double &dest, double alpha1, const double &v1, double alpha2, const double &v2)
Helper class for 'set_value_on_subset'.
Definition nedelec_project.h:639
Helper class for 'set_value_on_subset'.
Definition nedelec_project.h:605
Helper class for assembling the weak divergence operator.
Definition nedelec_project.h:243
Helper class for computation of the charges of the DVFs.
Definition nedelec_project.h:357
Helper class for setting the base conductor indices to vertices.
Definition nedelec_project.h:326
Helper class for the computation the weak divergence.
Definition nedelec_project.h:203
function ProblemDisc new(problemDesc, dom)