Plugins
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 
45 namespace ug{
46 namespace Electromagnetism{
47 
51 template <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.");
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:
81  m_auxLaplaceAss->add
83 }
84 
88 template <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 
107 template <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 
129 template <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 
190 template <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 
223  if (u.local_finite_element_id(u_fct).type () != LFEID::NEDELEC)
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 
245 template <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 
286 template <typename TDomain, typename TAlgebra>
287 template <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)];
327  NedelecT1_LDisc<TDomain, TElem>::local_div_matrix (&domain, pElem, aCorners,
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 
355 template <typename TDomain, typename TAlgebra>
356 template <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 
402 template <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 
459 template <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 
514 template <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 ();
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 
584 template <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 
615 template <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 
678 template <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 
699 template <typename TDomain, typename TAlgebra>
700 template <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 
743 template <typename TDomain, typename TAlgebra>
744 template <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 
825 template <typename TDomain, typename TAlgebra>
826 template <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 
860 template <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
873 template<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
894 template<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
905 template<typename TDomain, typename TAlgebra>
906 template<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
923 template<typename TDomain, typename TAlgebra>
924 template<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 
939 template<typename TDomain, typename TAlgebra>
940 template<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 
968 template <typename TDomain, typename TAlgebra>
970 (
971  NedelecProject & master
972 )
973 : m_master (master), m_base_cond (-2)
974 {}
975 
979 template <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 
1023 template <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 
1067 template <typename TDomain, typename TAlgebra>
1068 template <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 
1105 template <typename TDomain, typename TAlgebra>
1106 template <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 
1142 template <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 
1169 template <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 
1197 template <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
domain_type * get()
bool invalid() const
size_t allreduce(const size_t &t, pcl::ReduceOperation op) const
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
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()
ConstSmartPtr< DoFDistributionInfo > dof_distribution_info() const
size_t fct_id_by_name(const char *name) const
FunctionGroup fct_grp_by_name(const char *names) const
const LFEID & local_finite_element_id(size_t fct) 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
DoFDistribution::traits< Edge >::const_iterator t_edge_iterator
Iterator over edges.
Definition: nedelec_project.h:489
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< TDomain > domain()
SmartPtr< DoFDistribution > dof_distribution()
SmartPtr< ApproximationSpace< TDomain > > approx_space()
const GridLevel & grid_level() const
void init(SmartPtr< ApproximationSpace< TDomain > > spApproxSpace, SmartPtr< DoFDistribution > spDoFDistr, bool bManage)
TDomain::position_type position_type
SpaceType type() const
bool change_storage_type(ParallelStorageType type)
size_t size() const
size_t size() const
void get(V &u) const
PST_CONSISTENT
PST_ADDITIVE
Grid::VertexAttachmentAccessor< position_attachment_type > position_accessor_type
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)
const number & DoFRef(const TMatrix &mat, const DoFIndex &iInd, const DoFIndex &jInd)
ReferenceObjectID
void SetDirichletRow(TMatrix &mat, const DoFIndex &ind)
void VecScaleAdd(double &dest, double alpha1, const double &v1, double alpha2, const double &v2)
SurfaceView::traits< TElem >::const_iterator const_iterator
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)