ug4
integrate.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2015: G-CSC, Goethe University Frankfurt
3  * Author: Andreas Vogel
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):
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 
33 #ifndef __H__UG__LIB_DISC__FUNCTION_SPACES__INTEGRATE__
34 #define __H__UG__LIB_DISC__FUNCTION_SPACES__INTEGRATE__
35 
36 #include <cmath>
37 
38 #include <boost/function.hpp>
39 
40 #include "common/common.h"
41 
43 
46 #include "lib_disc/domain_util.h" // for CollectCornerCoordinates
53 
54 #ifdef UG_FOR_LUA
56 #endif
57 
58 namespace ug{
59 
60 
62 // Object encapsulating (scalar) GridFunction related data
64 template <typename TGridFunction>
66 {
67 public:
68  typedef typename TGridFunction::domain_type domain_type;
69 
70  ScalarGridFunctionData(TGridFunction& gridFct, size_t cmp)
71  : m_gridFct(gridFct), m_fct(cmp),
72  m_id(m_gridFct.local_finite_element_id(m_fct))
73  {}
74 
75  TGridFunction& grid_function()
76  {return m_gridFct;}
77 
78  const TGridFunction& grid_function() const
79  {return m_gridFct;}
80 
81  size_t fct()
82  {return m_fct;}
83 
84  const LFEID &id() const
85  {return m_id;}
86 
88  bool is_def_in_subset(int si) const
89  { return m_gridFct.is_def_in_subset(m_fct, si); }
90 
92  SmartPtr<domain_type> domain() {return m_gridFct.domain();}
93 
95  ConstSmartPtr<domain_type> domain() const {return m_gridFct.domain();}
96 
97  template <typename TElem>
98  size_t dof_indices(TElem* elem, std::vector<DoFIndex>& ind, bool bHang = false, bool bClear = true) const
99  {return m_gridFct.dof_indices(elem, m_fct, ind, bHang, bClear);}
100 
101 private:
103  TGridFunction& m_gridFct;
104 
106  size_t m_fct;
107 
110 };
111 
113 // Integrand Interface
115 
116 
118 
119 template <typename TData, int TWorldDim>
121 {
122  public:
124  static const int worldDim = TWorldDim;
125 
127  typedef TData data_type;
128 
130 
141  virtual void values(TData vValue[],
142  const MathVector<worldDim> vGlobIP[],
143  GridObject* pElem,
144  const MathVector<worldDim> vCornerCoords[],
145  const MathVector<1> vLocIP[],
146  const MathMatrix<1, worldDim> vJT[],
147  const size_t numIP) = 0;
148  virtual void values(TData vValue[],
149  const MathVector<worldDim> vGlobIP[],
150  GridObject* pElem,
151  const MathVector<worldDim> vCornerCoords[],
152  const MathVector<2> vLocIP[],
153  const MathMatrix<2, worldDim> vJT[],
154  const size_t numIP) = 0;
155  virtual void values(TData vValue[],
156  const MathVector<worldDim> vGlobIP[],
157  GridObject* pElem,
158  const MathVector<worldDim> vCornerCoords[],
159  const MathVector<3> vLocIP[],
160  const MathMatrix<3, worldDim> vJT[],
161  const size_t numIP) = 0;
163 
164  virtual ~IIntegrand() {}
165 
166 
168  virtual void set_subset(int si) {m_si = si;}
169 
171  inline int subset() const {return m_si;}
172 
173  protected:
175  int m_si;
176 };
177 
179 template <typename TData, int TWorldDim, typename TImpl>
180 class StdIntegrand : public IIntegrand<TData, TWorldDim>
181 {
182  public:
184  static const int worldDim = TWorldDim;
185 
187  typedef TData data_type;
188 
191  virtual void values(TData vValue[],
192  const MathVector<worldDim> vGlobIP[],
193  GridObject* pElem,
194  const MathVector<worldDim> vCornerCoords[],
195  const MathVector<1> vLocIP[],
196  const MathMatrix<1, worldDim> vJT[],
197  const size_t numIP)
198  {
199  getImpl().template evaluate<1>(vValue,vGlobIP,pElem,vCornerCoords,vLocIP,vJT,numIP);
200  }
201  virtual void values(TData vValue[],
202  const MathVector<worldDim> vGlobIP[],
203  GridObject* pElem,
204  const MathVector<worldDim> vCornerCoords[],
205  const MathVector<2> vLocIP[],
206  const MathMatrix<2, worldDim> vJT[],
207  const size_t numIP)
208  {
209  getImpl().template evaluate<2>(vValue,vGlobIP,pElem,vCornerCoords,vLocIP,vJT,numIP);
210  }
211  virtual void values(TData vValue[],
212  const MathVector<worldDim> vGlobIP[],
213  GridObject* pElem,
214  const MathVector<worldDim> vCornerCoords[],
215  const MathVector<3> vLocIP[],
216  const MathMatrix<3, worldDim> vJT[],
217  const size_t numIP)
218  {
219  getImpl().template evaluate<3>(vValue,vGlobIP,pElem,vCornerCoords,vLocIP,vJT,numIP);
220  }
222 
223  protected:
225  TImpl& getImpl() {return static_cast<TImpl&>(*this);}
226 
228  const TImpl& getImpl() const {return static_cast<const TImpl&>(*this);}
229 };
230 
233 // Generic Volume Integration Routine
236 
238 
259 template <int WorldDim, int dim, typename TConstIterator>
260 number Integrate(TConstIterator iterBegin,
261  TConstIterator iterEnd,
263  IIntegrand<number, WorldDim>& integrand,
264  int quadOrder, std::string quadType,
267  *paaElemContribs = NULL
268  )
269 {
270  PROFILE_FUNC();
271 
272 // reset the result
273  number integral = 0.0;
274 
275 // note: this iterator is for the base elements, e.g. Face and not
276 // for the special type, e.g. Triangle, Quadrilateral
277  TConstIterator iter = iterBegin;
278 
279 // this is the base element type (e.g. Face). This is the type when the
280 // iterators above are dereferenciated.
281  typedef typename domain_traits<dim>::grid_base_object grid_base_object;
282 
283 // get quad type
284  if(quadType.empty()) quadType = "best";
285  QuadType type = GetQuadratureType(quadType);
286 
287 // accessing without dereferencing a pointer first is simpler...
289  if(paaElemContribs)
290  aaElemContribs = *paaElemContribs;
291 
292 // We'll reuse containers to avoid reallocations
293  std::vector<MathVector<WorldDim> > vCorner;
294  std::vector<MathVector<WorldDim> > vGlobIP;
295  std::vector<MathMatrix<dim, WorldDim> > vJT;
296  std::vector<number> vValue;
297 
298 // iterate over all elements
299  for(; iter != iterEnd; ++iter)
300  {
301  // get element
302  grid_base_object* pElem = *iter;
303 
304  // get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
305  ReferenceObjectID roid = (ReferenceObjectID) pElem->reference_object_id();
306 
307  // get quadrature Rule for reference object id and order
308  try{
309  const QuadratureRule<dim>& rQuadRule
310  = QuadratureRuleProvider<dim>::get(roid, quadOrder, type);
311 
312  // get reference element mapping by reference object id
314  = ReferenceMappingProvider::get<dim, WorldDim>(roid);
315 
316  // number of integration points
317  const size_t numIP = rQuadRule.size();
318 
319  // get all corner coordinates
320  CollectCornerCoordinates(vCorner, *pElem, aaPos, true);
321 
322  // update the reference mapping for the corners
323  mapping.update(&vCorner[0]);
324 
325  // compute global integration points
326  vGlobIP.resize(numIP);
327  mapping.local_to_global(&(vGlobIP[0]), rQuadRule.points(), numIP);
328 
329  // compute transformation matrices
330  vJT.resize(numIP);
331  mapping.jacobian_transposed(&(vJT[0]), rQuadRule.points(), numIP);
332 
333  // compute integrand values at integration points
334  vValue.resize(numIP);
335  try
336  {
337  integrand.values(&(vValue[0]), &(vGlobIP[0]),
338  pElem, &vCorner[0], rQuadRule.points(),
339  &(vJT[0]),
340  numIP);
341  }
342  UG_CATCH_THROW("Unable to compute values of integrand at integration point.");
343 
344  // reset contribution of this element
345  number intValElem = 0;
346 
347  // loop integration points
348  for(size_t ip = 0; ip < numIP; ++ip)
349  {
350  // get quadrature weight
351  const number weightIP = rQuadRule.weight(ip);
352 
353  // get determinate of mapping
354  const number det = SqrtGramDeterminant(vJT[ip]);
355 
356  // add contribution of integration point
357  intValElem += vValue[ip] * weightIP * det;
358  }
359 
360  // add to global sum
361  integral += intValElem;
362  if(aaElemContribs.valid())
363  aaElemContribs[pElem] = intValElem;
364 
365  }UG_CATCH_THROW("SumValuesOnElems failed.");
366  } // end elem
367 
368 // return the summed integral contributions of all elements
369  return integral;
370 }
371 
372 template <typename TGridFunction, int dim>
374  TGridFunction& spGridFct,
375  int si, int quadOrder, std::string quadType)
376 {
377 // integrate elements of subset
378  typedef typename TGridFunction::template dim_traits<dim>::grid_base_object grid_base_object;
379  typedef typename TGridFunction::template dim_traits<dim>::const_iterator const_iterator;
380 
381  spIntegrand.set_subset(si);
382 
383  return Integrate<TGridFunction::dim,dim,const_iterator>
384  (spGridFct.template begin<grid_base_object>(si),
385  spGridFct.template end<grid_base_object>(si),
386  spGridFct.domain()->position_accessor(),
387  spIntegrand,
388  quadOrder, quadType);
389 }
390 
391 
392 template <typename TGridFunction>
394  TGridFunction& spGridFct,
395  const char* subsets, int quadOrder,
396  std::string quadType = std::string())
397 {
398 // world dimensions
399  static const int dim = TGridFunction::dim;
400 
401 // read subsets
402  SubsetGroup ssGrp(spGridFct.domain()->subset_handler());
403  if(subsets != NULL)
404  {
405  ssGrp.add(TokenizeString(subsets));
406  UG_COND_THROW(!SameDimensionsInAllSubsets(ssGrp), "IntegrateSubsets: Subsets '"<<subsets<<"' do not have same dimension."
407  "Cannot integrate on subsets of different dimensions.");
408  UG_LOG("IntegrateSubsets for subsets="<<subsets<<"\n");
409  }
410  else
411  {
412  // add all subsets and remove lower dim subsets afterwards
413  ssGrp.add_all();
414  RemoveLowerDimSubsets(ssGrp);
415  }
416 
417 // reset value
418  number value = 0;
419 
420 // loop subsets
421  for(size_t i = 0; i < ssGrp.size(); ++i)
422  {
423  // get subset index
424  const int si = ssGrp[i];
425 
426  // check dimension
427  UG_COND_THROW(ssGrp.dim(i) > dim, "IntegrateSubsets: Dimension of subset is "<<ssGrp.dim(i)<<", but "
428  " world dimension is "<<dim<<". Cannot integrate this.");
429 
430  // integrate elements of subset
431  try{
432  switch(ssGrp.dim(i))
433  {
434  case DIM_SUBSET_EMPTY_GRID: break;
435  case 1: value += IntegrateSubset<TGridFunction, 1>(spIntegrand, spGridFct, si, quadOrder, quadType); break;
436  case 2: value += IntegrateSubset<TGridFunction, 2>(spIntegrand, spGridFct, si, quadOrder, quadType); break;
437  case 3: value += IntegrateSubset<TGridFunction, 3>(spIntegrand, spGridFct, si, quadOrder, quadType); break;
438  default: UG_THROW("IntegrateSubsets: Dimension "<<ssGrp.dim(i)<<" not supported. "
439  " World dimension is "<<dim<<".");
440  }
441  }
442  UG_CATCH_THROW("IntegrateSubsets: Integration failed on subset "<<si);
443  }
444 
445 #ifdef UG_PARALLEL
446  // sum over processes
447  if(pcl::NumProcs() > 1)
448  {
450  number local = value;
451  com.allreduce(&local, &value, 1, PCL_DT_DOUBLE, PCL_RO_SUM);
452  }
453 #endif
454 
455 // return the result
456  return value;
457 }
458 
459 
461 // UserData Integrand
463 
465 template <typename TData, typename TGridFunction>
467  : public StdIntegrand<TData, TGridFunction::dim, UserDataIntegrand<TData, TGridFunction> >
468 {
469  public:
470  // world dimension of grid function
471  static const int worldDim = TGridFunction::dim;
472 
473  // data type
474  typedef TData data_type;
475 
476  private:
477  // data to integrate
479 
480  // grid function
481  TGridFunction* m_spGridFct;
482 
483  // time
485 
486  public:
489  TGridFunction* spGridFct,
490  number time)
491  : m_spData(spData), m_spGridFct(spGridFct), m_time(time)
492  {
493  m_spData->set_function_pattern(spGridFct->function_pattern());
494  };
495 
498  number time)
499  : m_spData(spData), m_spGridFct(NULL), m_time(time)
500  {
501  UG_COND_THROW(m_spData->requires_grid_fct(),
502  "UserDataIntegrand: Missing GridFunction, but data requires grid function.");
503  };
504 
506  template <int elemDim>
507  void evaluate(TData vValue[],
508  const MathVector<worldDim> vGlobIP[],
509  GridObject* pElem,
510  const MathVector<worldDim> vCornerCoords[],
511  const MathVector<elemDim> vLocIP[],
512  const MathMatrix<elemDim, worldDim> vJT[],
513  const size_t numIP)
514  {
515  // get local solution if needed
516  if(m_spData->requires_grid_fct())
517  {
518  // create storage
519  LocalIndices ind;
520  LocalVector u;
521 
522  // get global indices
523  m_spGridFct->indices(pElem, ind);
524 
525  // adapt local algebra
526  u.resize(ind);
527 
528  // read local values of u
530 
531  // compute data
532  try{
533  (*m_spData)(vValue, vGlobIP, m_time, this->m_si, pElem,
534  vCornerCoords, vLocIP, numIP, &u, &vJT[0]);
535  }
536  UG_CATCH_THROW("UserDataIntegrand: Cannot evaluate data.");
537  }
538  else
539  {
540  // compute data
541  try{
542  (*m_spData)(vValue, vGlobIP, m_time, this->m_si, numIP);
543  }
544  UG_CATCH_THROW("UserDataIntegrand: Cannot evaluate data.");
545  }
546 
547  }
548 };
549 
550 
551 
552 
554 template <typename TData, typename TGridFunction>
556  : public StdIntegrand<number, TGridFunction::dim, UserDataIntegrandSq<TData, TGridFunction> >
557 {
558  public:
559  // world dimension of grid function
560  static const int worldDim = TGridFunction::dim;
561 
562  // data type
563  typedef TData data_type;
564 
565  private:
566  // data to integrate
568 
569  // grid function
570  const TGridFunction* m_pGridFct;
571 
572  // time
574 
575  public:
578  const TGridFunction* pGridFct,
579  number time)
580  : m_spData(spData), m_pGridFct(pGridFct), m_time(time)
581  {
582  m_spData->set_function_pattern(pGridFct->function_pattern());
583  };
584 
587  number time)
588  : m_spData(spData), m_pGridFct(NULL), m_time(time)
589  {
590  if(m_spData->requires_grid_fct())
591  UG_THROW("UserDataIntegrand: Missing GridFunction, but "
592  " data requires grid function.")
593  };
594 
595 
597  template <int elemDim>
598  void evaluate(number vValue[],
599  const MathVector<worldDim> vGlobIP[],
600  GridObject* pElem,
601  const MathVector<worldDim> vCornerCoords[],
602  const MathVector<elemDim> vLocIP[],
603  const MathMatrix<elemDim, worldDim> vJT[],
604  const size_t numIP)
605  {
606 
607  std::vector<TData> tmpValues(numIP);
608 
609  // get local solution if needed
610  if(m_spData->requires_grid_fct())
611  {
612  UG_ASSERT(m_pGridFct!=NULL, "Error: Requires valid pointer!")
613  // create storage
614  LocalIndices ind;
615  LocalVector u;
616 
617  // get global indices
618  m_pGridFct->indices(pElem, ind);
619 
620  // adapt local algebra
621  u.resize(ind);
622 
623  // read local values of u
625 
626  // compute data
627  try{
628  (*m_spData)(&tmpValues.front(), vGlobIP, m_time, this->m_si, pElem,
629  vCornerCoords, vLocIP, numIP, &u, &vJT[0]);
630  }
631  UG_CATCH_THROW("UserDataIntegrand: Cannot evaluate data.");
632  }
633  else
634  {
635  // compute data
636  try{
637  (*m_spData)(&tmpValues.front(), vGlobIP, m_time, this->m_si, numIP);
638  }
639  UG_CATCH_THROW("UserDataIntegrand: Cannot evaluate data.");
640  }
641 
642  for (size_t i=0; i<numIP; ++i)
643  {
644  vValue[i]=inner_prod(tmpValues[i], tmpValues[i]);
645  }
646 
647  }
648  protected:
649 
650  number inner_prod(const number &d1, const number &d2)
651  {return d1*d2;}
652 
654  {return VecDot(d1, d2);}
655 
656  template<typename T>
657  number inner_prod(const T &d1, const T &d2)
658  { UG_ASSERT(0, "NOT IMPLEMENTED"); return 0.0;}
659 };
660 
661 
662 
663 
665 template <typename TData, typename TGridFunction>
667  : public StdIntegrand<number, TGridFunction::dim, UserDataDistIntegrandSq<TData, TGridFunction> >
668 {
669  public:
671  static const int worldDim = TGridFunction::dim;
672  // typedef typename L2Integrand<TGridFunction>::weight_type weight_type;
673 
674  protected:
676  const int m_fineTopLevel;
677 
679  const int m_coarseTopLevel;
680 
683 
684 
685 
687  // ConstSmartPtr<weight_type> m_spWeight;
688 
689  double m_time;
690  public:
691 
693  UserDataDistIntegrandSq(SmartPtr<UserData<TData, worldDim> > spData, TGridFunction& fineGridFct, size_t fineCmp,
694  TGridFunction& coarseGridFct, size_t coarseCmp)
695  : m_fineData(fineGridFct, fineCmp), m_fineTopLevel(fineGridFct.dof_distribution()->grid_level().level()),
696  m_coarseData(coarseGridFct, coarseCmp), m_coarseTopLevel(coarseGridFct.dof_distribution()->grid_level().level()),
697  m_spMG(m_fineData.domain()->grid()), m_spData(spData), m_time(0.0) /*, m_spWeight(make_sp(new ConstUserNumber<TGridFunction::dim>(1.0)))*/
698  {
700  UG_THROW("UserDataDistIntegrandSq: fine and top level inverted.");
701 
702  if(m_fineData.domain().get() != m_coarseData.domain().get())
703  UG_THROW("UserDataDistIntegrandSq: grid functions defined on different domains.");
704  };
705 
707 
709  virtual void set_subset(int si)
710  {
711  if(!m_fineData.is_def_in_subset(si))
712  UG_THROW("UserDataDistIntegrandSq: Grid function component"
713  <<m_fineData.fct()<<" not defined on subset "<<si);
714  if(!m_coarseData.is_def_in_subset(si))
715  UG_THROW("UserDataDistIntegrandSq: Grid function component"
716  <<m_coarseData.fct()<<" not defined on subset "<<si);
718  }
719 
721  template <int elemDim>
722  void evaluate(number vValue[],
723  const MathVector<worldDim> vGlobIP[],
724  GridObject* pFineElem,
725  const MathVector<worldDim> vCornerCoords[],
726  const MathVector<elemDim> vFineLocIP[],
727  const MathMatrix<elemDim, worldDim> vJT[],
728  const size_t numIP)
729  {
730 
731 
732  // must return 0.0, if m_spData is independent of grid functions
733  if(!m_spData->requires_grid_fct()) {
734  for (size_t i=0; i<numIP; ++i) { vValue[i]=0.0; }
735  return;
736  }
737 
738  // get coarse element
739  GridObject* pCoarseElem = pFineElem;
741  int parentLevel = m_spMG->get_level(pCoarseElem);
742  while(parentLevel > m_coarseTopLevel){
743  pCoarseElem = m_spMG->get_parent(pCoarseElem);
744  parentLevel = m_spMG->get_level(pCoarseElem);
745  }
746  }
747 
748  // get corner coordinates
749  typedef typename TGridFunction::template dim_traits<elemDim>::grid_base_object TElem;
750  std::vector<MathVector<worldDim> > vCornerCoarse;
751  CollectCornerCoordinates(vCornerCoarse, *static_cast<TElem*>(pCoarseElem), *m_coarseData.domain());
752 
753  // get Reference Mapping
754  const ReferenceObjectID coarseROID = pCoarseElem->reference_object_id();
756  = ReferenceMappingProvider::get<elemDim, worldDim>(coarseROID, vCornerCoarse);
757 
758  std::vector<MathVector<elemDim> > vCoarseLocIP;
759  vCoarseLocIP.resize(numIP);
760  for(size_t ip = 0; ip < vCoarseLocIP.size(); ++ip) VecSet(vCoarseLocIP[ip], 0.0);
761  map.global_to_local(&vCoarseLocIP[0], vGlobIP, numIP);
762 
763  // element weights
764  /* typedef typename weight_type::data_type ipdata_type;
765  std::vector<ipdata_type> fineElemWeights(numIP, 1.0);
766  UG_ASSERT(m_spWeight.valid(), "L2DistIntegrand::evaluate requires valid weights! ");
767  (*m_spWeight)(&fineElemWeights[0], vFineGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), numIP);*/
768 
769 
770  // get trial space
771  /* const LocalShapeFunctionSet<elemDim>& rFineLSFS =
772  LocalFiniteElementProvider::get<elemDim>(fineROID, m_fineData.id());
773  const LocalShapeFunctionSet<elemDim>& rCoarseLSFS =
774  LocalFiniteElementProvider::get<elemDim>(coarseROID, m_coarseData.id());*/
775 
776  // get multiindices of element
777  /*std::vector<DoFIndex> vFineMI, vCoarseMI;
778  m_fineData.dof_indices(pFineElem, vFineMI);
779  m_coarseData.dof_indices(pCoarseElem, vCoarseMI);*/
780 
781  TData fineValues[numIP];
782  TData coarseValues[numIP];
783 
784 
785 
786  // compute coarse data
787  try{
788  LocalVector uCoarse;
789  LocalIndices indCoarse;
790 
791  m_coarseData.grid_function().indices(pCoarseElem, indCoarse);
792  uCoarse.resize(indCoarse);
793  GetLocalVector(uCoarse, m_coarseData.grid_function());
794 
795  (*m_spData)(coarseValues, vGlobIP, m_time, this->m_si, pCoarseElem,
796  &vCornerCoarse[0], &vCoarseLocIP[0], numIP, &uCoarse, &vJT[0]);
797  } UG_CATCH_THROW("UserDataDistIntegrandSq: Cannot evaluate coarse data.");
798 
799 
800  // compute fine data
801  try{
802  LocalVector uFine;
803  LocalIndices indFine;
804 
805  m_fineData.grid_function().indices(pFineElem, indFine);
806  uFine.resize(indFine);
807  GetLocalVector(uFine, m_fineData.grid_function());
808 
809  (*m_spData)(fineValues, vGlobIP, m_time, this->m_si, pFineElem,
810  vCornerCoords, vFineLocIP, numIP, &uFine, &vJT[0]);
811  } UG_CATCH_THROW("UserDataDistIntegrandSq: Cannot evaluate fine data.");
812 
813  // loop all integration points
814  for(size_t ip = 0; ip < numIP; ++ip)
815  {
816  vValue[ip] = inner_dist2(fineValues[ip], coarseValues[ip]);
817  }
818 
819  }
820 
821 
822  protected:
823 
824  number inner_prod(const number &d1, const number &d2)
825  {return d1*d2;}
826 
828  {return VecDot(d1, d2);}
829 
830  template<typename T>
831  number inner_prod(const T &d1, const T &d2)
832  { UG_ASSERT(0, "NOT IMPLEMENTED"); return 0.0;}
833 
834 
835 
836  number inner_dist2(const number &v1, const number &v2)
837  { return (v1-v2)*(v1-v2); }
838 
840  { return VecDistanceSq(v1, v2); }
841 
842  template<typename T>
843  number inner_dist2(const T &d1, const T &d2)
844  { UG_ASSERT(0, "NOT IMPLEMENTED"); return 0.0;}
845 
846 };
847 
848 
851 // Volume Integrand implementations
854 
855 template <typename TGridFunction>
857  TGridFunction& spGridFct,
858  const char* subsets, number time,
859  int quadOrder, std::string quadType)
860 {
861  UserDataIntegrand<number, TGridFunction> spIntegrand(spData, &spGridFct, time);
862  return IntegrateSubsets(spIntegrand, spGridFct, subsets, quadOrder, quadType);
863 }
864 
865 template <typename TGridFunction>
867  const char* subsets, number time, int quadOrder, std::string quadType)
868 { return Integral(spData, *spGridFct, subsets, time, quadOrder, quadType); }
869 
870 template <typename TGridFunction>
871 number Integral(SmartPtr<UserData<number, TGridFunction::dim> > spData, SmartPtr<TGridFunction> spGridFct,const char* subsets,number time, int order)
872 {return Integral(spData, spGridFct, subsets, time, order, "best");}
873 
874 template <typename TGridFunction>
876 {return Integral(spData, spGridFct, subsets, time, 1, "best");}
877 
878 template <typename TGridFunction>
880 {return Integral(spData, spGridFct, NULL, time, 1, "best");}
881 
882 template <typename TGridFunction>
884 {return Integral(spData, spGridFct, subsets, 0.0, 1, "best");}
885 
886 template <typename TGridFunction>
888 {return Integral(spData, spGridFct, NULL, 0.0, 1, "best");}
889 
891 // const data
893 
894 template <typename TGridFunction>
896  const char* subsets,
897  number time, int quadOrder)
898 {
899  static const int dim = TGridFunction::dim;
901  make_sp(new ConstUserNumber<dim>(val));
902  return Integral(sp, spGridFct, subsets, time, quadOrder);
903 }
904 
905 template <typename TGridFunction>
906 number Integral(number val, SmartPtr<TGridFunction> spGridFct,const char* subsets,number time)
907 {return Integral(val, spGridFct, subsets, time, 1);}
908 
909 template <typename TGridFunction>
911 {return Integral(val, spGridFct, NULL, time, 1);}
912 
913 template <typename TGridFunction>
914 number Integral(number val, SmartPtr<TGridFunction> spGridFct,const char* subsets)
915 {return Integral(val, spGridFct, subsets, 0.0, 1);}
916 
917 template <typename TGridFunction>
919 {return Integral(val, spGridFct, NULL, 0.0, 1);}
920 
922 // lua data
924 
925 #ifdef UG_FOR_LUA
926 template <typename TGridFunction>
927 number Integral(const char* luaFct,
928  SmartPtr<TGridFunction> spGridFct,
929  const char* subsets, number time,
930  int quadOrder, std::string quadType)
931 {
932  static const int dim = TGridFunction::dim;
935  return Integral(sp, *spGridFct, subsets, time, quadOrder, quadType);
936 }
937 
938 template <typename TGridFunction>
939 number Integral(const char* luaFct, SmartPtr<TGridFunction> spGridFct,const char* subsets,number time, int quadOrder)
940 {return Integral(luaFct, spGridFct, subsets, time, quadOrder, "best");}
941 
942 template <typename TGridFunction>
943 number Integral(const char* luaFct, SmartPtr<TGridFunction> spGridFct,const char* subsets,number time)
944 {return Integral(luaFct, spGridFct, subsets, time, 1, "best");}
945 
946 template <typename TGridFunction>
947 number Integral(const char* luaFct, SmartPtr<TGridFunction> spGridFct,number time)
948 {return Integral(luaFct, spGridFct, NULL, time, 1, "best");}
949 
950 template <typename TGridFunction>
951 number Integral(const char* luaFct, SmartPtr<TGridFunction> spGridFct,const char* subsets)
952 {return Integral(luaFct, spGridFct, subsets, 0.0, 1, "best");}
953 
954 template <typename TGridFunction>
955 number Integral(const char* luaFct, SmartPtr<TGridFunction> spGridFct)
956 {return Integral(luaFct, spGridFct, NULL, 0.0, 1, "best");}
957 
958 #endif
959 
960 
961 
962 template <typename TGridFunction>
964  : public StdIntegrand<number, TGridFunction::dim, MaximumDistIntegrand<TGridFunction> >
965 {
966  public:
968  static const int worldDim = TGridFunction::dim;
969 
970  protected:
972 
973  double m_max, m_min;
974 
975  public:
977  MaximumDistIntegrand(TGridFunction& gridFct, size_t cmp)
978 
979  : m_scalarData(gridFct, cmp),
980  m_max(-std::numeric_limits<float>::infinity()),
981  m_min(std::numeric_limits<float>::infinity())
982  {};
983 
984  virtual ~MaximumDistIntegrand() {};
985 
987  virtual void set_subset(int si)
988  {
989  UG_COND_THROW(!m_scalarData.is_def_in_subset(si), "L2ErrorIntegrand: Grid function component" <<
990  m_scalarData.fct()<<" not defined on subset "<<si);
992  }
993 
994  void reset()
995  {
996  m_min = std::numeric_limits<double>::infinity();
997  m_max = -std::numeric_limits<double>::infinity();
998  }
999 
1000  double min() { return m_min; }
1001  double max() { return m_max; }
1002 
1004  template <int elemDim>
1005  void evaluate(number vValue[],
1006  const MathVector<worldDim> vGlobIP[],
1007  GridObject* pElem,
1008  const MathVector<worldDim> vCornerCoords[],
1009  const MathVector<elemDim> vLocIP[],
1010  const MathMatrix<elemDim, worldDim> vJT[],
1011  const size_t numIP)
1012  {
1013  // get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
1014  const ReferenceObjectID roid = pElem->reference_object_id();
1015 
1016  try{
1017  // get trial space
1018  const LocalShapeFunctionSet<elemDim>& rTrialSpace =
1019  LocalFiniteElementProvider::get<elemDim>(roid, m_scalarData.id());
1020 
1021  // number of dofs on element
1022  const size_t num_sh = rTrialSpace.num_sh();
1023 
1024  // get multiindices of element
1025  std::vector<DoFIndex> ind; // aux. index array
1026  m_scalarData.dof_indices(pElem, ind);
1027 
1028  // check multi indices
1029  UG_COND_THROW(ind.size() != num_sh, "L2ErrorIntegrand::evaluate: Wrong number of multi indices.");
1030 
1031  // evaluate function in corners.
1032  for(size_t sh = 0; sh < num_sh; ++sh)
1033  {
1034  // get value at shape point (e.g. corner for P1 fct)
1035  const number val = DoFRef(m_scalarData.grid_function(), ind[sh]);
1036 
1037  m_max = std::max(m_max, val);
1038  m_min = std::min(m_min, val);
1039  }
1040 
1041 
1042  } UG_CATCH_THROW("L2ErrorIntegrand::evaluate: trial space missing.");
1043  }
1044 };
1045 
1046 
1047 template <typename TGridFunction>
1048 number GetMinimum(TGridFunction &gridFct, const char* cmp, const char* subsets)
1049 {
1050  // get function id of name & check that function exists
1051  const size_t fct = gridFct.fct_id_by_name(cmp);
1052  UG_COND_THROW(fct >= gridFct.num_fct(),
1053  "L2Error: Function space does not contain a function with name " << cmp << ".");
1054 
1055  // Find minimum.
1056  MaximumDistIntegrand<TGridFunction> spIntegrand(gridFct, fct);
1057  IntegrateSubsets(spIntegrand, gridFct, subsets, 2);
1058  return spIntegrand.min();
1059 }
1060 
1061 template <typename TGridFunction>
1062 number Minimum(SmartPtr<TGridFunction> spGridFct, const char* cmp, const char* subsets)
1063 { return GetMinimum(*spGridFct, cmp, subsets); }
1064 
1065 
1067 // L2 Error Integrand
1069 
1070 template <typename TGridFunction>
1072  : public StdIntegrand<number, TGridFunction::dim, L2ErrorIntegrand<TGridFunction> >
1073 {
1074  public:
1076  static const int worldDim = TGridFunction::dim;
1077 
1078  private:
1080 
1083 
1086 
1087  public:
1090  TGridFunction& gridFct, size_t cmp,
1091  number time)
1092  : m_scalarData(gridFct, cmp),
1093  m_spExactSolution(spExactSol), m_time(time)
1094  {};
1095 
1096  virtual ~L2ErrorIntegrand() {};
1097 
1099  virtual void set_subset(int si)
1100  {
1101  if(!m_scalarData.is_def_in_subset(si))
1102  UG_THROW("L2ErrorIntegrand: Grid function component"
1103  <<m_scalarData.fct()<<" not defined on subset "<<si);
1105  }
1106 
1108  template <int elemDim>
1109  void evaluate(number vValue[],
1110  const MathVector<worldDim> vGlobIP[],
1111  GridObject* pElem,
1112  const MathVector<worldDim> vCornerCoords[],
1113  const MathVector<elemDim> vLocIP[],
1114  const MathMatrix<elemDim, worldDim> vJT[],
1115  const size_t numIP)
1116  {
1117  // get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
1118  const ReferenceObjectID roid = pElem->reference_object_id();
1119 
1120  try{
1121  // get trial space
1122  const LocalShapeFunctionSet<elemDim>& rTrialSpace =
1123  LocalFiniteElementProvider::get<elemDim>(roid, m_scalarData.id());
1124 
1125  // number of dofs on element
1126  const size_t num_sh = rTrialSpace.num_sh();
1127 
1128  // get multiindices of element
1129  std::vector<DoFIndex> ind; // aux. index array
1130  m_scalarData.dof_indices(pElem, ind);
1131 
1132  // check multi indices
1133  if(ind.size() != num_sh)
1134  UG_THROW("L2ErrorIntegrand::evaluate: Wrong number of"
1135  " multi indices.");
1136 
1137  // loop all integration points
1138  for(size_t ip = 0; ip < numIP; ++ip)
1139  {
1140  // compute exact solution at integration point
1141  number exactSolIP;
1142  (*m_spExactSolution)(exactSolIP, vGlobIP[ip], m_time, this->subset());
1143 
1144  // compute approximated solution at integration point
1145  number approxSolIP = 0.0;
1146  for(size_t sh = 0; sh < num_sh; ++sh)
1147  {
1148  // get value at shape point (e.g. corner for P1 fct)
1149  const number valSH = DoFRef(m_scalarData.grid_function(), ind[sh]);
1150 
1151  // add shape fct at ip * value at shape
1152  approxSolIP += valSH * rTrialSpace.shape(sh, vLocIP[ip]);
1153  }
1154 
1155  // get squared of difference
1156  vValue[ip] = (exactSolIP - approxSolIP);
1157  vValue[ip] *= vValue[ip];
1158  }
1159 
1160  }
1161  UG_CATCH_THROW("L2ErrorIntegrand::evaluate: trial space missing.");
1162  }
1163 };
1164 
1165 
1166 
1168 // L2 Error Integrand
1170 
1172 
1184 template <typename TGridFunction>
1186  TGridFunction& gridFct, const char* cmp,
1187  number time, int quadOrder, const char* subsets)
1188 {
1189 // get function id of name
1190  const size_t fct = gridFct.fct_id_by_name(cmp);
1191 
1192 // check that function exists
1193  UG_COND_THROW(fct >= gridFct.num_fct(),
1194  "L2Error: Function space does not contain a function with name " << cmp << ".");
1195 
1196  L2ErrorIntegrand<TGridFunction> spIntegrand(spExactSol, gridFct, fct, time);
1197  return sqrt(IntegrateSubsets(spIntegrand, gridFct, subsets, quadOrder));
1198 }
1199 
1200 template <typename TGridFunction>
1202  SmartPtr<TGridFunction> spGridFct, const char* cmp,
1203  number time, int quadOrder, const char* subsets)
1204 { return L2Error(spExactSol, *spGridFct, cmp, time, quadOrder, subsets); }
1205 
1206 template <typename TGridFunction>
1208  SmartPtr<TGridFunction> spGridFct, const char* cmp,
1209  number time, int quadOrder)
1210 { return L2Error(spExactSol, *spGridFct, cmp, time, quadOrder, NULL); }
1211 
1212 
1213 
1214 
1215 #ifdef UG_FOR_LUA
1216 template <typename TGridFunction>
1217 number L2Error(const char* ExactSol,
1218  SmartPtr<TGridFunction> spGridFct, const char* cmp,
1219  number time, int quadOrder, const char* subsets)
1220 {
1222  = make_sp(new LuaUserData<number, TGridFunction::domain_type::dim>(ExactSol));
1223  return L2Error(spExactSol, spGridFct, cmp, time, quadOrder, subsets);
1224 }
1225 
1226 template <typename TGridFunction>
1227 number L2Error(const char* ExactSol,
1228  SmartPtr<TGridFunction> spGridFct, const char* cmp,
1229  number time, int quadOrder)
1230 {
1231  return L2Error(ExactSol, spGridFct, cmp, time, quadOrder, NULL);
1232 }
1233 #endif
1234 
1235 
1236 
1237 
1239 // H1 Error Integrand
1241 
1242 template <typename TGridFunction>
1244  : public StdIntegrand<number, TGridFunction::dim, H1ErrorIntegrand<TGridFunction> >
1245 {
1246  public:
1248  static const int worldDim = TGridFunction::dim;
1249 
1250  private:
1253 
1256 
1259 
1262 
1263  public:
1267  TGridFunction& gridFct, size_t cmp,
1268  number time)
1269  : m_scalarData (gridFct, cmp),
1270  m_spExactSolution(spExactSol),
1271  m_spExactGrad(spExactGrad),
1272  m_time(time)
1273  {}
1274 
1276  virtual void set_subset(int si)
1277  {
1278  if(!m_scalarData.is_def_in_subset(si))
1279  UG_THROW("H1Error: Grid function component"
1280  <<m_scalarData.fct()<<" not defined on subset "<<si);
1282  }
1283 
1285  template <int elemDim>
1286  void evaluate(number vValue[],
1287  const MathVector<worldDim> vGlobIP[],
1288  GridObject* pElem,
1289  const MathVector<worldDim> vCornerCoords[],
1290  const MathVector<elemDim> vLocIP[],
1291  const MathMatrix<elemDim, worldDim> vJT[],
1292  const size_t numIP)
1293  {
1294  // get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
1295  const ReferenceObjectID roid = pElem->reference_object_id();
1296 
1297  try{
1298  // get trial space
1299  const LocalShapeFunctionSet<elemDim>& rTrialSpace =
1300  LocalFiniteElementProvider::get<elemDim>(roid, m_scalarData.id());
1301 
1302  // number of dofs on element
1303  const size_t num_sh = rTrialSpace.num_sh();
1304 
1305  // get multiindices of element
1306  std::vector<DoFIndex> ind; // aux. index array
1307  m_scalarData.dof_indices(pElem, ind);
1308 
1309  // check multi indices
1310  if(ind.size() != num_sh)
1311  UG_THROW("H1ErrorIntegrand::evaluate: Wrong number of"
1312  " multi indices.");
1313 
1314  // loop all integration points
1315  std::vector<MathVector<elemDim> > vLocGradient(num_sh);
1316  for(size_t ip = 0; ip < numIP; ++ip)
1317  {
1318  // compute exact solution at integration point
1319  number exactSolIP;
1320  (*m_spExactSolution)(exactSolIP, vGlobIP[ip], m_time, this->subset());
1321 
1322  // compute exact gradient at integration point
1323  MathVector<worldDim> exactGradIP;
1324  (*m_spExactGrad)(exactGradIP, vGlobIP[ip], m_time, this->subset());
1325 
1326  // compute shape gradients at ip
1327  rTrialSpace.grads(&vLocGradient[0], vLocIP[ip]);
1328 
1329  // compute approximated solution at integration point
1330  number approxSolIP = 0.0;
1331  MathVector<elemDim> locTmp; VecSet(locTmp, 0.0);
1332  for(size_t sh = 0; sh < num_sh; ++sh)
1333  {
1334  // get value at shape point (e.g. corner for P1 fct)
1335  const number valSH = DoFRef(m_scalarData.grid_function(), ind[sh]);
1336 
1337  // add shape fct at ip * value at shape
1338  approxSolIP += valSH * rTrialSpace.shape(sh, vLocIP[ip]);
1339 
1340  // add gradient at ip
1341  VecScaleAppend(locTmp, valSH, vLocGradient[sh]);
1342  }
1343 
1344  // compute global gradient
1345  MathVector<worldDim> approxGradIP;
1347  Inverse(JTInv, vJT[ip]);
1348  MatVecMult(approxGradIP, JTInv, locTmp);
1349 
1350  // get squared of difference
1351  vValue[ip] = (exactSolIP - approxSolIP) * (exactSolIP - approxSolIP);
1352  vValue[ip] += VecDistanceSq(approxGradIP, exactGradIP);
1353  }
1354 
1355  }
1356  UG_CATCH_THROW("H1ErrorIntegrand::evaluate: trial space missing.");
1357  }
1358 };
1359 
1361 
1374 template <typename TGridFunction>
1377  SmartPtr<TGridFunction> spGridFct, const char* cmp,
1378  number time, int quadOrder, const char* subsets)
1379 {
1380 // get function id of name
1381  const size_t fct = spGridFct->fct_id_by_name(cmp);
1382 
1383 // check that function exists
1384  if(fct >= spGridFct->num_fct())
1385  UG_THROW("H1Error: Function space does not contain"
1386  " a function with name " << cmp << ".");
1387 
1388  H1ErrorIntegrand<TGridFunction> spIntegrand(spExactSol, spExactGrad, *spGridFct, fct, time);
1389  return sqrt(IntegrateSubsets(spIntegrand, *spGridFct, subsets, quadOrder));
1390 }
1391 
1392 template <typename TGridFunction>
1395  SmartPtr<TGridFunction> spGridFct, const char* cmp,
1396  number time, int quadOrder)
1397 {
1398  return H1Error(spExactSol, spExactGrad, spGridFct, cmp, time, quadOrder, NULL);
1399 }
1400 
1401 #ifdef UG_FOR_LUA
1402 template <typename TGridFunction>
1403 number H1Error(const char* ExactSol, const char* ExactGrad,
1404  SmartPtr<TGridFunction> spGridFct, const char* cmp,
1405  number time, int quadOrder, const char* subsets)
1406 {
1407  static const int dim = TGridFunction::domain_type::dim;
1408  SmartPtr<UserData<number, dim> > spExactSol
1409  = make_sp(new LuaUserData<number, dim>(ExactSol));
1410  SmartPtr<UserData<MathVector<dim>, dim> > spExactGrad
1411  = make_sp(new LuaUserData<MathVector<dim>, dim>(ExactGrad));
1412  return H1Error(spExactSol, spExactGrad, spGridFct, cmp, time, quadOrder, subsets);
1413 }
1414 
1415 template <typename TGridFunction>
1416 number H1Error(const char* ExactSol, const char* ExactGrad,
1417  SmartPtr<TGridFunction> spGridFct, const char* cmp,
1418  number time, int quadOrder)
1419 {
1420  return H1Error(ExactSol, ExactGrad, spGridFct, cmp, time, quadOrder, NULL);
1421 }
1422 #endif
1423 
1424 
1425 
1427 
1440 template <typename TDistIntegrand, typename TGridFunction>
1441 number GridFunctionDistance2(TGridFunction& spGridFct1, const char* cmp1,
1442  TGridFunction& spGridFct2, const char* cmp2,
1443  int quadOrder, const char* subsets)
1444 {
1445 // get function id of name
1446  const size_t fct1 = spGridFct1.fct_id_by_name(cmp1);
1447  const size_t fct2 = spGridFct2.fct_id_by_name(cmp2);
1448 
1449 // check that function exists
1450  if(fct1 >= spGridFct1.num_fct())
1451  UG_THROW("GridFunctionDistance: Function space does not contain"
1452  " a function with name " << cmp1 << ".");
1453  if(fct2 >= spGridFct2.num_fct())
1454  UG_THROW("GridFunctionDistance: Function space does not contain"
1455  " a function with name " << cmp2 << ".");
1456 
1457 // get top level of grid functions
1458  const int level1 = spGridFct1.dof_distribution()->grid_level().level();
1459  const int level2 = spGridFct2.dof_distribution()->grid_level().level();
1460 
1461  if(level1 > level2){
1462  // level check
1463  TDistIntegrand spIntegrand(spGridFct1, fct1, spGridFct2, fct2);
1464  return IntegrateSubsets(spIntegrand, spGridFct1, subsets, quadOrder);
1465  }else{
1466  TDistIntegrand spIntegrand(spGridFct2, fct2, spGridFct1, fct1);
1467  return IntegrateSubsets(spIntegrand, spGridFct2, subsets, quadOrder);
1468  }
1469 
1470 }
1471 
1473 template <typename TDistIntegrand, typename TGridFunction>
1474 number GridFunctionDistance2(TGridFunction& spGridFct1, const char* cmp1,
1475  TGridFunction& spGridFct2, const char* cmp2,
1476  int quadOrder, const char* subsets, ConstSmartPtr<typename TDistIntegrand::weight_type> spWeights)
1477 {
1478 // get function id of name
1479  const size_t fct1 = spGridFct1.fct_id_by_name(cmp1);
1480  const size_t fct2 = spGridFct2.fct_id_by_name(cmp2);
1481 
1482 // check that function exists
1483  if(fct1 >= spGridFct1.num_fct())
1484  UG_THROW("GridFunctionDistance: Function space does not contain"
1485  " a function with name " << cmp1 << ".");
1486  if(fct2 >= spGridFct2.num_fct())
1487  UG_THROW("GridFunctionDistance: Function space does not contain"
1488  " a function with name " << cmp2 << ".");
1489 
1490 // get top level of gridfunctions
1491  const int level1 = spGridFct1.dof_distribution()->grid_level().level();
1492  const int level2 = spGridFct2.dof_distribution()->grid_level().level();
1493 
1494  // w/ weights
1495  if(level1 > level2){
1496  TDistIntegrand spIntegrand(spGridFct1, fct1, spGridFct2, fct2, spWeights);
1497  return IntegrateSubsets(spIntegrand, spGridFct1, subsets, quadOrder);
1498  }else{
1499  TDistIntegrand spIntegrand(spGridFct2, fct2, spGridFct1, fct1, spWeights);
1500  return IntegrateSubsets(spIntegrand, spGridFct2, subsets, quadOrder);
1501  }
1502 }
1503 
1504 
1506 template <typename TDistIntegrand, typename TGridFunction>
1507 number GridFunctionDistance2(TGridFunction& spGridFct1, const char* cmp1,
1508  TGridFunction& spGridFct2, const char* cmp2,
1509  int quadOrder, const char* subsets,
1511  number distAvg12)
1512 {
1513 // get function id of name
1514  const size_t fct1 = spGridFct1.fct_id_by_name(cmp1);
1515  const size_t fct2 = spGridFct2.fct_id_by_name(cmp2);
1516 
1517 // check that function exists
1518  if(fct1 >= spGridFct1.num_fct())
1519  UG_THROW("GridFunctionDistance: Function space does not contain"
1520  " a function with name " << cmp1 << ".");
1521  if(fct2 >= spGridFct2.num_fct())
1522  UG_THROW("GridFunctionDistance: Function space does not contain"
1523  " a function with name " << cmp2 << ".");
1524 
1525 // get top level of gridfunctions
1526  const int level1 = spGridFct1.dof_distribution()->grid_level().level();
1527  const int level2 = spGridFct2.dof_distribution()->grid_level().level();
1528 
1529  // w/ weights
1530  if(level1 > level2){
1531  TDistIntegrand spIntegrand(spGridFct1, fct1, spGridFct2, fct2, spWeights, distAvg12);
1532  return IntegrateSubsets(spIntegrand, spGridFct1, subsets, quadOrder);
1533  }else{
1534  TDistIntegrand spIntegrand(spGridFct2, fct2, spGridFct1, fct1, spWeights, -distAvg12);
1535  return IntegrateSubsets(spIntegrand, spGridFct2, subsets, quadOrder);
1536  }
1537 }
1538 
1539 
1540 
1542 // L2 Integrand
1544 
1546 template <typename TGridFunction>
1548  : public StdIntegrand<number, TGridFunction::dim, L2Integrand<TGridFunction> >
1549 {
1550  public:
1551  // world dimension of grid function
1552  static const int worldDim = TGridFunction::dim;
1554 
1555  protected:
1556  // grid function data
1558 
1561 
1562  public:
1564  L2Integrand(TGridFunction& spGridFct, size_t cmp)
1565  : m_scalarData(spGridFct, cmp), m_spWeight(make_sp(new ConstUserNumber<worldDim>(1.0)))
1566  {};
1567 
1568  L2Integrand(TGridFunction& spGridFct, size_t cmp, ConstSmartPtr<weight_type> spWeight)
1569  : m_scalarData(spGridFct, cmp), m_spWeight(spWeight)
1570  {};
1571 
1573  virtual ~L2Integrand() {};
1574 
1576  virtual void set_subset(int si)
1577  {
1578  if(!m_scalarData.is_def_in_subset(si))
1579  UG_THROW("L2ErrorIntegrand: Grid function component" <<m_scalarData.fct() <<" not defined on subset "<<si);
1581  }
1582 
1584  template <int elemDim>
1585  void evaluate(number vValue[],
1586  const MathVector<worldDim> vGlobIP[],
1587  GridObject* pElem,
1588  const MathVector<worldDim> vCornerCoords[],
1589  const MathVector<elemDim> vLocIP[],
1590  const MathMatrix<elemDim, worldDim> vJT[],
1591  const size_t numIP)
1592  {
1593  // get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
1595 
1596  // element weights
1597  typedef typename weight_type::data_type ipdata_type;
1598  std::vector<ipdata_type> locElemWeights(numIP, 1.0);
1599  UG_ASSERT(m_spWeight.valid(), "L2Integrand::evaluate requires valid weights!");
1600  (*m_spWeight)(&locElemWeights[0], vGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), numIP);
1601 
1602  try{
1603  // get trial space
1604  const LocalShapeFunctionSet<elemDim>& rTrialSpace =
1605  LocalFiniteElementProvider::get<elemDim>(roid, m_scalarData.id());
1606 
1607  // number of dofs on element
1608  const size_t num_sh = rTrialSpace.num_sh();
1609 
1610  // get multiindices of element
1611  std::vector<DoFIndex> ind; // aux. index array
1612  m_scalarData.dof_indices(pElem, ind);
1613 
1614  // check multi indices
1615  if(ind.size() != num_sh)
1616  UG_THROW("L2Integrand::evaluate: Wrong number of multi indices.");
1617 
1618  // loop all integration points
1619  for(size_t ip = 0; ip < numIP; ++ip)
1620  {
1621 
1622  // compute approximated solution at integration point
1623  number approxSolIP = 0.0;
1624  for(size_t sh = 0; sh < num_sh; ++sh)
1625  {
1626  // get value at shape point (e.g. corner for P1 fct)
1627  // and add shape fct at ip * value at shape
1628  const number valSH = DoFRef(m_scalarData.grid_function(), ind[sh]);
1629  approxSolIP += valSH * rTrialSpace.shape(sh, vLocIP[ip]);
1630  }
1631 
1632  // get square
1633  vValue[ip] = locElemWeights[ip]*approxSolIP*approxSolIP;
1634 
1635  }
1636 
1637  }
1638  UG_CATCH_THROW("L2FuncIntegrand::values: trial space missing.");
1639  }
1640 };
1641 
1654 template <typename TGridFunction>
1655 number L2Norm2(TGridFunction& u, const char* cmp,
1656  int quadOrder, const char* subsets,
1658 {
1659 // get function id of name
1660  const size_t fct = u.fct_id_by_name(cmp);
1661 
1662 // check that function exists
1663  UG_COND_THROW(fct >= u.num_fct(), "L2Norm: Function space does not contain"
1664  " a function with name " << cmp << ".");
1665 
1666  L2Integrand<TGridFunction> integrandL2(u, fct, spWeight);
1667  return IntegrateSubsets(integrandL2, u, subsets, quadOrder);
1668 }
1669 
1670 template <typename TGridFunction>
1671 number L2Norm2(TGridFunction& u, const char* cmp,
1672  int quadOrder, const char* subsets)
1673 {
1674 // get function id of name
1675  const size_t fct = u.fct_id_by_name(cmp);
1676 
1677 // check that function exists
1678  UG_COND_THROW(fct >= u.num_fct(), "L2Norm: Function space does not contain"
1679  " a function with name " << cmp << ".");
1680 
1681  L2Integrand<TGridFunction> integrandL2(u, fct);
1682  return IntegrateSubsets(integrandL2, u, subsets, quadOrder);
1683 }
1684 
1685 template <typename TGridFunction>
1686 number L2Norm(TGridFunction& u, const char* cmp,
1687  int quadOrder, const char* subsets)
1688 {
1689  return sqrt(L2Norm2(u, cmp, quadOrder, subsets));
1690 }
1699 template <typename TGridFunction>
1700 number L2Norm(TGridFunction& gridFct, const char* cmp, int quadOrder)
1701 { return L2Norm(gridFct, cmp, quadOrder, NULL); }
1702 
1703 template <typename TGridFunction>
1704 number L2Norm(SmartPtr<TGridFunction> spGridFct, const char* cmp, int quadOrder, const char* subsets)
1705 { return L2Norm(*spGridFct, cmp, quadOrder, subsets); }
1706 
1707 template <typename TGridFunction>
1708 number L2Norm(SmartPtr<TGridFunction> spGridFct, const char* cmp, int quadOrder)
1709 { return L2Norm(spGridFct, cmp, quadOrder, NULL); }
1710 
1711 
1713 template <typename TGridFunction>
1715  : public StdIntegrand<number, TGridFunction::dim, L2DistIntegrand<TGridFunction> >
1716 {
1717  public:
1719  static const int worldDim = TGridFunction::dim;
1721 
1722  protected:
1724  const int m_fineTopLevel;
1725 
1727  const int m_coarseTopLevel;
1728 
1731 
1733 
1736 
1737  public:
1738 
1740  L2DistIntegrand(TGridFunction& fineGridFct, size_t fineCmp,
1741  TGridFunction& coarseGridFct, size_t coarseCmp)
1742  : m_fineData(fineGridFct, fineCmp), m_fineTopLevel(fineGridFct.dof_distribution()->grid_level().level()),
1743  m_coarseData(coarseGridFct, coarseCmp), m_coarseTopLevel(coarseGridFct.dof_distribution()->grid_level().level()),
1744  m_spMG(m_fineData.domain()->grid()), m_spWeight(make_sp(new ConstUserNumber<TGridFunction::dim>(1.0))),
1745  m_deltaFineCoarse(0.0)
1746  {
1748  "L2DiffIntegrand: fine and top level inverted.");
1749  UG_COND_THROW(m_fineData.domain().get() != m_coarseData.domain().get(),
1750  "L2DiffIntegrand: grid functions defined on different domains.");
1751  };
1752 
1754  L2DistIntegrand(TGridFunction& fineGridFct, size_t fineCmp,
1755  TGridFunction& coarseGridFct, size_t coarseCmp, ConstSmartPtr<weight_type> spWeight)
1756  : m_fineData(fineGridFct, fineCmp), m_fineTopLevel(fineGridFct.dof_distribution()->grid_level().level()),
1757  m_coarseData(coarseGridFct, coarseCmp), m_coarseTopLevel(coarseGridFct.dof_distribution()->grid_level().level()),
1758  m_spMG(m_fineData.domain()->grid()), m_spWeight(spWeight),
1759  m_deltaFineCoarse(0.0)
1760  {
1762  "L2DiffIntegrand: fine and top level inverted.");
1763  UG_COND_THROW(m_fineData.domain().get() != m_coarseData.domain().get(),
1764  "L2DiffIntegrand: grid functions defined on different domains.");
1765  };
1766 
1768  L2DistIntegrand(TGridFunction& fineGridFct, size_t fineCmp,
1769  TGridFunction& coarseGridFct, size_t coarseCmp, ConstSmartPtr<weight_type> spWeight, number dist12)
1770  : m_fineData(fineGridFct, fineCmp), m_fineTopLevel(fineGridFct.dof_distribution()->grid_level().level()),
1771  m_coarseData(coarseGridFct, coarseCmp), m_coarseTopLevel(coarseGridFct.dof_distribution()->grid_level().level()),
1772  m_spMG(m_fineData.domain()->grid()), m_spWeight(spWeight),
1773  m_deltaFineCoarse(dist12)
1774  {
1776  "L2DiffIntegrand: fine and top level inverted.");
1777  UG_COND_THROW(m_fineData.domain().get() != m_coarseData.domain().get(),
1778  "L2DiffIntegrand: grid functions defined on different domains.");
1779  };
1780 
1781 
1782  virtual ~L2DistIntegrand() {}
1783 
1785  virtual void set_subset(int si)
1786  {
1787  UG_COND_THROW(!m_fineData.is_def_in_subset(si),
1788  "L2DiffIntegrand: Grid function component" <<m_fineData.fct()<<" not defined on subset "<<si);
1789  UG_COND_THROW(!m_coarseData.is_def_in_subset(si),
1790  "L2DiffIntegrand: Grid function component" <<m_coarseData.fct()<<" not defined on subset "<<si);
1792  }
1793 
1795  template <int elemDim>
1796  void evaluate(number vValue[],
1797  const MathVector<worldDim> vFineGlobIP[],
1798  GridObject* pFineElem,
1799  const MathVector<worldDim> vCornerCoords[],
1800  const MathVector<elemDim> vFineLocIP[],
1801  const MathMatrix<elemDim, worldDim> vJT[],
1802  const size_t numIP)
1803  {
1804  typedef typename TGridFunction::template dim_traits<elemDim>::grid_base_object Element;
1805 
1806  // get coarse element
1807  GridObject* pCoarseElem = pFineElem;
1809  int parentLevel = m_spMG->get_level(pCoarseElem);
1810  while(parentLevel > m_coarseTopLevel){
1811  pCoarseElem = m_spMG->get_parent(pCoarseElem);
1812  parentLevel = m_spMG->get_level(pCoarseElem);
1813  }
1814  }
1815 
1816  // get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
1817  const ReferenceObjectID fineROID = pFineElem->reference_object_id();
1818  const ReferenceObjectID coarseROID = pCoarseElem->reference_object_id();
1819 
1820  // get corner coordinates
1821  std::vector<MathVector<worldDim> > vCornerCoarse;
1822  CollectCornerCoordinates(vCornerCoarse, *static_cast<Element*>(pCoarseElem), *m_coarseData.domain());
1823 
1824  // get Reference Mapping
1826  = ReferenceMappingProvider::get<elemDim, worldDim>(coarseROID, vCornerCoarse);
1827 
1828  std::vector<MathVector<elemDim> > vCoarseLocIP;
1829  vCoarseLocIP.resize(numIP);
1830  for(size_t ip = 0; ip < vCoarseLocIP.size(); ++ip) VecSet(vCoarseLocIP[ip], 0.0);
1831  map.global_to_local(&vCoarseLocIP[0], vFineGlobIP, numIP);
1832 
1833  // element weights
1834  typedef typename weight_type::data_type ipdata_type;
1835  std::vector<ipdata_type> fineElemWeights(numIP, 1.0);
1836  UG_ASSERT(m_spWeight.valid(), "L2DistIntegrand::evaluate requires valid weights! ");
1837  (*m_spWeight)(&fineElemWeights[0], vFineGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), numIP);
1838 
1839  try{
1840  // get trial space
1841  const LocalShapeFunctionSet<elemDim>& rFineLSFS =
1842  LocalFiniteElementProvider::get<elemDim>(fineROID, m_fineData.id());
1843  const LocalShapeFunctionSet<elemDim>& rCoarseLSFS =
1844  LocalFiniteElementProvider::get<elemDim>(coarseROID, m_coarseData.id());
1845 
1846  // get multiindices of element
1847  std::vector<DoFIndex> vFineMI, vCoarseMI;
1848  m_fineData.dof_indices(pFineElem, vFineMI);
1849  m_coarseData.dof_indices(pCoarseElem, vCoarseMI);
1850 
1851  // loop all integration points
1852  for(size_t ip = 0; ip < numIP; ++ip)
1853  {
1854  // compute approximated solution at integration point
1855  number fineSolIP = 0.0;
1856  for(size_t sh = 0; sh < vFineMI.size(); ++sh)
1857  {
1858  // get value at shape point (e.g. corner for P1 fct)
1859  const number val = DoFRef(m_fineData.grid_function(), vFineMI[sh]);
1860 
1861  // add shape fct at ip * value at shape
1862  fineSolIP += val * rFineLSFS.shape(sh, vFineLocIP[ip]);
1863  }
1864  number coarseSolIP = 0.0;
1865  for(size_t sh = 0; sh < vCoarseMI.size(); ++sh)
1866  {
1867  // get value at shape point (e.g. corner for P1 fct)
1868  const number val = DoFRef(m_coarseData.grid_function(), vCoarseMI[sh]);
1869 
1870  // add shape fct at ip * value at shape
1871  coarseSolIP += val * rCoarseLSFS.shape(sh, vCoarseLocIP[ip]);
1872  }
1873 
1874  // get squared of difference
1875  vValue[ip] = fineElemWeights[ip]*(fineSolIP - coarseSolIP -m_deltaFineCoarse)*(fineSolIP-coarseSolIP-m_deltaFineCoarse);
1876  }
1877 
1878  }
1879  UG_CATCH_THROW("L2DistIntegrand::evaluate: trial space missing.");
1880  }
1881 };
1882 
1883 
1885 template <typename TGridFunction>
1886 number L2Distance2(TGridFunction& spGridFct1, const char* cmp1,
1887  TGridFunction& spGridFct2, const char* cmp2,
1888  int quadOrder, const char* subsets,
1889  ConstSmartPtr<typename L2Integrand<TGridFunction>::weight_type> spWeight, number avgDist12=0.0)
1890 {
1891  return GridFunctionDistance2<L2DistIntegrand<TGridFunction>, TGridFunction>
1892  (spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, subsets, spWeight, avgDist12);
1893 }
1894 
1895 
1897 template <typename TGridFunction>
1898 number L2Distance2(TGridFunction& spGridFct1, const char* cmp1,
1899  TGridFunction& spGridFct2, const char* cmp2,
1900  int quadOrder, const char* subsets)
1901 {
1902  return GridFunctionDistance2<L2DistIntegrand<TGridFunction>, TGridFunction>
1903  (spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, subsets);
1904 }
1905 
1907 template <typename TGridFunction>
1908 number L2Distance(TGridFunction& spGridFct1, const char* cmp1,
1909  TGridFunction& spGridFct2, const char* cmp2,
1910  int quadOrder, const char* subsets)
1911 {
1912  return sqrt(L2Distance2(spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, subsets));
1913 }
1914 
1915 
1916 template <typename TGridFunction>
1917 number L2Error(SmartPtr<TGridFunction> spGridFct1, const char* cmp1,
1918  SmartPtr<TGridFunction> spGridFct2, const char* cmp2,
1919  int quadOrder)
1920 {
1921  return L2Distance(*spGridFct1, cmp1, *spGridFct2, cmp2, quadOrder, NULL);
1922 }
1923 
1924 template <typename TGridFunction>
1925 number L2Error(SmartPtr<TGridFunction> spGridFct1, const char* cmp1,
1926  SmartPtr<TGridFunction> spGridFct2, const char* cmp2,
1927  int quadOrder, const char* subsets)
1928 {
1929  return L2Distance(*spGridFct1, cmp1, *spGridFct2, cmp2, quadOrder, subsets);
1930 }
1931 
1933 // H1 semi-norm Integrand
1935 
1936 
1937 
1939 template <typename TGridFunction>
1941  : public StdIntegrand<number, TGridFunction::dim, H1SemiIntegrand<TGridFunction> >
1942 {
1943  public:
1945  static const int worldDim = TGridFunction::dim;
1947 
1948  protected:
1951 
1954 
1955  public:
1957  H1SemiIntegrand(TGridFunction& gridFct, size_t cmp)
1958  : m_scalarData(gridFct, cmp), m_spWeight(make_sp(new ConstUserMatrix<worldDim>(1.0))) {}
1959 
1961  H1SemiIntegrand(TGridFunction& gridFct, size_t cmp, ConstSmartPtr<weight_type> spWeight)
1962  : m_scalarData(gridFct, cmp), m_spWeight(spWeight) {}
1963 
1965  virtual ~H1SemiIntegrand() {};
1966 
1968  virtual void set_subset(int si)
1969  {
1970 
1971  UG_COND_THROW(!m_scalarData.is_def_in_subset(si), "H1Error: Grid function component"
1972  <<m_scalarData.fct()<<" not defined on subset "<<si);
1974  }
1975 
1977  template <int elemDim>
1978  void evaluate(number vValue[],
1979  const MathVector<worldDim> vGlobIP[],
1980  GridObject* pElem,
1981  const MathVector<worldDim> vCornerCoords[],
1982  const MathVector<elemDim> vLocIP[],
1983  const MathMatrix<elemDim, worldDim> vJT[],
1984  const size_t numIP)
1985  {
1986  // get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
1987  const ReferenceObjectID roid = pElem->reference_object_id();
1988  const TGridFunction &gridFct= m_scalarData.grid_function();
1989 
1990  typedef typename weight_type::data_type ipdata_type;
1991 
1992  std::vector<ipdata_type> elemWeights(numIP, MathMatrix<worldDim, worldDim>());
1993  UG_ASSERT(m_spWeight.valid(), "H1SemiIntegrand::evaluate requires valid weights!");
1994 
1995 
1997  {
1998  // get local solution if needed
1999  LocalIndices ind;
2000  LocalVector uloc;
2001  gridFct.indices(pElem, ind); // get global indices
2002  uloc.resize(ind); // adapt local algebra
2003  GetLocalVector(uloc, gridFct); // read local values of u
2004 
2005  // compute data
2006  try{
2007  (*m_spWeight)(&elemWeights[0], vGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), pElem,
2008  vCornerCoords, vLocIP, numIP, &uloc, NULL);
2009  } UG_CATCH_THROW("H1SemiIntegrand: Cannot evaluate weight data.");
2010  }
2011  else
2012  {
2013  // compute data
2014  try{
2015  (*m_spWeight)(&elemWeights[0], vGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), numIP);
2016  } UG_CATCH_THROW("H1SemiIntegrand: Cannot evaluate weight data.");
2017  }
2018 
2019 
2020  try{
2021 
2022 
2023 
2024 
2025  // get trial space
2026  const LocalShapeFunctionSet<elemDim>& rTrialSpace =
2027  LocalFiniteElementProvider::get<elemDim>(roid, m_scalarData.id());
2028 
2029  // number of dofs on element
2030  const size_t num_sh = rTrialSpace.num_sh();
2031 
2032  // get multiindices of element
2033  std::vector<DoFIndex> ind; // aux. index array
2034  gridFct.dof_indices(pElem, m_scalarData.fct(), ind);
2035 
2036  // check multi indices
2037  UG_COND_THROW(ind.size() != num_sh, "H1SemiNormFuncIntegrand::evaluate: Wrong number of multi-)indices.");
2038 
2039  // loop all integration points
2040  std::vector<MathVector<elemDim> > vLocGradient(num_sh);
2041  for(size_t ip = 0; ip < numIP; ++ip)
2042  {
2043  // compute shape gradients at ip
2044  rTrialSpace.grads(&vLocGradient[0], vLocIP[ip]);
2045 
2046  // compute approximated solution at integration point
2047  number approxSolIP = 0.0;
2048  MathVector<elemDim> tmpVec(0.0);
2049  for(size_t sh = 0; sh < num_sh; ++sh)
2050  {
2051  // get value at shape point (e.g. corner for P1 fct)
2052  const number valSH = DoFRef(gridFct, ind[sh]);
2053 
2054  // add shape fct at ip * value at shape
2055  approxSolIP += valSH * rTrialSpace.shape(sh, vLocIP[ip]);
2056 
2057  // add gradient at ip
2058  VecScaleAppend(tmpVec, valSH, vLocGradient[sh]);
2059  }
2060 
2061  // compute gradient
2062  MathVector<worldDim> approxGradIP;
2064  Inverse(JTInv, vJT[ip]);
2065  MatVecMult(approxGradIP, JTInv, tmpVec);
2066 
2067  // get norm squared
2068  MathVector<worldDim> approxDGradIP;
2069  MatVecMult(approxDGradIP, elemWeights[ip], approxGradIP);
2070  vValue[ip] = VecDot(approxDGradIP, approxGradIP);
2071  }
2072 
2073  }
2074  UG_CATCH_THROW("H1SemiIntegrand::evaluate: trial space missing.");
2075  }
2076 };
2077 
2078 
2080 
2091 template <typename TGridFunction>
2092 number H1SemiNorm2(TGridFunction& gridFct, const char* cmp, int quadOrder, const char* subsets=NULL,
2094 {
2095 // get function id of name
2096  const size_t fct = gridFct.fct_id_by_name(cmp);
2097 
2098 // check that function exists
2099  UG_COND_THROW(fct >= gridFct.num_fct(), "H1SemiNorm: Function space does not contain"
2100  " a function with name " << cmp << ".");
2101  if (weights.invalid()) {
2102  H1SemiIntegrand<TGridFunction> integrand(gridFct, fct);
2103  return IntegrateSubsets(integrand, gridFct, subsets, quadOrder);
2104  } else {
2105  H1SemiIntegrand<TGridFunction> integrand(gridFct, fct, weights);
2106  return IntegrateSubsets(integrand, gridFct, subsets, quadOrder);
2107  }
2108 }
2109 
2111 template <typename TGridFunction>
2112 number H1SemiNorm(TGridFunction& gridFct, const char* cmp, int quadOrder, const char* subsets=NULL,
2114 {
2115  return (sqrt(H1SemiNorm2(gridFct, cmp, quadOrder, subsets, weights)));
2116 }
2117 
2118 // Delegating to H1SemiNorm
2119 template <typename TGridFunction>
2120 number H1SemiNorm(SmartPtr<TGridFunction> spGridFct, const char* cmp, int quadOrder, const char* subsets)
2121 { return H1SemiNorm(*spGridFct, cmp, quadOrder, subsets); }
2122 
2123 template <typename TGridFunction>
2124 number H1SemiNorm(SmartPtr<TGridFunction> spGridFct, const char* cmp, int quadOrder,
2125  const char* subsets, ConstSmartPtr<typename H1SemiIntegrand<TGridFunction>::weight_type> weights = SPNULL)
2126 { return H1SemiNorm(*spGridFct, cmp, quadOrder, subsets, weights); }
2127 
2128 template <typename TGridFunction>
2129 number H1SemiNorm( SmartPtr<TGridFunction> spGridFct, const char* cmp, int quadOrder)
2130 { return H1SemiNorm(*spGridFct, cmp, quadOrder, NULL); }
2131 
2132 template <typename TGridFunction>
2133 number H1SemiNorm( SmartPtr<TGridFunction> spGridFct, const char* cmp, int quadOrder,
2135 { return H1SemiNorm(*spGridFct, cmp, quadOrder, NULL, weights); }
2136 
2138 template <typename TGridFunction>
2139 class H1SemiDistIntegrand : public StdIntegrand<number, TGridFunction::dim, H1SemiDistIntegrand<TGridFunction> >
2140 {
2141  public:
2143  static const int worldDim = TGridFunction::dim;
2145 
2146  private:
2148  const int m_fineTopLevel;
2149 
2151  const int m_coarseTopLevel;
2152 
2155 
2158 
2159  public:
2161  H1SemiDistIntegrand(TGridFunction& fineGridFct, size_t fineCmp,
2162  TGridFunction& coarseGridFct, size_t coarseCmp)
2163  : m_fineData(fineGridFct, fineCmp),
2164  m_fineTopLevel(fineGridFct.dof_distribution()->grid_level().level()),
2165  m_coarseData(coarseGridFct, coarseCmp),
2166  m_coarseTopLevel(coarseGridFct.dof_distribution()->grid_level().level()),
2167  m_spMG(fineGridFct.domain()->grid()),
2168  m_spWeight(new ConstUserNumber<TGridFunction::dim>(1.0))
2169  {
2171  UG_THROW("H1SemiDiffIntegrand: fine and top level inverted.");
2172 
2173  if(m_fineData.domain().get() != m_coarseData.domain().get())
2174  UG_THROW("H1SemiDiffIntegrand: grid functions defined on different domains.");
2175  };
2176 
2178  H1SemiDistIntegrand(TGridFunction& fineGridFct, size_t fineCmp,
2179  TGridFunction& coarseGridFct, size_t coarseCmp,
2180  ConstSmartPtr<weight_type> spWeight)
2181  : m_fineData(fineGridFct, fineCmp),
2182  m_fineTopLevel(fineGridFct.dof_distribution()->grid_level().level()),
2183  m_coarseData(coarseGridFct, coarseCmp),
2184  m_coarseTopLevel(coarseGridFct.dof_distribution()->grid_level().level()),
2185  m_spMG(fineGridFct.domain()->grid()),
2186  m_spWeight(spWeight)
2187  {
2188  UG_COND_THROW(m_fineTopLevel < m_coarseTopLevel, "H1SemiDiffIntegrand: fine and top level inverted.");
2189  UG_COND_THROW(m_fineData.domain().get() != m_coarseData.domain().get(), "H1SemiDiffIntegrand: grid functions defined on different domains.");
2190  }
2192 
2194  virtual void set_subset(int si)
2195  {
2196 
2197  UG_COND_THROW(!m_fineData.is_def_in_subset(si), "H1SemiDiffIntegrand: Grid function component"
2198  <<m_fineData.fct()<<" not defined on subset "<<si);
2199  UG_COND_THROW(!m_coarseData.is_def_in_subset(si), "H1SemiDiffIntegrand: Grid function component"
2200  <<m_coarseData.fct()<<" not defined on subset "<<si);
2202  }
2203 
2205  template <int elemDim>
2206  void evaluate(number vValue[],
2207  const MathVector<worldDim> vFineGlobIP[],
2208  GridObject* pFineElem,
2209  const MathVector<worldDim> vCornerCoords[],
2210  const MathVector<elemDim> vFineLocIP[],
2211  const MathMatrix<elemDim, worldDim> vJT[],
2212  const size_t numIP)
2213  {
2214  typedef typename TGridFunction::template dim_traits<elemDim>::grid_base_object Element;
2215 
2216  const TGridFunction &fineGridFct = m_fineData.grid_function();
2217  const TGridFunction &coarseGridFct = m_coarseData.grid_function();
2218 
2219  // get coarse element
2220  GridObject* pCoarseElem = pFineElem;
2222  int parentLevel = m_spMG->get_level(pCoarseElem);
2223  while(parentLevel > m_coarseTopLevel){
2224  pCoarseElem = m_spMG->get_parent(pCoarseElem);
2225  parentLevel = m_spMG->get_level(pCoarseElem);
2226  }
2227  }
2228 
2229  // get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
2230  const ReferenceObjectID fineROID = pFineElem->reference_object_id();
2231  const ReferenceObjectID coarseROID = pCoarseElem->reference_object_id();
2232 
2233  // get corner coordinates
2234  std::vector<MathVector<worldDim> > vCornerCoarse;
2235  CollectCornerCoordinates(vCornerCoarse, *static_cast<Element*>(pCoarseElem), *m_coarseData.domain());
2236 
2237  // get reference Mapping
2239  = ReferenceMappingProvider::get<elemDim, worldDim>(coarseROID, vCornerCoarse);
2240 
2241  std::vector<MathVector<elemDim> > vCoarseLocIP;
2242  vCoarseLocIP.resize(numIP);
2243  for(size_t ip = 0; ip < vCoarseLocIP.size(); ++ip) VecSet(vCoarseLocIP[ip], 0.0);
2244  map.global_to_local(&vCoarseLocIP[0], vFineGlobIP, numIP);
2245 
2246 
2247  // determine weights
2248  std::vector<typename weight_type::data_type> elemWeights(numIP, MathMatrix<worldDim, worldDim>());
2249  UG_ASSERT(m_spWeight.valid(), "H1SemiDistIntegrand::evaluate requires valid weights!");
2250 
2251  // get local solution (if required)
2253  {
2254 
2255  LocalIndices ind;
2256  LocalVector u;
2257  fineGridFct.indices(pFineElem, ind); // get global indices
2258  u.resize(ind); // adapt local algebra
2259  GetLocalVector(u, fineGridFct); // read local values of u
2260 
2261  // compute data
2262  try{
2263  (*m_spWeight)(&elemWeights[0], vFineGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), pFineElem,
2264  vCornerCoords, vFineLocIP, numIP, &u, NULL);
2265  } UG_CATCH_THROW("H1SemiDistIntegrand: Cannot evaluate data.");
2266  }
2267  else
2268  {
2269  // compute data
2270  try{
2271  (*m_spWeight)(&elemWeights[0], vFineGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), numIP);
2272  } UG_CATCH_THROW("H1SemiDistIntegrand: Cannot evaluate data.");
2273  }
2274 
2275  try{
2276 
2277 
2278  // get trial space
2279  const LocalShapeFunctionSet<elemDim>& rFineLSFS =
2280  LocalFiniteElementProvider::get<elemDim>(fineROID, m_fineData.id());
2281  const LocalShapeFunctionSet<elemDim>& rCoarseLSFS =
2282  LocalFiniteElementProvider::get<elemDim>(coarseROID, m_coarseData.id());
2283 
2284  // get multiindices of element
2285  std::vector<DoFIndex> vFineMI, vCoarseMI;
2286  m_fineData.dof_indices(pFineElem, vFineMI);
2287  m_coarseData.dof_indices(pCoarseElem, vCoarseMI);
2288 
2289  std::vector<MathVector<elemDim> > vFineLocGradient(vFineMI.size());
2290  std::vector<MathVector<elemDim> > vCoarseLocGradient(vCoarseMI.size());
2291 
2292  // loop all integration points
2293  for(size_t ip = 0; ip < numIP; ++ip)
2294  {
2295  // compute shape gradients at ip
2296  rFineLSFS.grads(&vFineLocGradient[0], vFineLocIP[ip]);
2297  rCoarseLSFS.grads(&vCoarseLocGradient[0], vCoarseLocIP[ip]);
2298 
2299  // compute approximated solutions at integration point
2300  number fineSolIP = 0.0;
2301  MathVector<elemDim> fineLocTmp(0.0);
2302  for(size_t sh = 0; sh < vFineMI.size(); ++sh)
2303  {
2304  const number val = DoFRef(fineGridFct, vFineMI[sh]);
2305  fineSolIP += val * rFineLSFS.shape(sh, vFineLocIP[ip]);
2306  VecScaleAppend(fineLocTmp, val, vFineLocGradient[sh]);
2307  }
2308 
2309  number coarseSolIP = 0.0;
2310  MathVector<elemDim> coarseLocTmp(0.0);
2311  for(size_t sh = 0; sh < vCoarseMI.size(); ++sh)
2312  {
2313  const number val = DoFRef(coarseGridFct, vCoarseMI[sh]);
2314  coarseSolIP += val * rCoarseLSFS.shape(sh, vCoarseLocIP[ip]);
2315  VecScaleAppend(coarseLocTmp, val, vCoarseLocGradient[sh]);
2316  }
2317 
2318  // compute global gradient
2319  MathVector<worldDim> fineGradIP;
2321  Inverse(fineJTInv, vJT[ip]);
2322  MatVecMult(fineGradIP, fineJTInv, fineLocTmp);
2323 
2324  // compute global gradient
2325  MathVector<worldDim> coarseGradIP;
2326  MathMatrix<worldDim, elemDim> coarseJTInv;
2327  map.jacobian_transposed_inverse(coarseJTInv, vCoarseLocIP[ip]);
2328  MatVecMult(coarseGradIP, coarseJTInv, coarseLocTmp);
2329 
2330  // get squared of difference
2331  /*vValue[ip] = (coarseSolIP - fineSolIP);
2332  vValue[ip] *= vValue[ip]; */
2333  vValue[ip] = VecDistanceSq(coarseGradIP, fineGradIP, elemWeights[ip]);
2334  }
2335 
2336  }
2337  UG_CATCH_THROW("H1SemiDiffIntegrand::evaluate: trial space missing.");
2338  }
2339 };
2340 
2341 
2343 template <typename TGridFunction>
2344 number H1SemiError2(SmartPtr<TGridFunction> spGridFct1, const char* cmp1,
2345  SmartPtr<TGridFunction> spGridFct2, const char* cmp2,
2346  int quadOrder, const char* subsets)
2347 {
2348  return GridFunctionDistance2<H1SemiDistIntegrand<TGridFunction>, TGridFunction>
2349  (*spGridFct1, cmp1, *spGridFct2, cmp2, quadOrder, subsets);
2350 }
2351 
2353 template <typename TGridFunction>
2354 number H1SemiError(SmartPtr<TGridFunction> spGridFct1, const char* cmp1,
2355  SmartPtr<TGridFunction> spGridFct2, const char* cmp2,
2356  int quadOrder, const char* subsets)
2357 {
2358  return sqrt(H1SemiError2(*spGridFct1, cmp1, *spGridFct2, cmp2, quadOrder, subsets));
2359 }
2360 
2362 template <typename TGridFunction>
2363 number H1SemiError(SmartPtr<TGridFunction> spGridFct1, const char* cmp1,
2364  SmartPtr<TGridFunction> spGridFct2, const char* cmp2,
2365  int quadOrder)
2366 {
2367  return H1SemiError(*spGridFct1, cmp1, *spGridFct2, cmp2, quadOrder, NULL);
2368 }
2369 
2371 template <typename TGridFunction>
2372 number H1SemiDistance2(TGridFunction& spGridFct1, const char* cmp1,
2373  TGridFunction& spGridFct2, const char* cmp2,
2374  int quadOrder, const char* subsets,
2376 {
2377  return GridFunctionDistance2<H1SemiDistIntegrand<TGridFunction>, TGridFunction>
2378  (spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, subsets, weights);
2379 }
2380 
2382 template <typename TGridFunction>
2383 number H1SemiDistance(TGridFunction& spGridFct1, const char* cmp1,
2384  TGridFunction& spGridFct2, const char* cmp2,
2385  int quadOrder, const char* subsets,
2387 { return sqrt(H1SemiDistance2(spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, subsets, weights)); }
2388 
2390 template <typename TGridFunction>
2391 number H1SemiDistance2(TGridFunction& spGridFct1, const char* cmp1,
2392  TGridFunction& spGridFct2, const char* cmp2,
2393  int quadOrder, ConstSmartPtr<typename H1SemiDistIntegrand<TGridFunction>::weight_type > weights)
2394 { return H1SemiDistance2(spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, NULL, weights); }
2395 
2397 template <typename TGridFunction>
2398 number H1SemiDistance(TGridFunction& spGridFct1, const char* cmp1,
2399  TGridFunction& spGridFct2, const char* cmp2,
2400  int quadOrder, ConstSmartPtr<typename H1SemiDistIntegrand<TGridFunction>::weight_type > weights)
2401 { return sqrt(H1SemiDistance2(spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, NULL, weights)); }
2402 
2403 
2404 
2405 
2407 // H1 semi-norm Integrand
2409 
2411 template <typename TGridFunction>
2413  : public StdIntegrand<number, TGridFunction::dim, H1EnergyIntegrand<TGridFunction> >
2414 {
2415  public:
2417  static const int worldDim = TGridFunction::dim;
2419 
2420  protected:
2423 
2426 
2427  public:
2429  H1EnergyIntegrand(TGridFunction& gridFct, size_t cmp)
2430  : m_scalarData(gridFct, cmp), m_spWeight(make_sp(new ConstUserMatrix<worldDim>(1.0))) {}
2431 
2433  H1EnergyIntegrand(TGridFunction& gridFct, size_t cmp, ConstSmartPtr<weight_type> spWeight)
2434  : m_scalarData(gridFct, cmp), m_spWeight(spWeight) {}
2435 
2437  virtual ~H1EnergyIntegrand() {};
2438 
2440  virtual void set_subset(int si)
2441  {
2442 
2443  UG_COND_THROW(!m_scalarData.is_def_in_subset(si), "H1EnergyIntegrand: Grid function component"
2444  <<m_scalarData.fct()<<" not defined on subset "<<si);
2446  }
2447 
2449  template <int elemDim>
2450  void evaluate(number vValue[],
2451  const MathVector<worldDim> vGlobIP[],
2452  GridObject* pElem,
2453  const MathVector<worldDim> vCornerCoords[],
2454  const MathVector<elemDim> vLocIP[],
2455  const MathMatrix<elemDim, worldDim> vJT[],
2456  const size_t numIP)
2457  {
2458  // get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
2459  const ReferenceObjectID roid = pElem->reference_object_id();
2460  const TGridFunction &gridFct= m_scalarData.grid_function();
2461 
2462  typedef typename weight_type::data_type ipdata_type;
2463 
2464  std::vector<ipdata_type> elemWeights(numIP, MathMatrix<worldDim, worldDim>());
2465  UG_ASSERT(m_spWeight.valid(), "H1EnergyIntegrand::evaluate requires valid weights!");
2466 
2467 
2469  {
2470  // get local solution if needed
2471  LocalIndices ind;
2472  LocalVector uloc;
2473  gridFct.indices(pElem, ind); // get global indices
2474  uloc.resize(ind); // adapt local algebra
2475  GetLocalVector(uloc, gridFct); // read local values of u
2476 
2477  // compute data
2478  try{
2479  (*m_spWeight)(&elemWeights[0], vGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), pElem,
2480  vCornerCoords, vLocIP, numIP, &uloc, NULL);
2481  } UG_CATCH_THROW("H1EnergyIntegrand: Cannot evaluate weight data.");
2482  }
2483  else
2484  {
2485  // compute data
2486  try{
2487  (*m_spWeight)(&elemWeights[0], vGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), numIP);
2488  } UG_CATCH_THROW("H1EnergyIntegrand: Cannot evaluate weight data.");
2489  }
2490 
2491 
2492  try{
2493 
2494 
2495 
2496 
2497  // get trial space
2498  const LocalShapeFunctionSet<elemDim>& rTrialSpace =
2499  LocalFiniteElementProvider::get<elemDim>(roid, m_scalarData.id());
2500 
2501  // number of dofs on element
2502  const size_t num_sh = rTrialSpace.num_sh();
2503 
2504  // get multiindices of element
2505  std::vector<DoFIndex> ind; // aux. index array
2506  gridFct.dof_indices(pElem, m_scalarData.fct(), ind);
2507 
2508  // check multi indices
2509  UG_COND_THROW(ind.size() != num_sh, "H1EnergyIntegrand::evaluate: Wrong number of multi-)indices.");
2510 
2511  // loop all integration points
2512  std::vector<MathVector<elemDim> > vLocGradient(num_sh);
2513  for(size_t ip = 0; ip < numIP; ++ip)
2514  {
2515  // compute shape gradients at ip
2516  rTrialSpace.grads(&vLocGradient[0], vLocIP[ip]);
2517 
2518  // compute approximated solution at integration point
2519  number approxSolIP = 0.0;
2520  MathVector<elemDim> tmpVec(0.0);
2521  for(size_t sh = 0; sh < num_sh; ++sh)
2522  {
2523  // get value at shape point (e.g. corner for P1 fct)
2524  const number valSH = DoFRef(gridFct, ind[sh]);
2525 
2526  // add shape fct at ip * value at shape
2527  approxSolIP += valSH * rTrialSpace.shape(sh, vLocIP[ip]);
2528 
2529  // add gradient at ip
2530  VecScaleAppend(tmpVec, valSH, vLocGradient[sh]);
2531  }
2532 
2533  // compute gradient
2534  MathVector<worldDim> approxGradIP;
2536  Inverse(JTInv, vJT[ip]);
2537  MatVecMult(approxGradIP, JTInv, tmpVec);
2538 
2539  // get norm squared
2540  MathVector<worldDim> approxDGradIP;
2541  MatVecMult(approxDGradIP, elemWeights[ip], approxGradIP);
2542  vValue[ip] = VecTwoNormSq(approxDGradIP);
2543  }
2544 
2545  }
2546  UG_CATCH_THROW("H1EnergyIntegrand::evaluate: trial space missing.");
2547  }
2548 };
2549 
2550 
2552 
2563 template <typename TGridFunction>
2564 number H1EnergyNorm2(TGridFunction& gridFct, const char* cmp, int quadOrder, const char* subsets=NULL,
2566 {
2567 // get function id of name
2568  const size_t fct = gridFct.fct_id_by_name(cmp);
2569 
2570 // check that function exists
2571  UG_COND_THROW(fct >= gridFct.num_fct(), "H1SemiNorm: Function space does not contain"
2572  " a function with name " << cmp << ".");
2573  if (weights.invalid()) {
2574  H1EnergyIntegrand<TGridFunction> integrand(gridFct, fct);
2575  return IntegrateSubsets(integrand, gridFct, subsets, quadOrder);
2576  } else {
2577  H1EnergyIntegrand<TGridFunction> integrand(gridFct, fct, weights);
2578  return IntegrateSubsets(integrand, gridFct, subsets, quadOrder);
2579  }
2580 }
2581 template <typename TGridFunction>
2582 number H1EnergyNorm(TGridFunction& gridFct, const char* cmp, int quadOrder, const char* subsets=NULL,
2584 {
2585  return (sqrt(H1EnergyNorm2(gridFct, cmp, quadOrder, subsets, weights)));
2586 }
2587 
2588 template <typename TGridFunction>
2589 number H1EnergyNorm(SmartPtr<TGridFunction> spGridFct, const char* cmp, int quadOrder,
2590  const char* subsets, ConstSmartPtr<typename H1SemiIntegrand<TGridFunction>::weight_type> weights = SPNULL)
2591 { return H1EnergyNorm(*spGridFct, cmp, quadOrder, subsets, weights); }
2592 
2593 template <typename TGridFunction>
2594 number H1EnergyNorm( SmartPtr<TGridFunction> spGridFct, const char* cmp, int quadOrder)
2595 { return H1EnergyNorm(spGridFct, cmp, quadOrder, NULL); }
2596 
2597 template <typename TGridFunction>
2598 number H1EnergyNorm( SmartPtr<TGridFunction> spGridFct, const char* cmp, int quadOrder,
2600 { return H1EnergyNorm(spGridFct, cmp, quadOrder, NULL, weights); }
2601 
2602 
2603 
2604 
2606 template <typename TGridFunction>
2608  : public StdIntegrand<number, TGridFunction::dim, H1EnergyDistIntegrand<TGridFunction> >
2609 {
2610  public:
2612  static const int worldDim = TGridFunction::dim;
2614 
2615  private:
2617  const int m_fineTopLevel;
2618 
2620  const int m_coarseTopLevel;
2621 
2624 
2627 
2628  public:
2630  H1EnergyDistIntegrand(TGridFunction& fineGridFct, size_t fineCmp,
2631  TGridFunction& coarseGridFct, size_t coarseCmp)
2632  : m_fineData(fineGridFct, fineCmp),
2633  m_fineTopLevel(fineGridFct.dof_distribution()->grid_level().level()),
2634  m_coarseData(coarseGridFct, coarseCmp),
2635  m_coarseTopLevel(coarseGridFct.dof_distribution()->grid_level().level()),
2636  m_spMG(fineGridFct.domain()->grid()),
2637  m_spWeight(new ConstUserNumber<TGridFunction::dim>(1.0))
2638  {
2640  UG_THROW("H1EnergyDistIntegrand: fine and top level inverted.");
2641 
2642  if(m_fineData.domain().get() != m_coarseData.domain().get())
2643  UG_THROW("H1EnergyDistIntegrand: grid functions defined on different domains.");
2644  };
2645 
2647  H1EnergyDistIntegrand(TGridFunction& fineGridFct, size_t fineCmp,
2648  TGridFunction& coarseGridFct, size_t coarseCmp,
2649  ConstSmartPtr<weight_type> spWeight)
2650  : m_fineData(fineGridFct, fineCmp),
2651  m_fineTopLevel(fineGridFct.dof_distribution()->grid_level().level()),
2652  m_coarseData(coarseGridFct, coarseCmp),
2653  m_coarseTopLevel(coarseGridFct.dof_distribution()->grid_level().level()),
2654  m_spMG(fineGridFct.domain()->grid()),
2655  m_spWeight(spWeight)
2656  {
2658  UG_THROW("H1EnergyDistIntegrand: fine and top level inverted.");
2659 
2660  if(m_fineData.domain().get() != m_coarseData.domain().get())
2661  UG_THROW("H1EnergyDistIntegrand: grid functions defined on different domains.");
2662  }
2664 
2666  virtual void set_subset(int si)
2667  {
2668  if(!m_fineData.is_def_in_subset(si))
2669  UG_THROW("H1EnergyDistIntegrand: Grid function component"
2670  <<m_fineData.fct()<<" not defined on subset "<<si);
2671  if(!m_coarseData.is_def_in_subset(si))
2672  UG_THROW("H1EnergyDistIntegrand: Grid function component"
2673  <<m_coarseData.fct()<<" not defined on subset "<<si);
2675  }
2676 
2678  template <int elemDim>
2679  void evaluate(number vValue[],
2680  const MathVector<worldDim> vFineGlobIP[],
2681  GridObject* pFineElem,
2682  const MathVector<worldDim> vCornerCoords[],
2683  const MathVector<elemDim> vFineLocIP[],
2684  const MathMatrix<elemDim, worldDim> vJT[],
2685  const size_t numIP)
2686  {
2687  typedef typename TGridFunction::template dim_traits<elemDim>::grid_base_object Element;
2688 
2689  const TGridFunction &fineGridFct = m_fineData.grid_function();
2690  const TGridFunction &coarseGridFct = m_coarseData.grid_function();
2691 
2692  // get coarse element
2693  GridObject* pCoarseElem = pFineElem;
2695  int parentLevel = m_spMG->get_level(pCoarseElem);
2696  while(parentLevel > m_coarseTopLevel){
2697  pCoarseElem = m_spMG->get_parent(pCoarseElem);
2698  parentLevel = m_spMG->get_level(pCoarseElem);
2699  }
2700  }
2701 
2702  // get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
2703  const ReferenceObjectID fineROID = pFineElem->reference_object_id();
2704  const ReferenceObjectID coarseROID = pCoarseElem->reference_object_id();
2705 
2706  // get corner coordinates
2707  std::vector<MathVector<worldDim> > vCornerCoarse;
2708  CollectCornerCoordinates(vCornerCoarse, *static_cast<Element*>(pCoarseElem), *m_coarseData.domain());
2709 
2710  // get reference Mapping
2712  = ReferenceMappingProvider::get<elemDim, worldDim>(coarseROID, vCornerCoarse);
2713 
2714  std::vector<MathVector<elemDim> > vCoarseLocIP;
2715  vCoarseLocIP.resize(numIP);
2716  for(size_t ip = 0; ip < vCoarseLocIP.size(); ++ip) VecSet(vCoarseLocIP[ip], 0.0);
2717  map.global_to_local(&vCoarseLocIP[0], vFineGlobIP, numIP);
2718 
2719 
2720  // determine weights
2721  std::vector<typename weight_type::data_type> elemWeights(numIP, MathMatrix<worldDim, worldDim>());
2722  UG_ASSERT(m_spWeight.valid(), "H1SemiDistIntegrand::evaluate requires valid weights!");
2723 
2724  // get local solution if needed
2726  {
2727 
2728  LocalIndices ind;
2729  LocalVector u;
2730  fineGridFct.indices(pFineElem, ind); // get global indices
2731  u.resize(ind); // adapt local algebra
2732  GetLocalVector(u, fineGridFct); // read local values of u
2733 
2734  // compute data
2735  try{
2736  (*m_spWeight)(&elemWeights[0], vFineGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), pFineElem,
2737  vCornerCoords, vFineLocIP, numIP, &u, NULL);
2738  } UG_CATCH_THROW("H1SemiDistIntegrand: Cannot evaluate data.");
2739  }
2740  else
2741  {
2742  // compute data
2743  try{
2744  (*m_spWeight)(&elemWeights[0], vFineGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), numIP);
2745  } UG_CATCH_THROW("H1SemiDistIntegrand: Cannot evaluate data.");
2746  }
2747 
2748  try{
2749 
2750 
2751  // get trial space
2752  const LocalShapeFunctionSet<elemDim>& rFineLSFS =
2753  LocalFiniteElementProvider::get<elemDim>(fineROID, m_fineData.id());
2754  const LocalShapeFunctionSet<elemDim>& rCoarseLSFS =
2755  LocalFiniteElementProvider::get<elemDim>(coarseROID, m_coarseData.id());
2756 
2757  // get multiindices of element
2758  std::vector<DoFIndex> vFineMI, vCoarseMI;
2759  m_fineData.dof_indices(pFineElem, vFineMI);
2760  m_coarseData.dof_indices(pCoarseElem, vCoarseMI);
2761 
2762  std::vector<MathVector<elemDim> > vFineLocGradient(vFineMI.size());
2763  std::vector<MathVector<elemDim> > vCoarseLocGradient(vCoarseMI.size());
2764 
2765  // loop all integration points
2766  for(size_t ip = 0; ip < numIP; ++ip)
2767  {
2768  // compute shape gradients at ip
2769  rFineLSFS.grads(&vFineLocGradient[0], vFineLocIP[ip]);
2770  rCoarseLSFS.grads(&vCoarseLocGradient[0], vCoarseLocIP[ip]);
2771 
2772  // compute approximated solutions at integration point
2773  number fineSolIP = 0.0;
2774  MathVector<elemDim> fineLocTmp(0.0);
2775  for(size_t sh = 0; sh < vFineMI.size(); ++sh)
2776  {
2777  const number val = DoFRef(fineGridFct, vFineMI[sh]);
2778  fineSolIP += val * rFineLSFS.shape(sh, vFineLocIP[ip]);
2779  VecScaleAppend(fineLocTmp, val, vFineLocGradient[sh]);
2780  }
2781 
2782  number coarseSolIP = 0.0;
2783  MathVector<elemDim> coarseLocTmp(0.0);
2784  for(size_t sh = 0; sh < vCoarseMI.size(); ++sh)
2785  {
2786  const number val = DoFRef(coarseGridFct, vCoarseMI[sh]);
2787  coarseSolIP += val * rCoarseLSFS.shape(sh, vCoarseLocIP[ip]);
2788  VecScaleAppend(coarseLocTmp, val, vCoarseLocGradient[sh]);
2789  }
2790 
2791  // compute global D*gradient
2792  MathVector<worldDim> fineGradIP;
2794  Inverse(fineJTInv, vJT[ip]);
2795  MatVecMult(fineGradIP, fineJTInv, fineLocTmp);
2796  MatVecMult(fineLocTmp, elemWeights[ip], fineGradIP);
2797 
2798  // compute global D*gradient
2799  MathVector<worldDim> coarseGradIP;
2800  MathMatrix<worldDim, elemDim> coarseJTInv;
2801  map.jacobian_transposed_inverse(coarseJTInv, vCoarseLocIP[ip]);
2802  MatVecMult(coarseGradIP, coarseJTInv, coarseLocTmp);
2803  MatVecMult(coarseLocTmp, elemWeights[ip], coarseGradIP);
2804 
2805  // get squared difference
2806  vValue[ip] = VecDistanceSq(fineLocTmp, coarseLocTmp);
2807 
2808  }
2809 
2810  }
2811  UG_CATCH_THROW("H1EnergyDiffIntegrand::evaluate: trial space missing.");
2812  }
2813 };
2814 
2815 
2817 template <typename TGridFunction>
2818 number H1EnergyDistance2(TGridFunction& spGridFct1, const char* cmp1,
2819  TGridFunction& spGridFct2, const char* cmp2,
2820  int quadOrder, const char* subsets,
2822 {
2823  return GridFunctionDistance2<H1EnergyDistIntegrand<TGridFunction>, TGridFunction>
2824  (spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, subsets, weights);
2825 }
2826 
2828 template <typename TGridFunction>
2829 number H1EnergyDistance(TGridFunction& spGridFct1, const char* cmp1,
2830  TGridFunction& spGridFct2, const char* cmp2,
2831  int quadOrder, const char* subsets,
2833 { return sqrt(H1EnergyDistance2(spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, subsets, weights)); }
2834 
2836 template <typename TGridFunction>
2837 number H1EnergyDistance2(TGridFunction& spGridFct1, const char* cmp1,
2838  TGridFunction& spGridFct2, const char* cmp2,
2839  int quadOrder, ConstSmartPtr<typename H1SemiDistIntegrand<TGridFunction>::weight_type > weights)
2840 { return H1EnergyDistance2(spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, NULL, weights); }
2841 
2843 template <typename TGridFunction>
2844 number H1EnergyDistance(TGridFunction& spGridFct1, const char* cmp1,
2845  TGridFunction& spGridFct2, const char* cmp2,
2846  int quadOrder, ConstSmartPtr<typename H1SemiDistIntegrand<TGridFunction>::weight_type > weights)
2847 { return sqrt(H1EnergyDistance2(spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, NULL, weights)); }
2848 
2849 
2850 
2851 
2853 // H1 norm integrand
2855 template <typename TGridFunction>
2857  : public StdIntegrand<number, TGridFunction::dim, H1NormIntegrand<TGridFunction> >
2858 {
2859  public:
2861  static const int worldDim = TGridFunction::dim;
2862 
2863  private:
2865 
2866  public:
2868  H1NormIntegrand(TGridFunction& gridFct, size_t cmp)
2869  : m_scalarData(gridFct, cmp) {}
2870 
2872  virtual ~H1NormIntegrand() {}
2873 
2875  virtual void set_subset(int si)
2876  {
2877  if(!m_scalarData.is_def_in_subset(si))
2878  UG_THROW("H1Norm: Grid function component"
2879  <<m_scalarData.fct()<<" not defined on subset "<<si);
2881  }
2882 
2884  template <int elemDim>
2885  void evaluate(number vValue[],
2886  const MathVector<worldDim> vGlobIP[],
2887  GridObject* pElem,
2888  const MathVector<worldDim> vCornerCoords[],
2889  const MathVector<elemDim> vLocIP[],
2890  const MathMatrix<elemDim, worldDim> vJT[],
2891  const size_t numIP)
2892  {
2893  // get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
2894  const ReferenceObjectID roid = pElem->reference_object_id();
2895 
2896  try{
2897  // get trial space
2898  const LocalShapeFunctionSet<elemDim>& rTrialSpace =
2899  LocalFiniteElementProvider::get<elemDim>(roid, m_scalarData.id());
2900 
2901  // number of dofs on element
2902  const size_t num_sh = rTrialSpace.num_sh();
2903 
2904  // get multiindices of element
2905  std::vector<DoFIndex> ind; // aux. index array
2906  m_scalarData.dof_indices(pElem, ind);
2907 
2908  // check multi indices
2909  if(ind.size() != num_sh)
2910  UG_THROW("H1ErrorIntegrand::evaluate: Wrong number of"
2911  " multi indices.");
2912 
2913  // loop all integration points
2914  std::vector<MathVector<elemDim> > vLocGradient(num_sh);
2915  for(size_t ip = 0; ip < numIP; ++ip)
2916  {
2917 
2918  // compute shape gradients at ip
2919  rTrialSpace.grads(&vLocGradient[0], vLocIP[ip]);
2920 
2921  // compute approximated solution at integration point
2922  number approxSolIP = 0.0;
2923  MathVector<elemDim> locTmp; VecSet(locTmp, 0.0);
2924  for(size_t sh = 0; sh < num_sh; ++sh)
2925  {
2926  // get value at shape point (e.g. corner for P1 fct)
2927  const number valSH = DoFRef(m_scalarData.grid_function(), ind[sh]);
2928 
2929  // add shape fct at ip * value at shape
2930  approxSolIP += valSH * rTrialSpace.shape(sh, vLocIP[ip]);
2931 
2932  // add gradient at ip
2933  VecScaleAppend(locTmp, valSH, vLocGradient[sh]);
2934  }
2935 
2936  // compute global gradient
2937  MathVector<worldDim> approxGradIP;
2939  RightInverse(JTInv, vJT[ip]);
2940  MatVecMult(approxGradIP, JTInv, locTmp);
2941 
2942  // get squared of difference
2943  vValue[ip] = approxSolIP * approxSolIP;
2944  vValue[ip] += VecDot(approxGradIP, approxGradIP);
2945  }
2946 
2947  }
2948  UG_CATCH_THROW("H1SemiNormFuncIntegrand::evaluate: trial space missing.");
2949  }
2950 };
2951 
2952 
2953 
2954 
2955 template <typename TGridFunction>
2956 number H1Norm2(TGridFunction& u, const char* cmp,
2957  int quadOrder, const char* subsets=NULL)
2958 {
2959 // get function id of name
2960  const size_t fct = u.fct_id_by_name(cmp);
2961 
2962 // check that function exists
2963  if(fct >= u.num_fct())
2964  UG_THROW("H1Norm: Function space does not contain"
2965  " a function with name " << cmp << ".");
2966 
2967  H1NormIntegrand<TGridFunction> spIntegrand(u, fct);
2968  return IntegrateSubsets(spIntegrand, u, subsets, quadOrder);
2969 }
2970 
2971 
2972 template <typename TGridFunction>
2973 number H1Norm(TGridFunction& u, const char* cmp,
2974  int quadOrder, const char* subsets=NULL)
2975 {
2976  return sqrt(H1Norm2(u, cmp, quadOrder,subsets));
2977 }
2978 
2979 template <typename TGridFunction>
2980 number H1Norm(SmartPtr<TGridFunction> spGridFct, const char* cmp,
2981  int quadOrder, const char* subsets)
2982 {
2983  return H1Norm(*spGridFct, cmp, quadOrder, subsets);
2984 }
2985 
2986 template <typename TGridFunction>
2987 number H1Norm(SmartPtr<TGridFunction> spGridFct, const char* cmp, int quadOrder)
2988 {
2989  return H1Norm(*spGridFct, cmp, quadOrder, NULL);
2990 }
2991 
2992 
2993 
2995 template <typename TGridFunction>
2997  : public StdIntegrand<number, TGridFunction::dim, H1DistIntegrand<TGridFunction> >
2998 {
2999  public:
3001  static const int worldDim = TGridFunction::dim;
3002 
3003  private:
3005  const int m_fineTopLevel;
3006 
3008  const int m_coarseTopLevel;
3009 
3012 
3013  public:
3015  H1DistIntegrand(TGridFunction& fineGridFct, size_t fineCmp,
3016  TGridFunction& coarseGridFct, size_t coarseCmp)
3017  : m_fineData(fineGridFct, fineCmp),
3018  m_fineTopLevel(fineGridFct.dof_distribution()->grid_level().level()),
3019  m_coarseData(coarseGridFct, coarseCmp),
3020  m_coarseTopLevel(coarseGridFct.dof_distribution()->grid_level().level()),
3021  m_spMG(fineGridFct.domain()->grid())
3022  {
3024  UG_THROW("H1DiffIntegrand: fine and top level inverted.");
3025 
3026  if(fineGridFct.domain().get() !=
3027  coarseGridFct.domain().get())
3028  UG_THROW("H1DiffIntegrand: grid functions defined on different domains.");
3029  };
3030 
3032  virtual ~H1DistIntegrand() {};
3033 
3035  virtual void set_subset(int si)
3036  {
3037  if(!m_fineData.is_def_in_subset(si))
3038  UG_THROW("H1DiffIntegrand: Grid function component"
3039  <<m_fineData.fct()<<" not defined on subset "<<si);
3040  if(!m_coarseData.is_def_in_subset(si))
3041  UG_THROW("H1DiffIntegrand: Grid function component"
3042  <<m_coarseData.fct()<<" not defined on subset "<<si);
3044  }
3045 
3047  template <int elemDim>
3048  void evaluate(number vValue[],
3049  const MathVector<worldDim> vFineGlobIP[],
3050  GridObject* pFineElem,
3051  const MathVector<worldDim> vCornerCoords[],
3052  const MathVector<elemDim> vFineLocIP[],
3053  const MathMatrix<elemDim, worldDim> vJT[],
3054  const size_t numIP)
3055  {
3056  typedef typename TGridFunction::template dim_traits<elemDim>::grid_base_object Element;
3057 
3058  // get coarse element
3059  GridObject* pCoarseElem = pFineElem;
3061  int parentLevel = m_spMG->get_level(pCoarseElem);
3062  while(parentLevel > m_coarseTopLevel){
3063  pCoarseElem = m_spMG->get_parent(pCoarseElem);
3064  parentLevel = m_spMG->get_level(pCoarseElem);
3065  }
3066  }
3067 
3068  // get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
3069  const ReferenceObjectID fineROID = pFineElem->reference_object_id();
3070  const ReferenceObjectID coarseROID = pCoarseElem->reference_object_id();
3071 
3072  // get corner coordinates
3073  std::vector<MathVector<worldDim> > vCornerCoarse;
3074  CollectCornerCoordinates(vCornerCoarse, *static_cast<Element*>(pCoarseElem), *m_coarseData.domain());
3075 
3076  // get Reference Mapping
3078  = ReferenceMappingProvider::get<elemDim, worldDim>(coarseROID, vCornerCoarse);
3079 
3080  std::vector<MathVector<elemDim> > vCoarseLocIP;
3081  vCoarseLocIP.resize(numIP);
3082  for(size_t ip = 0; ip < vCoarseLocIP.size(); ++ip) VecSet(vCoarseLocIP[ip], 0.0);
3083  map.global_to_local(&vCoarseLocIP[0], vFineGlobIP, numIP);
3084 
3085  try{
3086  // get trial space
3087  const LocalShapeFunctionSet<elemDim>& rFineLSFS =
3088  LocalFiniteElementProvider::get<elemDim>(fineROID, m_fineData.id());
3089  const LocalShapeFunctionSet<elemDim>& rCoarseLSFS =
3090  LocalFiniteElementProvider::get<elemDim>(coarseROID, m_coarseData.id());
3091 
3092  // get multiindices of element
3093  std::vector<DoFIndex> vFineMI, vCoarseMI;
3094  m_fineData.dof_indices(pFineElem, vFineMI);
3095  m_coarseData.dof_indices(pCoarseElem, vCoarseMI);
3096 
3097  std::vector<MathVector<elemDim> > vFineLocGradient(vFineMI.size());
3098  std::vector<MathVector<elemDim> > vCoarseLocGradient(vCoarseMI.size());
3099 
3100  // loop all integration points
3101  for(size_t ip = 0; ip < numIP; ++ip)
3102  {
3103  // compute shape gradients at ip
3104  rFineLSFS.grads(&vFineLocGradient[0], vFineLocIP[ip]);
3105  rCoarseLSFS.grads(&vCoarseLocGradient[0], vCoarseLocIP[ip]);
3106 
3107  // compute approximated solution at integration point
3108  number fineSolIP = 0.0;
3109  MathVector<elemDim> fineLocTmp; VecSet(fineLocTmp, 0.0);
3110  for(size_t sh = 0; sh < vFineMI.size(); ++sh)
3111  {
3112  const number val = DoFRef(m_fineData.grid_function(), vFineMI[sh]);
3113  fineSolIP += val * rFineLSFS.shape(sh, vFineLocIP[ip]);
3114  VecScaleAppend(fineLocTmp, val, vFineLocGradient[sh]);
3115  }
3116  number coarseSolIP = 0.0;
3117  MathVector<elemDim> coarseLocTmp; VecSet(coarseLocTmp, 0.0);
3118  for(size_t sh = 0; sh < vCoarseMI.size(); ++sh)
3119  {
3120  const number val = DoFRef(m_coarseData.grid_function(), vCoarseMI[sh]);
3121  coarseSolIP += val * rCoarseLSFS.shape(sh, vCoarseLocIP[ip]);
3122  VecScaleAppend(coarseLocTmp, val, vCoarseLocGradient[sh]);
3123  }
3124 
3125  // compute global gradient
3126  MathVector<worldDim> fineGradIP;
3128  RightInverse(fineJTInv, vJT[ip]);
3129  MatVecMult(fineGradIP, fineJTInv, fineLocTmp);
3130 
3131  // compute global gradient
3132  MathVector<worldDim> coarseGradIP;
3133  MathMatrix<worldDim, elemDim> coarseJTInv;
3134  map.jacobian_transposed_inverse(coarseJTInv, vCoarseLocIP[ip]);
3135  MatVecMult(coarseGradIP, coarseJTInv, coarseLocTmp);
3136 
3137  // get squared of difference
3138  vValue[ip] = (coarseSolIP - fineSolIP);
3139  vValue[ip] *= vValue[ip];
3140  vValue[ip] += VecDistanceSq(coarseGradIP, fineGradIP);
3141  }
3142 
3143  }
3144  UG_CATCH_THROW("H1DiffIntegrand::evaluate: trial space missing.");
3145  }
3146 };
3147 
3148 
3149 
3150 template <typename TGridFunction>
3151 number H1Distance2(TGridFunction& spGridFct1, const char* cmp1,
3152  TGridFunction& spGridFct2, const char* cmp2,
3153  int quadOrder, const char* subsets=NULL)
3154 {
3155  return GridFunctionDistance2<H1DistIntegrand<TGridFunction>, TGridFunction>
3156  (spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, subsets);
3157 }
3158 
3159 
3160 template <typename TGridFunction>
3161 number H1Distance(TGridFunction& spGridFct1, const char* cmp1,
3162  TGridFunction& spGridFct2, const char* cmp2,
3163  int quadOrder, const char* subsets=NULL)
3164 {
3165  return sqrt(H1Distance2(spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, subsets));
3166 }
3168 template <typename TGridFunction>
3169 number H1Error(SmartPtr<TGridFunction> spGridFct1, const char* cmp1,
3170  SmartPtr<TGridFunction> spGridFct2, const char* cmp2,
3171  int quadOrder, const char* subsets)
3172 {
3173  return H1Distance(*spGridFct1, cmp1, *spGridFct2, cmp2, quadOrder, subsets);
3174 }
3175 
3177 template <typename TGridFunction>
3178 number H1Error(SmartPtr<TGridFunction> spGridFct1, const char* cmp1,
3179  SmartPtr<TGridFunction> spGridFct2, const char* cmp2,
3180  int quadOrder)
3181 {
3182  return H1Distance(*spGridFct1, cmp1, *spGridFct2, cmp2, quadOrder, NULL);
3183 }
3184 
3185 
3187 // Standard Integrand
3189 
3190 template <typename TGridFunction>
3192  : public StdIntegrand<number, TGridFunction::dim, StdFuncIntegrand<TGridFunction> >
3193 {
3194  public:
3195  // world dimension of grid function
3196  static const int worldDim = TGridFunction::dim;
3197 
3198  private:
3199  // grid function
3200  TGridFunction* m_pGridFct;
3201 
3202  // component of function
3203  const size_t m_fct;
3204 
3205  public:
3207  StdFuncIntegrand(TGridFunction* pGridFct, size_t cmp)
3208  : m_pGridFct(pGridFct), m_fct(cmp)
3209  {};
3210 
3211  virtual ~StdFuncIntegrand(){}
3212 
3214  virtual void set_subset(int si)
3215  {
3216  if(!m_pGridFct->is_def_in_subset(m_fct, si))
3217  UG_THROW("L2ErrorIntegrand: Grid function component"
3218  <<m_fct<<" not defined on subset "<<si);
3220  }
3221 
3223  template <int elemDim>
3224  void evaluate(number vValue[],
3225  const MathVector<worldDim> vGlobIP[],
3226  GridObject* pElem,
3227  const MathVector<worldDim> vCornerCoords[],
3228  const MathVector<elemDim> vLocIP[],
3229  const MathMatrix<elemDim, worldDim> vJT[],
3230  const size_t numIP)
3231  {
3232  // get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
3234 
3235  const LFEID m_id = m_pGridFct->local_finite_element_id(m_fct);
3236 
3237  try{
3238  // get trial space
3239  const LocalShapeFunctionSet<elemDim>& rTrialSpace =
3240  LocalFiniteElementProvider::get<elemDim>(roid, m_id);
3241 
3242  // number of dofs on element
3243  const size_t num_sh = rTrialSpace.num_sh();
3244 
3245  // get multiindices of element
3246 
3247  std::vector<DoFIndex> ind; // aux. index array
3248  m_pGridFct->dof_indices(pElem, m_fct, ind);
3249 
3250  // check multi indices
3251  UG_COND_THROW(ind.size() != num_sh,
3252  "StdFuncIntegrand::evaluate: Wrong number of multi indices.");
3253 
3254  // loop all integration points
3255  for(size_t ip = 0; ip < numIP; ++ip)
3256  {
3257 
3258  // compute approximated solution at integration point
3259  number approxSolIP = 0.0;
3260  for(size_t sh = 0; sh < num_sh; ++sh)
3261  {
3262  // get value at shape point (e.g. corner for P1 fct)
3263  // and add shape fct at ip * value at shape
3264  const number valSH = DoFRef((*m_pGridFct), ind[sh]);
3265  approxSolIP += valSH * rTrialSpace.shape(sh, vLocIP[ip]);
3266  }
3267 
3268  // get function value at ip
3269  vValue[ip] = approxSolIP;
3270 
3271  }
3272 
3273  }
3274  UG_CATCH_THROW("StdFuncIntegrand::evaluate: trial space missing.");
3275  }
3276 };
3277 
3278 
3279 template <typename TGridFunction>
3280 number StdFuncIntegralOnVertex(TGridFunction& gridFct,
3281  size_t fct,
3282  int si)
3283 {
3284 // integrate elements of subset
3285  typedef typename TGridFunction::template dim_traits<0>::grid_base_object grid_base_object;
3286  typedef typename TGridFunction::template dim_traits<0>::const_iterator const_iterator;
3287 
3288  // reset the result
3289  number integral = 0;
3290 
3291 // note: this iterator is for the base elements, e.g. Face and not
3292 // for the special type, e.g. Triangle, Quadrilateral
3293  const_iterator iter = gridFct.template begin<grid_base_object>(si);
3294  const_iterator iterEnd = gridFct.template end<grid_base_object>(si);
3295 
3296 // iterate over all elements
3297  for(; iter != iterEnd; ++iter)
3298  {
3299  // get element
3300  grid_base_object* pElem = *iter;
3301 
3302  std::vector<DoFIndex> ind; // aux. index array
3303  gridFct.dof_indices(pElem, fct, ind);
3304 
3305  // compute approximated solution at integration point
3306  number value = 0.0;
3307  for(size_t sh = 0; sh < ind.size(); ++sh)
3308  {
3309  value += DoFRef(gridFct, ind[sh]);
3310  }
3311 
3312  // add to global sum
3313  integral += value;
3314 
3315  } // end elem
3316 
3317 // return the summed integral contributions of all elements
3318  return integral;
3319 }
3320 
3321 template <typename TGridFunction>
3323 { return StdFuncIntegralOnVertex(*spGridFct, fct, si); }
3324 
3325 
3326 template <typename TGridFunction>
3327 number Integral(TGridFunction& gridFct, const char* cmp,
3328  const char* subsets, int quadOrder)
3329 {
3330 // get function id of name
3331  const size_t fct = gridFct.fct_id_by_name(cmp);
3332 
3333 // check that function exists
3334  UG_COND_THROW(fct >= gridFct.num_fct(), "L2Norm: Function space does not contain"
3335  " a function with name " << cmp << ".");
3336 
3337 // read subsets
3338  SubsetGroup ssGrp(gridFct.domain()->subset_handler());
3339  if(subsets != NULL)
3340  {
3341  ssGrp.add(TokenizeString(subsets));
3342  if(!SameDimensionsInAllSubsets(ssGrp))
3343  UG_THROW("IntegrateSubsets: Subsets '"<<subsets<<"' do not have same dimension."
3344  "Can not integrate on subsets of different dimensions.");
3345  }
3346  else
3347  {
3348  // add all subsets and remove lower dim subsets afterwards
3349  ssGrp.add_all();
3350  RemoveLowerDimSubsets(ssGrp);
3351  }
3352 
3353  // \TODO: This should be generalite in IntegrateSubset instead of doing it directly here
3354  bool bOnlyVertex = true;
3355  for(size_t s = 0; s < ssGrp.size(); ++s)
3356  if(ssGrp.dim(s) != 0) bOnlyVertex = false;
3357 
3358  if(bOnlyVertex)
3359  {
3360  number value = 0;
3361  for(size_t s = 0; s < ssGrp.size(); ++s)
3362  value += StdFuncIntegralOnVertex(gridFct, fct, ssGrp[s]);
3363 
3364 #ifdef UG_PARALLEL
3365  // sum over processes
3366  if(pcl::NumProcs() > 1)
3367  {
3369  number local = value;
3370  com.allreduce(&local, &value, 1, PCL_DT_DOUBLE, PCL_RO_SUM);
3371  }
3372 #endif
3373  return value;
3374  }
3375 
3376  StdFuncIntegrand<TGridFunction> integrand(&gridFct, fct);
3377  return IntegrateSubsets(integrand, gridFct, subsets, quadOrder);
3378 }
3379 
3380 template <typename TGridFunction>
3381 number Integral(SmartPtr<TGridFunction> spGridFct, const char* cmp,
3382  const char* subsets, int quadOrder)
3383 { return Integral(*spGridFct, cmp, subsets, quadOrder); }
3384 
3385 
3386 template <typename TGridFunction>
3387 number Integral(SmartPtr<TGridFunction> spGridFct, const char* cmp,
3388  const char* subsets)
3389 {
3390  return Integral(spGridFct, cmp, subsets, 1);
3391 }
3392 template <typename TGridFunction>
3393 number Integral(SmartPtr<TGridFunction> spGridFct, const char* cmp)
3394 {
3395  return Integral(spGridFct, cmp, NULL, 1);
3396 }
3397 
3398 
3401 // Generic Boundary Integration Routine
3404 
3405 template <int WorldDim, int dim, typename TConstIterator>
3407  TConstIterator iterEnd,
3409  const ISubsetHandler* ish,
3410  IIntegrand<MathVector<WorldDim>, WorldDim>& integrand,
3411  const SubsetGroup& bndSSGrp)
3412 {
3413 // reset the result
3414  number integral = 0;
3415 
3416 // note: this iterator is for the base elements, e.g. Face and not
3417 // for the special type, e.g. Triangle, Quadrilateral
3418  TConstIterator iter = iterBegin;
3419 
3420 // this is the base element type (e.g. Face). This is the type when the
3421 // iterators above are dereferenciated.
3422  typedef typename domain_traits<dim>::grid_base_object grid_base_object;
3423 
3424 // create a FV1 Geometry
3425  DimFV1Geometry<dim> geo;
3426 
3427 // specify, which subsets are boundary
3428  for(size_t s = 0; s < bndSSGrp.size(); ++s)
3429  {
3430  // get subset index
3431  const int bndSubset = bndSSGrp[s];
3432 
3433  // request this subset index as boundary subset. This will force the
3434  // creation of boundary subsets when calling geo.update
3435  geo.add_boundary_subset(bndSubset);
3436  }
3437 
3438 // vector of corner coordinates of element corners (to be filled for each elem)
3439  std::vector<MathVector<WorldDim> > vCorner;
3440 
3441 // iterate over all elements
3442  for(; iter != iterEnd; ++iter)
3443  {
3444  // get element
3445  grid_base_object* pElem = *iter;
3446 
3447  // get all corner coordinates
3448  CollectCornerCoordinates(vCorner, *pElem, aaPos, true);
3449 
3450  // compute bf and grads at bip for element
3451  try{
3452  geo.update(pElem, &vCorner[0], ish);
3453  }
3454  UG_CATCH_THROW("IntegralNormalComponentOnManifold: "
3455  "Cannot update Finite Volume Geometry.");
3456 
3457  // specify, which subsets are boundary
3458  for(size_t s = 0; s < bndSSGrp.size(); ++s)
3459  {
3460  // get subset index
3461  const int bndSubset = bndSSGrp[s];
3462 
3463  // get all bf of this subset
3464  typedef typename DimFV1Geometry<dim>::BF BF;
3465  const std::vector<BF>& vBF = geo.bf(bndSubset);
3466 
3467  // loop boundary faces
3468  for(size_t b = 0; b < vBF.size(); ++b)
3469  {
3470  // get bf
3471  const BF& bf = vBF[b];
3472 
3473  // value
3474  MathVector<WorldDim> value;
3475 
3476  // jacobian
3478  Inverse(JT, bf.JTInv());
3479 
3480  // compute integrand values at integration points
3481  try
3482  {
3483  integrand.values(&value, &(bf.global_ip()),
3484  pElem, &vCorner[0], &(bf.local_ip()),
3485  &(JT),
3486  1);
3487  }
3488  UG_CATCH_THROW("IntegralNormalComponentOnManifold: Unable to compute values of "
3489  "integrand at integration point.");
3490 
3491  // sum up contribution (normal includes area)
3492  integral += VecDot(value, bf.normal());
3493 
3494  } // end bf
3495  } // end bnd subsets
3496  } // end elem
3497 
3498 // return the summed integral contributions of all elements
3499  return integral;
3500 }
3501 
3502 
3503 template <int WorldDim, int dim, typename TConstIterator>
3505  TConstIterator iterBegin,
3506  TConstIterator iterEnd,
3508  const ISubsetHandler* ish,
3509  IIntegrand<MathVector<WorldDim>, WorldDim>& integrand,
3510  const SubsetGroup& bndSSGrp,
3511  int quadOrder,
3512  Grid& grid)
3513 {
3514 // reset the result
3515  number integral = 0;
3516 
3517 // note: this iterator is for the base elements, e.g. Face and not
3518 // for the special type, e.g. Triangle, Quadrilateral
3519  TConstIterator iter = iterBegin;
3520 
3521 // this is the base element type (e.g. Face). This is the type when the
3522 // iterators above are dereferenciated.
3523  typedef typename domain_traits<dim>::element_type Element;
3524  typedef typename domain_traits<dim>::side_type Side;
3525 
3526 // vector of corner coordinates of element corners (to be filled for each elem)
3527  std::vector<MathVector<WorldDim> > vCorner;
3528  std::vector<int> vSubsetIndex;
3529 
3530 // iterate over all elements
3531  for(; iter != iterEnd; ++iter)
3532  {
3533  // get element
3534  Element* pElem = *iter;
3535 
3536  // get all corner coordinates
3537  CollectCornerCoordinates(vCorner, *pElem, aaPos, true);
3538 
3539  // get reference object id
3540  const ReferenceObjectID elemRoid = pElem->reference_object_id();
3541 
3542  // get sides
3543  typename Grid::traits<Side>::secure_container vSide;
3544  grid.associated_elements_sorted(vSide, pElem);
3545  vSubsetIndex.resize(vSide.size());
3546  for(size_t i = 0; i < vSide.size(); ++i)
3547  vSubsetIndex[i] = ish->get_subset_index(vSide[i]);
3548 
3550  = ReferenceMappingProvider::get<dim, WorldDim>(elemRoid, vCorner);
3551 
3552  const DimReferenceElement<dim>& rRefElem
3553  = ReferenceElementProvider::get<dim>(elemRoid);
3554 
3555  // loop sub elements
3556  for(size_t side = 0; side < vSide.size(); ++side)
3557  {
3558  // check if side used
3559  if(!bndSSGrp.contains(vSubsetIndex[side])) continue;
3560 
3561  // get side
3562  Side* pSide = vSide[side];
3563 
3564  std::vector<MathVector<WorldDim> > vSideCorner(rRefElem.num(dim-1, side, 0));
3565  std::vector<MathVector<dim> > vLocalSideCorner(rRefElem.num(dim-1, side, 0));
3566  for(size_t co = 0; co < vSideCorner.size(); ++co){
3567  vSideCorner[co] = vCorner[rRefElem.id(dim-1, side, 0, co)];
3568  vLocalSideCorner[co] = rRefElem.corner(rRefElem.id(dim-1, side, 0, co));
3569  }
3570 
3571  // side quad rule
3572  const ReferenceObjectID sideRoid = pSide->reference_object_id();
3573  const QuadratureRule<dim-1>& rSideQuadRule
3574  = QuadratureRuleProvider<dim-1>::get(sideRoid, quadOrder);
3575 
3576  // normal
3577  MathVector<WorldDim> Normal;
3578  ElementNormal<WorldDim>(sideRoid, Normal, &vSideCorner[0]);
3579 
3580  // quadrature points
3581  const number* vWeight = rSideQuadRule.weights();
3582  const size_t nip = rSideQuadRule.size();
3583  std::vector<MathVector<dim> > vLocalIP(nip);
3584  std::vector<MathVector<dim> > vGlobalIP(nip);
3585 
3586  DimReferenceMapping<dim-1, dim>& map
3587  = ReferenceMappingProvider::get<dim-1, dim>(sideRoid, vLocalSideCorner);
3588 
3589  for(size_t ip = 0; ip < nip; ++ip)
3590  map.local_to_global(vLocalIP[ip], rSideQuadRule.point(ip));
3591 
3592  for(size_t ip = 0; ip < nip; ++ip)
3593  rMapping.local_to_global(vGlobalIP[ip], vLocalIP[ip]);
3594 
3595  // compute transformation matrices
3596  std::vector<MathMatrix<dim-1, WorldDim> > vJT(nip);
3597  map.jacobian_transposed(&(vJT[0]), rSideQuadRule.points(), nip);
3598 
3599  std::vector<MathMatrix<dim, WorldDim> > vElemJT(nip);
3600  rMapping.jacobian_transposed(&(vElemJT[0]), &vLocalIP[0], nip);
3601 
3602  std::vector<MathVector<WorldDim> > vValue(nip);
3603 
3604  // compute integrand values at integration points
3605  try
3606  {
3607  integrand.values(&vValue[0], &vGlobalIP[0],
3608  pElem, &vCorner[0], &vLocalIP[0],
3609  &(vElemJT[0]),
3610  nip);
3611  }
3612  UG_CATCH_THROW("IntegralNormalComponentOnManifold: Unable to compute values of "
3613  "integrand at integration point.");
3614 
3615  // loop integration points
3616  for(size_t ip = 0; ip < nip; ++ip)
3617  {
3618  // get quadrature weight
3619  const number weightIP = vWeight[ip];
3620 
3621  // get determinate of mapping
3622  const number det = SqrtGramDeterminant(vJT[ip]);
3623 
3624  // add contribution of integration point
3625  integral += VecDot(vValue[ip], Normal) * weightIP * det;
3626  }
3627  } // end bf
3628  } // end elem
3629 
3630 // return the summed integral contributions of all elements
3631  return integral;
3632 }
3633 
3634 template <typename TGridFunction, int dim>
3636  SmartPtr<TGridFunction> spGridFct,
3637  int si, const SubsetGroup& bndSSGrp, int quadOrder)
3638 {
3639 // integrate elements of subset
3640  typedef typename TGridFunction::template dim_traits<dim>::grid_base_object grid_base_object;
3641  typedef typename TGridFunction::template dim_traits<dim>::const_iterator const_iterator;
3642  static const int WorldDim = TGridFunction::dim;
3643 
3644  spIntegrand->set_subset(si);
3645 
3646  if(quadOrder == 1)
3647  return IntegralNormalComponentOnManifoldUsingFV1Geom<WorldDim,dim,const_iterator>
3648  (spGridFct->template begin<grid_base_object>(si),
3649  spGridFct->template end<grid_base_object>(si),
3650  spGridFct->domain()->position_accessor(),
3651  spGridFct->domain()->subset_handler().get(),
3652  *spIntegrand, bndSSGrp);
3653  else{
3654  UG_LOG(" #### IntegralNormalComponentOnManifoldSubset ####:\n")
3655  return IntegralNormalComponentOnManifoldGeneral<WorldDim,dim,const_iterator>
3656  (spGridFct->template begin<grid_base_object>(si),
3657  spGridFct->template end<grid_base_object>(si),
3658  spGridFct->domain()->position_accessor(),
3659  spGridFct->domain()->subset_handler().get(),
3660  *spIntegrand, bndSSGrp, quadOrder, *spGridFct->domain()->grid());
3661  }
3662 }
3663 
3664 template <typename TGridFunction>
3667  SmartPtr<TGridFunction> spGridFct,
3668  const char* BndSubsets, const char* InnerSubsets,
3669  int quadOrder)
3670 {
3671 // world dimensions
3672  static const int dim = TGridFunction::dim;
3673 
3674 // read subsets
3675  SubsetGroup innerSSGrp(spGridFct->domain()->subset_handler());
3676  if(InnerSubsets != NULL)
3677  {
3678  innerSSGrp.add(TokenizeString(InnerSubsets));
3679  if(!SameDimensionsInAllSubsets(innerSSGrp))
3680  UG_THROW("IntegralNormalComponentOnManifold: Subsets '"<<InnerSubsets<<"' do not have same dimension."
3681  "Can not integrate on subsets of different dimensions.");
3682  }
3683  else
3684  {
3685  // add all subsets and remove lower dim subsets afterwards
3686  innerSSGrp.add_all();
3687  RemoveLowerDimSubsets(innerSSGrp);
3688  }
3689 
3690 // read subsets
3691  SubsetGroup bndSSGrp(spGridFct->domain()->subset_handler());
3692  if(BndSubsets != NULL)
3693  bndSSGrp.add(TokenizeString(BndSubsets));
3694  else
3695  UG_THROW("IntegralNormalComponentOnManifold: No boundary subsets passed.");
3696 
3697 // reset value
3698  number value = 0;
3699 
3700 // loop subsets
3701  for(size_t i = 0; i < innerSSGrp.size(); ++i)
3702  {
3703  // get subset index
3704  const int si = innerSSGrp[i];
3705 
3706  // check dimension
3707  if(innerSSGrp.dim(i) != dim && innerSSGrp.dim(i) != DIM_SUBSET_EMPTY_GRID)
3708  UG_THROW("IntegralNormalComponentOnManifold: Dimension of inner subset is "<<
3709  innerSSGrp.dim(i)<<", but only World Dimension "<<dim<<
3710  " subsets can be used for inner subsets.");
3711 
3712  // integrate elements of subset
3713  switch(innerSSGrp.dim(i))
3714  {
3715  case DIM_SUBSET_EMPTY_GRID: break;
3716  case dim: value += IntegralNormalComponentOnManifoldSubset<TGridFunction, dim>(spIntegrand, spGridFct, si, bndSSGrp, quadOrder); break;
3717  default: UG_THROW("IntegralNormalComponentOnManifold: Dimension "<<innerSSGrp.dim(i)<<" not supported. "
3718  " World dimension is "<<dim<<".");
3719  }
3720  }
3721 
3722 #ifdef UG_PARALLEL
3723  // sum over processes
3724  if(pcl::NumProcs() > 1)
3725  {
3727  number local = value;
3728  com.allreduce(&local, &value, 1, PCL_DT_DOUBLE, PCL_RO_SUM);
3729  }
3730 #endif
3731 
3732 // return the result
3733  return value;
3734 }
3735 
3736 template <typename TGridFunction>
3739  SmartPtr<TGridFunction> spGridFct,
3740  const char* BndSubset, const char* InnerSubset,
3741  number time,
3742  int quadOrder)
3743 {
3745  = make_sp(new UserDataIntegrand<MathVector<TGridFunction::dim>, TGridFunction>(spData, &(*spGridFct), time));
3746 
3747  return IntegralNormalComponentOnManifoldSubsets(spIntegrand, spGridFct, BndSubset, InnerSubset, quadOrder);
3748 }
3749 
3750 template <typename TGridFunction>
3753  SmartPtr<TGridFunction> spGridFct,
3754  const char* BndSubset, const char* InnerSubset,
3755  number time)
3756 {return IntegralNormalComponentOnManifold(spData, spGridFct, BndSubset, InnerSubset, time, 1);}
3757 
3758 template <typename TGridFunction>
3761  SmartPtr<TGridFunction> spGridFct,
3762  const char* BndSubset,
3763  number time)
3764 {return IntegralNormalComponentOnManifold(spData, spGridFct, BndSubset, NULL, time, 1);}
3765 
3766 template <typename TGridFunction>
3769  SmartPtr<TGridFunction> spGridFct,
3770  const char* BndSubset, const char* InnerSubset)
3771 {return IntegralNormalComponentOnManifold(spData, spGridFct, BndSubset, InnerSubset, 0.0, 1);}
3772 
3773 template <typename TGridFunction>
3776  SmartPtr<TGridFunction> spGridFct,
3777  const char* BndSubset)
3778 {return IntegralNormalComponentOnManifold(spData, spGridFct, BndSubset, NULL, 0.0, 1);}
3779 
3781 // lua data
3783 
3784 #ifdef UG_FOR_LUA
3785 template <typename TGridFunction>
3787  const char* luaFct, SmartPtr<TGridFunction> spGridFct,
3788  const char* BndSubset, const char* InnerSubset,
3789  number time, int quadOrder)
3790 {
3791  static const int dim = TGridFunction::dim;
3793  LuaUserDataFactory<MathVector<dim>, dim>::create(luaFct);
3794  return IntegralNormalComponentOnManifold(sp, spGridFct, BndSubset, InnerSubset, time, quadOrder);
3795 }
3796 
3797 template <typename TGridFunction>
3799  const char* luaFct, SmartPtr<TGridFunction> spGridFct,
3800  const char* BndSubset, const char* InnerSubset,
3801  number time)
3802 {return IntegralNormalComponentOnManifold(luaFct, spGridFct, BndSubset, InnerSubset, time, 1);}
3803 
3804 template <typename TGridFunction>
3806  const char* luaFct, SmartPtr<TGridFunction> spGridFct,
3807  const char* BndSubset,
3808  number time)
3809 {return IntegralNormalComponentOnManifold(luaFct, spGridFct, BndSubset, NULL, time, 1);}
3810 
3811 template <typename TGridFunction>
3813  const char* luaFct, SmartPtr<TGridFunction> spGridFct,
3814  const char* BndSubset, const char* InnerSubset)
3815 {return IntegralNormalComponentOnManifold(luaFct, spGridFct, BndSubset, InnerSubset, 0.0, 1);}
3816 
3817 template <typename TGridFunction>
3819  const char* luaFct, SmartPtr<TGridFunction> spGridFct,
3820  const char* BndSubset)
3821 {return IntegralNormalComponentOnManifold(luaFct, spGridFct, BndSubset, NULL, 0.0, 1);}
3822 #endif
3823 
3825 // Boundary Integral
3828 
3839 template <typename TGridFunction>
3840 number IntegrateNormalComponentOnManifold(TGridFunction& u, const char* cmp,
3841  const char* BndSubset)
3842 {
3843 // get function id of name
3844  const size_t fct = u.fct_id_by_name(cmp);
3845 
3846 // check that function exists
3847  if(fct >= u.num_fct())
3848  UG_THROW("IntegrateNormalComponentOnManifold: Function space does not contain"
3849  " a function with name " << cmp << ".");
3850 
3851  if(u.local_finite_element_id(fct) != LFEID(LFEID::LAGRANGE, TGridFunction::dim, 1))
3852  UG_THROW("IntegrateNormalComponentOnManifold:"
3853  "Only implemented for Lagrange P1 functions.");
3854 
3855 // read bnd subsets
3856  SubsetGroup bndSSGrp(u.domain()->subset_handler());
3857  bndSSGrp.add(TokenizeString(BndSubset));
3858 
3859 // reset value
3860  number value = 0;
3861 
3862 // loop subsets
3863  for(size_t i = 0; i < bndSSGrp.size(); ++i)
3864  {
3865  // get subset index
3866  const int si = bndSSGrp[i];
3867 
3868  // skip if function is not defined in subset
3869  if(!u.is_def_in_subset(fct, si)) continue;
3870 
3871  // create integration kernel
3872  static const int dim = TGridFunction::dim;
3873 
3874  // integrate elements of subset
3875  typedef typename domain_traits<dim>::grid_base_object grid_base_object;
3876 
3877  // get iterators for all elems on subset
3878  typedef typename TGridFunction::template dim_traits<dim>::const_iterator const_iterator;
3879  const_iterator iter = u.template begin<grid_base_object>();
3880  const_iterator iterEnd = u.template end<grid_base_object>();
3881 
3882  // create a FV1 Geometry
3883  DimFV1Geometry<dim> geo;
3884 
3885  // specify, which subsets are boundary
3886  for(size_t s = 0; s < bndSSGrp.size(); ++s)
3887  {
3888  // get subset index
3889  const int bndSubset = bndSSGrp[s];
3890 
3891  // request this subset index as boundary subset. This will force the
3892  // creation of boundary subsets when calling geo.update
3893  geo.add_boundary_subset(bndSubset);
3894  }
3895 
3896  // vector of corner coordinates of element corners (to be filled for each elem)
3897  std::vector<MathVector<dim> > vCorner;
3898 
3899  // loop elements of subset
3900  for( ; iter != iterEnd; ++iter)
3901  {
3902  // get element
3903  grid_base_object* elem = *iter;
3904 
3905  // get all corner coordinates
3906  CollectCornerCoordinates(vCorner, *elem, u.domain()->position_accessor(), true);
3907 
3908  // compute bf and grads at bip for element
3909  try{
3910  geo.update(elem, &vCorner[0], u.domain()->subset_handler().get());
3911  }
3912  UG_CATCH_THROW("IntegrateNormalComponenOnManifold: "
3913  "Cannot update Finite Volume Geometry.");
3914 
3915  // get fct multi-indices of element
3916  std::vector<DoFIndex> ind;
3917  u.dof_indices(elem, fct, ind);
3918 
3919  // specify, which subsets are boundary
3920  for(size_t s = 0; s < bndSSGrp.size(); ++s)
3921  {
3922  // get subset index
3923  const int bndSubset = bndSSGrp[s];
3924 
3925  // get all bf of this subset
3926  typedef typename DimFV1Geometry<dim>::BF BF;
3927  const std::vector<BF>& vBF = geo.bf(bndSubset);
3928 
3929  // loop boundary faces
3930  for(size_t b = 0; b < vBF.size(); ++b)
3931  {
3932  // get bf
3933  const BF& bf = vBF[b];
3934 
3935  // get normal on bf
3936  const MathVector<dim>& normal = bf.normal();
3937 
3938  // check multi indices
3939  UG_ASSERT(ind.size() == bf.num_sh(),
3940  "IntegrateNormalComponentOnManifold::values: Wrong number of"
3941  " multi indices, ind: "<<ind.size() << ", bf.num_sh: "
3942  << bf.num_sh());
3943 
3944  MathVector<dim> val; VecSet(val, 0.0);
3945  for(size_t sh = 0; sh < bf.num_sh(); ++sh)
3946  {
3947  const number fctVal = DoFRef(u, ind[sh]);
3948  const MathVector<dim>& ip = bf.global_ip();
3949  VecScaleAdd(val, 1.0, val, fctVal, ip);
3950  }
3951 
3952  // sum up contributions
3953  value -= VecDot(val, normal);
3954  }
3955  }
3956  }
3957  }
3958 
3959 #ifdef UG_PARALLEL
3960  // sum over processes
3961  if(pcl::NumProcs() > 1)
3962  {
3964  number local = value;
3965  com.allreduce(&local, &value, 1, PCL_DT_DOUBLE, PCL_RO_SUM);
3966  }
3967 #endif
3968 
3969 // return the result
3970  return value;
3971 }
3972 
3974 
3988 template <typename TGridFunction>
3989 number IntegrateNormalGradientOnManifold(TGridFunction& u, const char* cmp,
3990  const char* BndSubset, const char* InnerSubset = NULL)
3991 {
3992 // get function id of name
3993  const size_t fct = u.fct_id_by_name(cmp);
3994 
3995 // check that function exists
3996  if(fct >= u.num_fct())
3997  UG_THROW("IntegrateNormalGradientOnManifold: Function space does not contain"
3998  " a function with name " << cmp << ".");
3999 
4000  if(u.local_finite_element_id(fct) != LFEID(LFEID::LAGRANGE, TGridFunction::dim, 1))
4001  UG_THROW("IntegrateNormalGradientOnManifold:"
4002  "Only implemented for Lagrange P1 functions.");
4003 
4004 // read subsets
4005  SubsetGroup innerSSGrp(u.domain()->subset_handler());
4006  if(InnerSubset != NULL)
4007  innerSSGrp.add(TokenizeString(InnerSubset));
4008  else // add all if no subset specified
4009  innerSSGrp.add_all();
4010 
4011 // read bnd subsets
4012  SubsetGroup bndSSGrp(u.domain()->subset_handler());
4013  if(InnerSubset != NULL){
4014  bndSSGrp.add(TokenizeString(BndSubset));
4015  }
4016  else{
4017  UG_THROW("IntegrateNormalGradientOnManifold: No boundary subsets specified. Aborting.");
4018  }
4019 
4020 // reset value
4021  number value = 0;
4022 
4023 // loop subsets
4024  for(size_t i = 0; i < innerSSGrp.size(); ++i)
4025  {
4026  // get subset index
4027  const int si = innerSSGrp[i];
4028 
4029  // skip if function is not defined in subset
4030  if(!u.is_def_in_subset(fct, si)) continue;
4031 
4032 
4033  if (innerSSGrp.dim(i) != TGridFunction::dim)
4034  UG_THROW("IntegrateNormalGradientOnManifold: Element dimension does not match world dimension!");
4035 
4036  // create integration kernel
4037  static const int dim = TGridFunction::dim;
4038 
4039  // integrate elements of subset
4040  typedef typename domain_traits<dim>::grid_base_object grid_base_object;
4041 
4042  // get iterators for all elems on subset
4043  typedef typename TGridFunction::template dim_traits<dim>::const_iterator const_iterator;
4044  const_iterator iter = u.template begin<grid_base_object>();
4045  const_iterator iterEnd = u.template end<grid_base_object>();
4046 
4047  // create a FV1 Geometry
4048  DimFV1Geometry<dim> geo;
4049 
4050  // specify, which subsets are boundary
4051  for(size_t s = 0; s < bndSSGrp.size(); ++s)
4052  {
4053  // get subset index
4054  const int bndSubset = bndSSGrp[s];
4055 
4056  // request this subset index as boundary subset. This will force the
4057  // creation of boundary subsets when calling geo.update
4058  geo.add_boundary_subset(bndSubset);
4059  }
4060 
4061  // vector of corner coordinates of element corners (to be filled for each elem)
4062  std::vector<MathVector<dim> > vCorner;
4063 
4064  // loop elements of subset
4065  for( ; iter != iterEnd; ++iter)
4066  {
4067  // get element
4068  grid_base_object* elem = *iter;
4069 
4070  // get all corner coordinates
4071  CollectCornerCoordinates(vCorner, *elem, u.domain()->position_accessor(), true);
4072 
4073  // compute bf and grads at bip for element
4074  try{
4075  geo.update(elem, &vCorner[0], u.domain()->subset_handler().get());
4076  }
4077  UG_CATCH_THROW("IntegrateNormalGradientOnManifold: "
4078  "Cannot update Finite Volume Geometry.");
4079 
4080  // get fct multi-indeces of element
4081  std::vector<DoFIndex> ind;
4082  u.dof_indices(elem, fct, ind);
4083 
4084  // specify, which subsets are boundary
4085  for(size_t s = 0; s < bndSSGrp.size(); ++s)
4086  {
4087  // get subset index
4088  const int bndSubset = bndSSGrp[s];
4089 
4090  // get all bf of this subset
4091  typedef typename DimFV1Geometry<dim>::BF BF;
4092  const std::vector<BF>& vBF = geo.bf(bndSubset);
4093 
4094  // loop boundary faces
4095  for(size_t b = 0; b < vBF.size(); ++b)
4096  {
4097  // get bf
4098  const BF& bf = vBF[b];
4099 
4100  // get normal on bf
4101  const MathVector<dim>& normal = bf.normal();
4102 
4103  // check multi indices
4104  UG_ASSERT(ind.size() == bf.num_sh(),
4105  "IntegrateNormalGradientOnManifold::values: Wrong number of"
4106  " multi indices, ind: "<<ind.size() << ", bf.num_sh: "
4107  << bf.num_sh());
4108 
4109  // compute gradient of solution at bip
4110  MathVector<dim> grad; VecSet(grad, 0.0);
4111  for(size_t sh = 0; sh < bf.num_sh(); ++sh)
4112  {
4113  const number fctVal = DoFRef(u, ind[sh]);
4114 
4115  VecScaleAdd(grad, 1.0, grad, fctVal, bf.global_grad(sh));
4116  }
4117 
4118  // sum up contributions
4119  value -= VecDot(grad, normal);
4120  }
4121  }
4122  }
4123  }
4124 
4125 #ifdef UG_PARALLEL
4126  // sum over processes
4127  if(pcl::NumProcs() > 1)
4128  {
4130  number local = value;
4131  com.allreduce(&local, &value, 1, PCL_DT_DOUBLE, PCL_RO_SUM);
4132  }
4133 #endif
4134 
4135 // return the result
4136  return value;
4137 }
4138 
4139 } // namespace ug
4140 
4141 #endif /*__H__UG__LIB_DISC__FUNCTION_SPACES__INTEGRATE__*/
parameterString s
bool valid() const
returns true if the pointer is valid, false if not.
Definition: smart_pointer.h:414
T * get()
returns encapsulated pointer
Definition: smart_pointer.h:197
Definition: pcl_process_communicator.h:70
void allreduce(const void *sendBuf, void *recBuf, int count, DataType type, ReduceOperation op) const
performs MPI_Allreduce on the processes of the communicator.
Definition: pcl_process_communicator.cpp:318
bool valid() const
Definition: attachment_pipe.h:553
constant matrix user data
Definition: const_user_data.h:232
constant scalar user data
Definition: const_user_data.h:153
boundary face
Definition: fv1_geom.h:903
Geometry and shape functions for 1st order Vertex-Centered Finite Volume.
Definition: fv1_geom.h:665
const BF & bf(int si, size_t i) const
returns the boundary face i for subsetIndex
Definition: fv1_geom.h:1135
void update(GridObject *elem, const MathVector< worldDim > *vCornerCoords, const ISubsetHandler *ish=NULL)
update data for given element
Definition: fv1_geom.cpp:669
void add_boundary_subset(int subsetIndex)
add subset that is interpreted as boundary subset.
Definition: fv1_geom.h:1104
const MathVector< dim > & corner(size_t i) const
coordinates of reference corner (i = 0 ... num(0))
Definition: reference_element.h:192
virtual base class for reference mappings
Definition: reference_mapping_provider.h:53
virtual void jacobian_transposed(MathMatrix< dim, worldDim > &JT, const MathVector< dim > &locPos) const =0
returns transposed of jacobian
virtual number jacobian_transposed_inverse(MathMatrix< worldDim, dim > &JTInv, const MathVector< dim > &locPos) const =0
returns transposed of the inverse of the jacobian and returns sqrt of gram determinante
virtual void local_to_global(MathVector< worldDim > &globPos, const MathVector< dim > &locPos) const =0
map local coordinate to global coordinate
virtual void update(const MathVector< worldDim > *vCornerCoord)=0
refresh mapping for new set of corners
virtual void global_to_local(MathVector< dim > &locPos, const MathVector< worldDim > &globPos, const size_t maxIter=1000, const number tol=1e-10) const =0
map global coordinate to local coordinate
the generic attachment-accessor for access to grids attachment pipes.
Definition: grid.h:182
Manages the elements of a grid and their interconnection.
Definition: grid.h:132
void associated_elements_sorted(traits< Vertex >::secure_container &elemsOut, TElem *e)
Puts all elements of type TAss which are contained in 'e' into elemsOut in the reference elements ord...
Definition: grid_impl.hpp:503
The base class for all geometric objects, such as vertices, edges, faces, volumes,...
Definition: grid_base_objects.h:157
virtual ReferenceObjectID reference_object_id() const =0
Integrand for the distance of two grid functions - evaluated in the H1 norm.
Definition: integrate.h:2998
const int m_fineTopLevel
Definition: integrate.h:3005
const int m_coarseTopLevel
Definition: integrate.h:3008
ScalarGridFunctionData< TGridFunction > m_fineData
Definition: integrate.h:3004
SmartPtr< MultiGrid > m_spMG
multigrid
Definition: integrate.h:3011
virtual ~H1DistIntegrand()
DTOR.
Definition: integrate.h:3032
ScalarGridFunctionData< TGridFunction > m_coarseData
Definition: integrate.h:3007
static const int worldDim
world dimension of grid function
Definition: integrate.h:3001
virtual void set_subset(int si)
sets subset
Definition: integrate.h:3035
H1DistIntegrand(TGridFunction &fineGridFct, size_t fineCmp, TGridFunction &coarseGridFct, size_t coarseCmp)
constructor (1 is fine grid function)
Definition: integrate.h:3015
void evaluate(number vValue[], const MathVector< worldDim > vFineGlobIP[], GridObject *pFineElem, const MathVector< worldDim > vCornerCoords[], const MathVector< elemDim > vFineLocIP[], const MathMatrix< elemDim, worldDim > vJT[], const size_t numIP)
returns the values of the integrand for a bunch of ips
Definition: integrate.h:3048
Integrand for the distance of two grid functions - evaluated in the norm .
Definition: integrate.h:2609
ConstSmartPtr< weight_type > m_spWeight
scalar weight (optional)
Definition: integrate.h:2626
static const int worldDim
world dimension of grid function
Definition: integrate.h:2612
SmartPtr< MultiGrid > m_spMG
multigrid
Definition: integrate.h:2623
H1SemiIntegrand< TGridFunction >::weight_type weight_type
Definition: integrate.h:2613
virtual void set_subset(int si)
sets subset
Definition: integrate.h:2666
ScalarGridFunctionData< TGridFunction > m_fineData
Definition: integrate.h:2616
virtual ~H1EnergyDistIntegrand()
Definition: integrate.h:2663
void evaluate(number vValue[], const MathVector< worldDim > vFineGlobIP[], GridObject *pFineElem, const MathVector< worldDim > vCornerCoords[], const MathVector< elemDim > vFineLocIP[], const MathMatrix< elemDim, worldDim > vJT[], const size_t numIP)
returns the values of the integrand for a bunch of ips
Definition: integrate.h:2679
const int m_fineTopLevel
Definition: integrate.h:2617
ScalarGridFunctionData< TGridFunction > m_coarseData
Definition: integrate.h:2619
H1EnergyDistIntegrand(TGridFunction &fineGridFct, size_t fineCmp, TGridFunction &coarseGridFct, size_t coarseCmp, ConstSmartPtr< weight_type > spWeight)
constructor
Definition: integrate.h:2647
H1EnergyDistIntegrand(TGridFunction &fineGridFct, size_t fineCmp, TGridFunction &coarseGridFct, size_t coarseCmp)
constructor
Definition: integrate.h:2630
const int m_coarseTopLevel
Definition: integrate.h:2620
Norm of a grid function, evaluated in (weighted) H1-semi norm.
Definition: integrate.h:2414
ConstSmartPtr< weight_type > m_spWeight
scalar weight (optional)
Definition: integrate.h:2425
virtual void set_subset(int si)
sets subset
Definition: integrate.h:2440
static const int worldDim
world dimension of grid function
Definition: integrate.h:2417
UserData< MathMatrix< worldDim, worldDim >, worldDim > weight_type
Definition: integrate.h:2418
ScalarGridFunctionData< TGridFunction > m_scalarData
grid function data
Definition: integrate.h:2422
virtual ~H1EnergyIntegrand()
DTOR.
Definition: integrate.h:2437
H1EnergyIntegrand(TGridFunction &gridFct, size_t cmp, ConstSmartPtr< weight_type > spWeight)
constructor
Definition: integrate.h:2433
H1EnergyIntegrand(TGridFunction &gridFct, size_t cmp)
constructor
Definition: integrate.h:2429
void evaluate(number vValue[], const MathVector< worldDim > vGlobIP[], GridObject *pElem, const MathVector< worldDim > vCornerCoords[], const MathVector< elemDim > vLocIP[], const MathMatrix< elemDim, worldDim > vJT[], const size_t numIP)
returns the values of the integrand for a bunch of ips
Definition: integrate.h:2450
Definition: integrate.h:1245
virtual void set_subset(int si)
sets subset
Definition: integrate.h:1276
SmartPtr< UserData< MathVector< worldDim >, worldDim > > m_spExactGrad
exact gradient
Definition: integrate.h:1258
H1ErrorIntegrand(SmartPtr< UserData< number, worldDim > > spExactSol, SmartPtr< UserData< MathVector< worldDim >, worldDim > > spExactGrad, TGridFunction &gridFct, size_t cmp, number time)
constructor
Definition: integrate.h:1265
ScalarGridFunctionData< TGridFunction > m_scalarData
grid function
Definition: integrate.h:1252
SmartPtr< UserData< number, worldDim > > m_spExactSolution
exact solution
Definition: integrate.h:1255
static const int worldDim
world dimension of grid function
Definition: integrate.h:1248
void evaluate(number vValue[], const MathVector< worldDim > vGlobIP[], GridObject *pElem, const MathVector< worldDim > vCornerCoords[], const MathVector< elemDim > vLocIP[], const MathMatrix< elemDim, worldDim > vJT[], const size_t numIP)
returns the values of the integrand for a bunch of ips
Definition: integrate.h:1286
number m_time
time
Definition: integrate.h:1261
Definition: integrate.h:2858
void evaluate(number vValue[], const MathVector< worldDim > vGlobIP[], GridObject *pElem, const MathVector< worldDim > vCornerCoords[], const MathVector< elemDim > vLocIP[], const MathMatrix< elemDim, worldDim > vJT[], const size_t numIP)
returns the values of the integrand for a bunch of ips
Definition: integrate.h:2885
ScalarGridFunctionData< TGridFunction > m_scalarData
Definition: integrate.h:2864
virtual ~H1NormIntegrand()
DTOR.
Definition: integrate.h:2872
virtual void set_subset(int si)
sets subset
Definition: integrate.h:2875
static const int worldDim
world dimension of grid function
Definition: integrate.h:2861
H1NormIntegrand(TGridFunction &gridFct, size_t cmp)
CTOR.
Definition: integrate.h:2868
Integrand for the distance of two grid functions - evaluated in the (weighted) H1-semi norm.
Definition: integrate.h:2140
void evaluate(number vValue[], const MathVector< worldDim > vFineGlobIP[], GridObject *pFineElem, const MathVector< worldDim > vCornerCoords[], const MathVector< elemDim > vFineLocIP[], const MathMatrix< elemDim, worldDim > vJT[], const size_t numIP)
returns the values of the integrand for a bunch of ips
Definition: integrate.h:2206
H1SemiDistIntegrand(TGridFunction &fineGridFct, size_t fineCmp, TGridFunction &coarseGridFct, size_t coarseCmp, ConstSmartPtr< weight_type > spWeight)
constructor
Definition: integrate.h:2178
const int m_fineTopLevel
Definition: integrate.h:2148
H1SemiDistIntegrand(TGridFunction &fineGridFct, size_t fineCmp, TGridFunction &coarseGridFct, size_t coarseCmp)
constructor
Definition: integrate.h:2161
ScalarGridFunctionData< TGridFunction > m_fineData
Definition: integrate.h:2147
virtual ~H1SemiDistIntegrand()
Definition: integrate.h:2191
ConstSmartPtr< weight_type > m_spWeight
scalar weight (optional)
Definition: integrate.h:2157
H1SemiIntegrand< TGridFunction >::weight_type weight_type
Definition: integrate.h:2144
virtual void set_subset(int si)
sets subset
Definition: integrate.h:2194
static const int worldDim
world dimension of grid function
Definition: integrate.h:2143
SmartPtr< MultiGrid > m_spMG
multigrid
Definition: integrate.h:2154
ScalarGridFunctionData< TGridFunction > m_coarseData
Definition: integrate.h:2150
const int m_coarseTopLevel
Definition: integrate.h:2151
Norm of a grid function, evaluated in (weighted) H1-semi norm.
Definition: integrate.h:1942
UserData< MathMatrix< worldDim, worldDim >, worldDim > weight_type
Definition: integrate.h:1946
void evaluate(number vValue[], const MathVector< worldDim > vGlobIP[], GridObject *pElem, const MathVector< worldDim > vCornerCoords[], const MathVector< elemDim > vLocIP[], const MathMatrix< elemDim, worldDim > vJT[], const size_t numIP)
returns the values of the integrand for a bunch of ips
Definition: integrate.h:1978
static const int worldDim
world dimension of grid function
Definition: integrate.h:1945
H1SemiIntegrand(TGridFunction &gridFct, size_t cmp, ConstSmartPtr< weight_type > spWeight)
constructor
Definition: integrate.h:1961
ScalarGridFunctionData< TGridFunction > m_scalarData
grid function data
Definition: integrate.h:1950
ConstSmartPtr< weight_type > m_spWeight
scalar weight (optional)
Definition: integrate.h:1953
virtual void set_subset(int si)
sets subset
Definition: integrate.h:1968
H1SemiIntegrand(TGridFunction &gridFct, size_t cmp)
constructor
Definition: integrate.h:1957
virtual ~H1SemiIntegrand()
DTOR.
Definition: integrate.h:1965
Abstract integrand interface.
Definition: integrate.h:121
virtual void values(TData vValue[], const MathVector< worldDim > vGlobIP[], GridObject *pElem, const MathVector< worldDim > vCornerCoords[], const MathVector< 1 > vLocIP[], const MathMatrix< 1, worldDim > vJT[], const size_t numIP)=0
returns the values of the integrand for a bunch of ips
virtual void set_subset(int si)
sets the subset
Definition: integrate.h:168
static const int worldDim
world dimension
Definition: integrate.h:124
int subset() const
returns the subset
Definition: integrate.h:171
virtual void values(TData vValue[], const MathVector< worldDim > vGlobIP[], GridObject *pElem, const MathVector< worldDim > vCornerCoords[], const MathVector< 3 > vLocIP[], const MathMatrix< 3, worldDim > vJT[], const size_t numIP)=0
returns the values of the integrand for a bunch of ips
int m_si
subset
Definition: integrate.h:175
TData data_type
data type
Definition: integrate.h:127
virtual void values(TData vValue[], const MathVector< worldDim > vGlobIP[], GridObject *pElem, const MathVector< worldDim > vCornerCoords[], const MathVector< 2 > vLocIP[], const MathMatrix< 2, worldDim > vJT[], const size_t numIP)=0
returns the values of the integrand for a bunch of ips
virtual ~IIntegrand()
Definition: integrate.h:164
Definition: subset_handler_interface.h:223
int get_subset_index(GridObject *elem) const
Definition: subset_handler_interface.cpp:560
Integrand for the distance of two grid functions - evaluated in the (weighted) H1-semi norm.
Definition: integrate.h:1716
const int m_coarseTopLevel
Definition: integrate.h:1727
void evaluate(number vValue[], const MathVector< worldDim > vFineGlobIP[], GridObject *pFineElem, const MathVector< worldDim > vCornerCoords[], const MathVector< elemDim > vFineLocIP[], const MathMatrix< elemDim, worldDim > vJT[], const size_t numIP)
returns the values of the integrand for a bunch of ips
Definition: integrate.h:1796
virtual ~L2DistIntegrand()
Definition: integrate.h:1782
double m_deltaFineCoarse
shift
Definition: integrate.h:1735
static const int worldDim
world dimension of grid function
Definition: integrate.h:1719
L2DistIntegrand(TGridFunction &fineGridFct, size_t fineCmp, TGridFunction &coarseGridFct, size_t coarseCmp, ConstSmartPtr< weight_type > spWeight)
constructor (1st is fine grid function)
Definition: integrate.h:1754
ConstSmartPtr< weight_type > m_spWeight
Definition: integrate.h:1732
const int m_fineTopLevel
Definition: integrate.h:1724
L2DistIntegrand(TGridFunction &fineGridFct, size_t fineCmp, TGridFunction &coarseGridFct, size_t coarseCmp)
constructor (1st is fine grid function)
Definition: integrate.h:1740
ScalarGridFunctionData< TGridFunction > m_coarseData
Definition: integrate.h:1726
L2DistIntegrand(TGridFunction &fineGridFct, size_t fineCmp, TGridFunction &coarseGridFct, size_t coarseCmp, ConstSmartPtr< weight_type > spWeight, number dist12)
constructor (1st is fine grid function)
Definition: integrate.h:1768
virtual void set_subset(int si)
sets subset
Definition: integrate.h:1785
L2Integrand< TGridFunction >::weight_type weight_type
Definition: integrate.h:1720
SmartPtr< MultiGrid > m_spMG
multigrid
Definition: integrate.h:1730
ScalarGridFunctionData< TGridFunction > m_fineData
Definition: integrate.h:1723
Definition: integrate.h:1073
L2ErrorIntegrand(SmartPtr< UserData< number, worldDim > > spExactSol, TGridFunction &gridFct, size_t cmp, number time)
constructor
Definition: integrate.h:1089
static const int worldDim
world dimension of grid function
Definition: integrate.h:1076
number m_time
time
Definition: integrate.h:1085
ScalarGridFunctionData< TGridFunction > m_scalarData
Definition: integrate.h:1079
SmartPtr< UserData< number, worldDim > > m_spExactSolution
exact solution
Definition: integrate.h:1082
virtual void set_subset(int si)
sets subset
Definition: integrate.h:1099
virtual ~L2ErrorIntegrand()
Definition: integrate.h:1096
void evaluate(number vValue[], const MathVector< worldDim > vGlobIP[], GridObject *pElem, const MathVector< worldDim > vCornerCoords[], const MathVector< elemDim > vLocIP[], const MathMatrix< elemDim, worldDim > vJT[], const size_t numIP)
returns the values of the integrand for a bunch of ips
Definition: integrate.h:1109
Grid function as L2 integrand.
Definition: integrate.h:1549
ScalarGridFunctionData< TGridFunction > m_scalarData
Definition: integrate.h:1557
virtual void set_subset(int si)
sets subset
Definition: integrate.h:1576
UserData< number, worldDim > weight_type
Definition: integrate.h:1553
L2Integrand(TGridFunction &spGridFct, size_t cmp, ConstSmartPtr< weight_type > spWeight)
Definition: integrate.h:1568
virtual ~L2Integrand()
DTOR.
Definition: integrate.h:1573
void evaluate(number vValue[], const MathVector< worldDim > vGlobIP[], GridObject *pElem, const MathVector< worldDim > vCornerCoords[], const MathVector< elemDim > vLocIP[], const MathMatrix< elemDim, worldDim > vJT[], const size_t numIP)
returns the values of the integrand for a bunch of ips
Definition: integrate.h:1585
static const int worldDim
Definition: integrate.h:1552
L2Integrand(TGridFunction &spGridFct, size_t cmp)
CTOR.
Definition: integrate.h:1564
ConstSmartPtr< weight_type > m_spWeight
scalar weight (optional, default is 1.0)
Definition: integrate.h:1560
Identifier for Local Finite Elements.
Definition: local_finite_element_id.h:98
@ LAGRANGE
Definition: local_finite_element_id.h:104
virtual size_t num_sh() const
Definition: local_dof_set.cpp:46
Definition: local_algebra.h:50
virtual base class for local shape function sets
Definition: local_shape_function_set.h:70
virtual void grads(grad_type *vGrad, const MathVector< dim > &x) const =0
returns all gradients evaluated at a point
virtual shape_type shape(size_t i, const MathVector< dim > &x) const =0
evaluates the shape function
Definition: local_algebra.h:198
void resize(const LocalIndices &ind)
resize for current local indices
Definition: local_algebra.h:214
static SmartPtr< LuaUserData< TData, dim, TRet > > create(const std::string &name)
Definition: lua_user_data.h:223
A class for fixed size, dense matrices.
Definition: math_matrix.h:52
Definition: integrate.h:965
ScalarGridFunctionData< TGridFunction > m_scalarData
Definition: integrate.h:971
double max()
Definition: integrate.h:1001
virtual void set_subset(int si)
sets subset
Definition: integrate.h:987
static const int worldDim
world dimension of grid function
Definition: integrate.h:968
MaximumDistIntegrand(TGridFunction &gridFct, size_t cmp)
constructor
Definition: integrate.h:977
void reset()
Definition: integrate.h:994
double m_min
Definition: integrate.h:973
double min()
Definition: integrate.h:1000
void evaluate(number vValue[], const MathVector< worldDim > vGlobIP[], GridObject *pElem, const MathVector< worldDim > vCornerCoords[], const MathVector< elemDim > vLocIP[], const MathMatrix< elemDim, worldDim > vJT[], const size_t numIP)
returns the values of the integrand for a bunch of ips
Definition: integrate.h:1005
double m_max
Definition: integrate.h:973
virtual ~MaximumDistIntegrand()
Definition: integrate.h:984
Container which holds an array of pointers.
Definition: pointer_const_array.h:84
size_t size() const
returns the size of the associated array.
Definition: pointer_const_array_impl.hpp:106
number weight(size_t i) const
return the i'th weight
Definition: quadrature.h:105
const MathVector< dim > * points() const
returns all positions in an array of size()
Definition: quadrature.h:102
size_t size() const
number of integration points
Definition: quadrature.h:92
static const QuadratureRule< TDim > & get(size_t order, QuadType type=BEST)
gets quadrature rule of requested order
Definition: quadrature_provider_impl.h:40
size_t num(int dim) const
returns the number of geometric objects of dim
Definition: reference_element.h:95
int id(int dim_i, size_t i, int dim_j, size_t j) const
id of object j in dimension dim_j of obj i in dimension dim_i
Definition: reference_element.h:127
static DimReferenceMapping< TDim, TWorldDim > & get(ReferenceObjectID roid)
returns a reference to a DimReferenceMapping
Definition: reference_mapping_provider.h:225
Definition: integrate.h:66
TGridFunction::domain_type domain_type
Definition: integrate.h:68
TGridFunction & grid_function()
Definition: integrate.h:75
size_t m_fct
component of function
Definition: integrate.h:106
size_t fct()
Definition: integrate.h:81
TGridFunction & m_gridFct
grid function
Definition: integrate.h:103
ConstSmartPtr< domain_type > domain() const
returns const domain (forward)
Definition: integrate.h:95
ScalarGridFunctionData(TGridFunction &gridFct, size_t cmp)
Definition: integrate.h:70
SmartPtr< domain_type > domain()
returns domain (forward)
Definition: integrate.h:92
size_t dof_indices(TElem *elem, std::vector< DoFIndex > &ind, bool bHang=false, bool bClear=true) const
Definition: integrate.h:98
LFEID m_id
local finite element id
Definition: integrate.h:109
const TGridFunction & grid_function() const
Definition: integrate.h:78
const LFEID & id() const
Definition: integrate.h:84
bool is_def_in_subset(int si) const
returns true, iff scalar function is defined in subset si
Definition: integrate.h:88
Definition: integrate.h:3193
const size_t m_fct
Definition: integrate.h:3203
virtual void set_subset(int si)
sets subset
Definition: integrate.h:3214
TGridFunction * m_pGridFct
Definition: integrate.h:3200
static const int worldDim
Definition: integrate.h:3196
virtual ~StdFuncIntegrand()
Definition: integrate.h:3211
StdFuncIntegrand(TGridFunction *pGridFct, size_t cmp)
constructor
Definition: integrate.h:3207
void evaluate(number vValue[], const MathVector< worldDim > vGlobIP[], GridObject *pElem, const MathVector< worldDim > vCornerCoords[], const MathVector< elemDim > vLocIP[], const MathMatrix< elemDim, worldDim > vJT[], const size_t numIP)
returns the values of the integrand for a bunch of ips
Definition: integrate.h:3224
Abstract integrand interface (using CRTP)
Definition: integrate.h:181
TImpl & getImpl()
access to implementation
Definition: integrate.h:225
virtual void values(TData vValue[], const MathVector< worldDim > vGlobIP[], GridObject *pElem, const MathVector< worldDim > vCornerCoords[], const MathVector< 1 > vLocIP[], const MathMatrix< 1, worldDim > vJT[], const size_t numIP)
returns the values of the integrand for a bunch of ips
Definition: integrate.h:191
virtual void values(TData vValue[], const MathVector< worldDim > vGlobIP[], GridObject *pElem, const MathVector< worldDim > vCornerCoords[], const MathVector< 2 > vLocIP[], const MathMatrix< 2, worldDim > vJT[], const size_t numIP)
returns the values of the integrand for a bunch of ips
Definition: integrate.h:201
static const int worldDim
world dimension
Definition: integrate.h:184
TData data_type
data type
Definition: integrate.h:187
virtual void values(TData vValue[], const MathVector< worldDim > vGlobIP[], GridObject *pElem, const MathVector< worldDim > vCornerCoords[], const MathVector< 3 > vLocIP[], const MathMatrix< 3, worldDim > vJT[], const size_t numIP)
returns the values of the integrand for a bunch of ips
Definition: integrate.h:211
const TImpl & getImpl() const
const access to implementation
Definition: integrate.h:228
Group of subsets.
Definition: subset_group.h:51
size_t size() const
number of subsets in this group
Definition: subset_group.h:122
void add_all()
select all subsets of underlying subset handler
Definition: subset_group.cpp:133
int dim(size_t i) const
dimension of subset
Definition: subset_group.cpp:237
void add(int si)
adds a subset by number to this group
Definition: subset_group.cpp:64
bool contains(int si) const
returns true if subset is contained in this group
Definition: subset_group.cpp:272
For arbitrary UserData and grid functions and , this class (should) define the integrand .
Definition: integrate.h:668
ScalarGridFunctionData< TGridFunction > m_coarseData
Definition: integrate.h:678
number inner_prod(const MathVector< worldDim > &d1, const MathVector< worldDim > &d2)
Definition: integrate.h:827
number inner_dist2(const number &v1, const number &v2)
Definition: integrate.h:836
number inner_prod(const number &d1, const number &d2)
Definition: integrate.h:824
virtual ~UserDataDistIntegrandSq()
Definition: integrate.h:706
ScalarGridFunctionData< TGridFunction > m_fineData
Definition: integrate.h:675
const int m_fineTopLevel
Definition: integrate.h:676
static const int worldDim
world dimension of grid function
Definition: integrate.h:671
SmartPtr< MultiGrid > m_spMG
multigrid
Definition: integrate.h:682
number inner_prod(const T &d1, const T &d2)
Definition: integrate.h:831
number inner_dist2(const MathVector< worldDim > &v1, const MathVector< worldDim > &v2)
Definition: integrate.h:839
UserDataDistIntegrandSq(SmartPtr< UserData< TData, worldDim > > spData, TGridFunction &fineGridFct, size_t fineCmp, TGridFunction &coarseGridFct, size_t coarseCmp)
constructor (1st is fine grid function)
Definition: integrate.h:693
double m_time
Definition: integrate.h:689
const int m_coarseTopLevel
Definition: integrate.h:679
void evaluate(number vValue[], const MathVector< worldDim > vGlobIP[], GridObject *pFineElem, const MathVector< worldDim > vCornerCoords[], const MathVector< elemDim > vFineLocIP[], const MathMatrix< elemDim, worldDim > vJT[], const size_t numIP)
returns the values of the integrand for a bunch of ips
Definition: integrate.h:722
SmartPtr< UserData< TData, worldDim > > m_spData
Definition: integrate.h:686
virtual void set_subset(int si)
sets subset
Definition: integrate.h:709
number inner_dist2(const T &d1, const T &d2)
Definition: integrate.h:843
Type based UserData.
Definition: user_data.h:143
virtual bool requires_grid_fct() const =0
returns if grid function is needed for evaluation
TData data_type
Definition: user_data.h:145
For arbitrary UserData , this class defines the integrand .
Definition: integrate.h:468
UserDataIntegrand(SmartPtr< UserData< TData, worldDim > > spData, number time)
constructor
Definition: integrate.h:497
static const int worldDim
Definition: integrate.h:471
TData data_type
Definition: integrate.h:474
TGridFunction * m_spGridFct
Definition: integrate.h:481
UserDataIntegrand(SmartPtr< UserData< TData, worldDim > > spData, TGridFunction *spGridFct, number time)
constructor
Definition: integrate.h:488
number m_time
Definition: integrate.h:484
SmartPtr< UserData< TData, worldDim > > m_spData
Definition: integrate.h:478
void evaluate(TData vValue[], const MathVector< worldDim > vGlobIP[], GridObject *pElem, const MathVector< worldDim > vCornerCoords[], const MathVector< elemDim > vLocIP[], const MathMatrix< elemDim, worldDim > vJT[], const size_t numIP)
returns the values of the integrand for a bunch of ips
Definition: integrate.h:507
For arbitrary UserData (of type TData), this class defines the integrand .
Definition: integrate.h:557
number inner_prod(const MathVector< worldDim > &d1, const MathVector< worldDim > &d2)
Definition: integrate.h:653
UserDataIntegrandSq(SmartPtr< UserData< TData, worldDim > > spData, const TGridFunction *pGridFct, number time)
constructor
Definition: integrate.h:577
SmartPtr< UserData< TData, worldDim > > m_spData
Definition: integrate.h:567
void evaluate(number vValue[], const MathVector< worldDim > vGlobIP[], GridObject *pElem, const MathVector< worldDim > vCornerCoords[], const MathVector< elemDim > vLocIP[], const MathMatrix< elemDim, worldDim > vJT[], const size_t numIP)
returns the values of the integrand for a bunch of ips
Definition: integrate.h:598
static const int worldDim
Definition: integrate.h:560
TData data_type
Definition: integrate.h:563
number m_time
Definition: integrate.h:573
const TGridFunction * m_pGridFct
Definition: integrate.h:570
number inner_prod(const number &d1, const number &d2)
Definition: integrate.h:650
number inner_prod(const T &d1, const T &d2)
Definition: integrate.h:657
UserDataIntegrandSq(SmartPtr< UserData< TData, worldDim > > spData, number time)
constructor
Definition: integrate.h:586
void CollectCornerCoordinates(std::vector< typename TAAPos::ValueType > &vCornerCoordsOut, const TElem &elem, const TAAPos &aaPos, bool clearContainer=true)
returns the corner coordinates of a geometric object
Definition: domain_util_impl.h:75
MathMatrix< N, M, T >::value_type SqrtGramDeterminant(const MathMatrix< N, M, T > &m)
Square root of Gram Determinant of a matrix.
Definition: math_matrix_functions_common_impl.hpp:508
MathMatrix< N, M, T >::value_type RightInverse(MathMatrix< N, M, T > &mOut, const MathMatrix< M, N, T > &m)
Right-Inverse of a Matrix.
Definition: math_matrix_functions_common_impl.hpp:680
MathMatrix< N, M, T >::value_type Inverse(MathMatrix< N, M, T > &mOut, const MathMatrix< M, N, T > &m)
Inverse of a matrix.
Definition: math_matrix_functions_common_impl.hpp:561
#define PCL_RO_SUM
Definition: pcl_methods.h:63
#define PCL_DT_DOUBLE
Definition: pcl_datatype.h:57
int NumProcs()
returns the number of processes
Definition: pcl_base.cpp:91
static const int dim
const NullSmartPtr SPNULL
The equivalent to NULL for smart pointers.
Definition: smart_pointer.h:90
#define UG_ASSERT(expr, msg)
Definition: assert.h:70
#define UG_CATCH_THROW(msg)
Definition: error.h:64
#define UG_THROW(msg)
Definition: error.h:57
#define UG_LOG(msg)
Definition: log.h:367
#define UG_COND_THROW(cond, msg)
UG_COND_THROW(cond, msg) : performs a UG_THROW(msg) if cond == true.
Definition: error.h:61
double number
Definition: types.h:124
void MatVecMult(vector_t_out &vOut, const matrix_t &m, const vector_t_in &v)
Matrix - Vector Multiplication.
Definition: math_matrix_vector_functions_common_impl.hpp:49
void VecScaleAppend(vector_t &vOut, typename vector_t::value_type s1, const vector_t &v1)
Scales a Vector and adds it to a second vector.
Definition: math_vector_functions_common_impl.hpp:126
void VecSet(vector_t &vInOut, typename vector_t::value_type s)
Set each vector component to scalar (componentwise)
Definition: math_vector_functions_common_impl.hpp:539
void VecScaleAdd(vector_t &vOut, typename vector_t::value_type s1, const vector_t &v1, typename vector_t::value_type s2, const vector_t &v2)
Scales two Vectors, adds them and returns the sum in a third vector.
Definition: math_vector_functions_common_impl.hpp:265
vector_t::value_type VecTwoNormSq(const vector_t &v)
Definition: math_vector_functions_common_impl.hpp:585
vector_t::value_type VecDistanceSq(const vector_t &v1, const vector_t &v2)
returns the squared distance of two vector_ts.
Definition: math_vector_functions_common_impl.hpp:351
vector_t::value_type VecDot(const vector_t &v1, const vector_t &v2)
returns the dot-product of two vector_ts
Definition: math_vector_functions_common_impl.hpp:385
function util LuaCallbackHelper create(func)
Definition: smart_pointer.h:814
int local(bglp_vertex_descriptor p)
Definition: parallel_matrix.h:57
the ug namespace
number H1SemiDistance2(TGridFunction &spGridFct1, const char *cmp1, TGridFunction &spGridFct2, const char *cmp2, int quadOrder, const char *subsets, ConstSmartPtr< typename H1SemiDistIntegrand< TGridFunction >::weight_type > weights)
Squared distance in H1 semi norm (with select subsets & weights)
Definition: integrate.h:2372
number H1SemiError2(SmartPtr< TGridFunction > spGridFct1, const char *cmp1, SmartPtr< TGridFunction > spGridFct2, const char *cmp2, int quadOrder, const char *subsets)
Distance in H1 semi norm (with subset selection)
Definition: integrate.h:2344
number IntegrateNormalGradientOnManifold(TGridFunction &u, const char *cmp, const char *BndSubset, const char *InnerSubset=NULL)
Integrates the Flux of a component over some boundary subsets.
Definition: integrate.h:3989
number Integrate(TConstIterator iterBegin, TConstIterator iterEnd, typename domain_traits< WorldDim >::position_accessor_type &aaPos, IIntegrand< number, WorldDim > &integrand, int quadOrder, std::string quadType, Grid::AttachmentAccessor< typename domain_traits< dim >::grid_base_object, ANumber > *paaElemContribs=NULL)
integrates on the whole domain
Definition: integrate.h:260
number L2Distance2(TGridFunction &spGridFct1, const char *cmp1, TGridFunction &spGridFct2, const char *cmp2, int quadOrder, const char *subsets, ConstSmartPtr< typename L2Integrand< TGridFunction >::weight_type > spWeight, number avgDist12=0.0)
computes the squared l2 distance between two functions
Definition: integrate.h:1886
number H1Norm(TGridFunction &u, const char *cmp, int quadOrder, const char *subsets=NULL)
Definition: integrate.h:2973
number H1SemiNorm2(TGridFunction &gridFct, const char *cmp, int quadOrder, const char *subsets=NULL, ConstSmartPtr< typename H1SemiIntegrand< TGridFunction >::weight_type > weights=SPNULL)
compute H1 semi-norm of a function on the whole domain (or on selected subsets)
Definition: integrate.h:2092
QuadType GetQuadratureType(const std::string &name)
returns Identifier from string
Definition: quadrature_provider.cpp:299
ReferenceObjectID
these ids are used to identify the shape of a geometric object.
Definition: grid_base_objects.h:74
number IntegralNormalComponentOnManifoldGeneral(TConstIterator iterBegin, TConstIterator iterEnd, typename domain_traits< WorldDim >::position_accessor_type &aaPos, const ISubsetHandler *ish, IIntegrand< MathVector< WorldDim >, WorldDim > &integrand, const SubsetGroup &bndSSGrp, int quadOrder, Grid &grid)
Definition: integrate.h:3504
number & DoFRef(TMatrix &mat, const DoFIndex &iInd, const DoFIndex &jInd)
Definition: multi_index.h:276
number IntegrateNormalComponentOnManifold(TGridFunction &u, const char *cmp, const char *BndSubset)
Integrates a component over some boundary subsets.
Definition: integrate.h:3840
number L2Norm2(TGridFunction &u, const char *cmp, int quadOrder, const char *subsets, ConstSmartPtr< typename L2Integrand< TGridFunction >::weight_type > spWeight)
Definition: integrate.h:1655
number L2Distance(TGridFunction &spGridFct1, const char *cmp1, TGridFunction &spGridFct2, const char *cmp2, int quadOrder, const char *subsets)
computes the l2 distance between two functions
Definition: integrate.h:1908
number H1Error(SmartPtr< UserData< number, TGridFunction::dim > > spExactSol, SmartPtr< UserData< MathVector< TGridFunction::dim >, TGridFunction::dim > > spExactGrad, SmartPtr< TGridFunction > spGridFct, const char *cmp, number time, int quadOrder, const char *subsets)
compute H1 error of a function on the whole domain or on some subsets
Definition: integrate.h:1375
number IntegrateSubsets(IIntegrand< number, TGridFunction::dim > &spIntegrand, TGridFunction &spGridFct, const char *subsets, int quadOrder, std::string quadType=std::string())
Definition: integrate.h:393
number IntegralNormalComponentOnManifoldUsingFV1Geom(TConstIterator iterBegin, TConstIterator iterEnd, typename domain_traits< WorldDim >::position_accessor_type &aaPos, const ISubsetHandler *ish, IIntegrand< MathVector< WorldDim >, WorldDim > &integrand, const SubsetGroup &bndSSGrp)
Definition: integrate.h:3406
number H1SemiDistance(TGridFunction &spGridFct1, const char *cmp1, TGridFunction &spGridFct2, const char *cmp2, int quadOrder, const char *subsets, ConstSmartPtr< typename H1SemiDistIntegrand< TGridFunction >::weight_type > weights)
Distance in H1 semi norm (with select subsets & weights)
Definition: integrate.h:2383
void TokenizeString(const string &str, vector< string > &vToken, const char delimiter)
Definition: string_util.cpp:56
number IntegrateSubset(IIntegrand< number, TGridFunction::dim > &spIntegrand, TGridFunction &spGridFct, int si, int quadOrder, std::string quadType)
Definition: integrate.h:373
number H1EnergyNorm(TGridFunction &gridFct, const char *cmp, int quadOrder, const char *subsets=NULL, ConstSmartPtr< typename H1SemiIntegrand< TGridFunction >::weight_type > weights=SPNULL)
Definition: integrate.h:2582
number H1Distance2(TGridFunction &spGridFct1, const char *cmp1, TGridFunction &spGridFct2, const char *cmp2, int quadOrder, const char *subsets=NULL)
Definition: integrate.h:3151
number IntegralNormalComponentOnManifold(SmartPtr< UserData< MathVector< TGridFunction::dim >, TGridFunction::dim > > spData, SmartPtr< TGridFunction > spGridFct, const char *BndSubset, const char *InnerSubset, number time, int quadOrder)
Definition: integrate.h:3737
bool SameDimensionsInAllSubsets(const SubsetGroup &subsetGroup)
Definition: subset_group.cpp:299
number Minimum(SmartPtr< TGridFunction > spGridFct, const char *cmp, const char *subsets)
Definition: integrate.h:1062
number StdFuncIntegralOnVertex(TGridFunction &gridFct, size_t fct, int si)
Definition: integrate.h:3280
number IntegralNormalComponentOnManifoldSubsets(SmartPtr< IIntegrand< MathVector< TGridFunction::dim >, TGridFunction::dim > > spIntegrand, SmartPtr< TGridFunction > spGridFct, const char *BndSubsets, const char *InnerSubsets, int quadOrder)
Definition: integrate.h:3665
number H1SemiNorm(TGridFunction &gridFct, const char *cmp, int quadOrder, const char *subsets=NULL, ConstSmartPtr< typename H1SemiIntegrand< TGridFunction >::weight_type > weights=SPNULL)
Computes the H1SemiNorm.
Definition: integrate.h:2112
number IntegralNormalComponentOnManifoldSubset(SmartPtr< IIntegrand< MathVector< TGridFunction::dim >, TGridFunction::dim > > spIntegrand, SmartPtr< TGridFunction > spGridFct, int si, const SubsetGroup &bndSSGrp, int quadOrder)
Definition: integrate.h:3635
void GetLocalVector(LocalVector &lvec, const TVector &vec)
Definition: local_algebra.h:739
void RemoveLowerDimSubsets(SubsetGroup &subsetGroup)
Definition: subset_group.cpp:315
number H1Norm2(TGridFunction &u, const char *cmp, int quadOrder, const char *subsets=NULL)
Definition: integrate.h:2956
number L2Error(SmartPtr< UserData< number, TGridFunction::dim > > spExactSol, TGridFunction &gridFct, const char *cmp, number time, int quadOrder, const char *subsets)
computes the l2 error function on the whole domain or on some subsets
Definition: integrate.h:1185
number H1Distance(TGridFunction &spGridFct1, const char *cmp1, TGridFunction &spGridFct2, const char *cmp2, int quadOrder, const char *subsets=NULL)
Definition: integrate.h:3161
number GridFunctionDistance2(TGridFunction &spGridFct1, const char *cmp1, TGridFunction &spGridFct2, const char *cmp2, int quadOrder, const char *subsets)
computes an (abstract) distance between two functions
Definition: integrate.h:1441
number H1SemiError(SmartPtr< TGridFunction > spGridFct1, const char *cmp1, SmartPtr< TGridFunction > spGridFct2, const char *cmp2, int quadOrder, const char *subsets)
Distance in H1 semi norm (with subset selection)
Definition: integrate.h:2354
number H1EnergyDistance(TGridFunction &spGridFct1, const char *cmp1, TGridFunction &spGridFct2, const char *cmp2, int quadOrder, const char *subsets, ConstSmartPtr< typename H1SemiDistIntegrand< TGridFunction >::weight_type > weights)
Distance in H1 semi norm (with select subsets & weights)
Definition: integrate.h:2829
number L2Norm(TGridFunction &u, const char *cmp, int quadOrder, const char *subsets)
Definition: integrate.h:1686
number Integral(SmartPtr< UserData< number, TGridFunction::dim > > spData, TGridFunction &spGridFct, const char *subsets, number time, int quadOrder, std::string quadType)
Definition: integrate.h:856
number H1EnergyDistance2(TGridFunction &spGridFct1, const char *cmp1, TGridFunction &spGridFct2, const char *cmp2, int quadOrder, const char *subsets, ConstSmartPtr< typename H1SemiDistIntegrand< TGridFunction >::weight_type > weights)
Squared distance in H1 semi norm (with select subsets & weights)
Definition: integrate.h:2818
number GetMinimum(TGridFunction &gridFct, const char *cmp, const char *subsets)
Definition: integrate.h:1048
number H1EnergyNorm2(TGridFunction &gridFct, const char *cmp, int quadOrder, const char *subsets=NULL, ConstSmartPtr< typename H1SemiIntegrand< TGridFunction >::weight_type > weights=SPNULL)
compute energy -norm of a function on the whole domain (or on selected subsets)
Definition: integrate.h:2564
@ DIM_SUBSET_EMPTY_GRID
Definition: subset_dim_util.h:92
#define PROFILE_FUNC()
Definition: profiler.h:257
QuadType
types of quadratures
Definition: quadrature_provider.h:41
SmartPtr< T, FreePolicy > make_sp(T *inst)
returns a SmartPtr for the passed raw pointer
Definition: smart_pointer.h:836
Definition: domain_traits.h:53
function ProblemDisc new(problemDesc, dom)