ug4
Loading...
Searching...
No Matches
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
39#include "common/common.h"
40
42
45#include "lib_disc/domain_util.h" // for CollectCornerCoordinates
52
53#ifdef UG_FOR_LUA
55#endif
56
57namespace ug{
58
59
61// Object encapsulating (scalar) GridFunction related data
63template <typename TGridFunction>
65{
66public:
67 typedef typename TGridFunction::domain_type domain_type;
68
69 ScalarGridFunctionData(TGridFunction& gridFct, size_t cmp)
70 : m_gridFct(gridFct), m_fct(cmp),
71 m_id(m_gridFct.local_finite_element_id(m_fct))
72 {}
73
74 TGridFunction& grid_function()
75 {return m_gridFct;}
76
77 const TGridFunction& grid_function() const
78 {return m_gridFct;}
79
80 size_t fct()
81 {return m_fct;}
82
83 const LFEID &id() const
84 {return m_id;}
85
87 bool is_def_in_subset(int si) const
88 { return m_gridFct.is_def_in_subset(m_fct, si); }
89
92
94 ConstSmartPtr<domain_type> domain() const {return m_gridFct.domain();}
95
96 template <typename TElem>
97 size_t dof_indices(TElem* elem, std::vector<DoFIndex>& ind, bool bHang = false, bool bClear = true) const
98 {return m_gridFct.dof_indices(elem, m_fct, ind, bHang, bClear);}
99
100private:
102 TGridFunction& m_gridFct;
103
105 size_t m_fct;
106
109};
110
112// Integrand Interface
114
115
117
118template <typename TData, int TWorldDim>
120{
121 public:
123 static const int worldDim = TWorldDim;
124
126 typedef TData data_type;
127
129
140 virtual void values(TData vValue[],
141 const MathVector<worldDim> vGlobIP[],
142 GridObject* pElem,
143 const MathVector<worldDim> vCornerCoords[],
144 const MathVector<1> vLocIP[],
145 const MathMatrix<1, worldDim> vJT[],
146 const size_t numIP) = 0;
147 virtual void values(TData vValue[],
148 const MathVector<worldDim> vGlobIP[],
149 GridObject* pElem,
150 const MathVector<worldDim> vCornerCoords[],
151 const MathVector<2> vLocIP[],
152 const MathMatrix<2, worldDim> vJT[],
153 const size_t numIP) = 0;
154 virtual void values(TData vValue[],
155 const MathVector<worldDim> vGlobIP[],
156 GridObject* pElem,
157 const MathVector<worldDim> vCornerCoords[],
158 const MathVector<3> vLocIP[],
159 const MathMatrix<3, worldDim> vJT[],
160 const size_t numIP) = 0;
162
163 virtual ~IIntegrand() {}
164
165
167 virtual void set_subset(int si) {m_si = si;}
168
170 inline int subset() const {return m_si;}
171
172 protected:
174 int m_si;
175};
176
178template <typename TData, int TWorldDim, typename TImpl>
179class StdIntegrand : public IIntegrand<TData, TWorldDim>
180{
181 public:
183 static const int worldDim = TWorldDim;
184
186 typedef TData data_type;
187
190 virtual void values(TData vValue[],
191 const MathVector<worldDim> vGlobIP[],
192 GridObject* pElem,
193 const MathVector<worldDim> vCornerCoords[],
194 const MathVector<1> vLocIP[],
195 const MathMatrix<1, worldDim> vJT[],
196 const size_t numIP)
197 {
198 getImpl().template evaluate<1>(vValue,vGlobIP,pElem,vCornerCoords,vLocIP,vJT,numIP);
199 }
200 virtual void values(TData vValue[],
201 const MathVector<worldDim> vGlobIP[],
202 GridObject* pElem,
203 const MathVector<worldDim> vCornerCoords[],
204 const MathVector<2> vLocIP[],
205 const MathMatrix<2, worldDim> vJT[],
206 const size_t numIP)
207 {
208 getImpl().template evaluate<2>(vValue,vGlobIP,pElem,vCornerCoords,vLocIP,vJT,numIP);
209 }
210 virtual void values(TData vValue[],
211 const MathVector<worldDim> vGlobIP[],
212 GridObject* pElem,
213 const MathVector<worldDim> vCornerCoords[],
214 const MathVector<3> vLocIP[],
215 const MathMatrix<3, worldDim> vJT[],
216 const size_t numIP)
217 {
218 getImpl().template evaluate<3>(vValue,vGlobIP,pElem,vCornerCoords,vLocIP,vJT,numIP);
219 }
221
222 protected:
224 TImpl& getImpl() {return static_cast<TImpl&>(*this);}
225
227 const TImpl& getImpl() const {return static_cast<const TImpl&>(*this);}
228};
229
232// Generic Volume Integration Routine
235
237
258template <int WorldDim, int dim, typename TConstIterator>
259number Integrate(TConstIterator iterBegin,
260 TConstIterator iterEnd,
263 int quadOrder, std::string quadType,
266 *paaElemContribs = NULL
267 )
268{
269 PROFILE_FUNC();
270
271// reset the result
272 number integral = 0.0;
273
274// note: this iterator is for the base elements, e.g. Face and not
275// for the special type, e.g. Triangle, Quadrilateral
276 TConstIterator iter = iterBegin;
277
278// this is the base element type (e.g. Face). This is the type when the
279// iterators above are dereferenciated.
280 typedef typename domain_traits<dim>::grid_base_object grid_base_object;
281
282// get quad type
283 if(quadType.empty()) quadType = "best";
284 QuadType type = GetQuadratureType(quadType);
285
286// accessing without dereferencing a pointer first is simpler...
288 if(paaElemContribs)
289 aaElemContribs = *paaElemContribs;
290
291// We'll reuse containers to avoid reallocations
292 std::vector<MathVector<WorldDim> > vCorner;
293 std::vector<MathVector<WorldDim> > vGlobIP;
294 std::vector<MathMatrix<dim, WorldDim> > vJT;
295 std::vector<number> vValue;
296
297// iterate over all elements
298 for(; iter != iterEnd; ++iter)
299 {
300 // get element
301 grid_base_object* pElem = *iter;
302
303 // get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
304 ReferenceObjectID roid = (ReferenceObjectID) pElem->reference_object_id();
305
306 // get quadrature Rule for reference object id and order
307 try{
308 const QuadratureRule<dim>& rQuadRule
309 = QuadratureRuleProvider<dim>::get(roid, quadOrder, type);
310
311 // get reference element mapping by reference object id
313 = ReferenceMappingProvider::get<dim, WorldDim>(roid);
314
315 // number of integration points
316 const size_t numIP = rQuadRule.size();
317
318 // get all corner coordinates
319 CollectCornerCoordinates(vCorner, *pElem, aaPos, true);
320
321 // update the reference mapping for the corners
322 mapping.update(&vCorner[0]);
323
324 // compute global integration points
325 vGlobIP.resize(numIP);
326 mapping.local_to_global(&(vGlobIP[0]), rQuadRule.points(), numIP);
327
328 // compute transformation matrices
329 vJT.resize(numIP);
330 mapping.jacobian_transposed(&(vJT[0]), rQuadRule.points(), numIP);
331
332 // compute integrand values at integration points
333 vValue.resize(numIP);
334 try
335 {
336 integrand.values(&(vValue[0]), &(vGlobIP[0]),
337 pElem, &vCorner[0], rQuadRule.points(),
338 &(vJT[0]),
339 numIP);
340 }
341 UG_CATCH_THROW("Unable to compute values of integrand at integration point.");
342
343 // reset contribution of this element
344 number intValElem = 0;
345
346 // loop integration points
347 for(size_t ip = 0; ip < numIP; ++ip)
348 {
349 // get quadrature weight
350 const number weightIP = rQuadRule.weight(ip);
351
352 // get determinate of mapping
353 const number det = SqrtGramDeterminant(vJT[ip]);
354
355 // add contribution of integration point
356 intValElem += vValue[ip] * weightIP * det;
357 }
358
359 // add to global sum
360 integral += intValElem;
361 if(aaElemContribs.valid())
362 aaElemContribs[pElem] = intValElem;
363
364 }UG_CATCH_THROW("SumValuesOnElems failed.");
365 } // end elem
366
367// return the summed integral contributions of all elements
368 return integral;
369}
370
371template <typename TGridFunction, int dim>
373 TGridFunction& spGridFct,
374 int si, int quadOrder, std::string quadType)
375{
376// integrate elements of subset
377 typedef typename TGridFunction::template dim_traits<dim>::grid_base_object grid_base_object;
378 typedef typename TGridFunction::template dim_traits<dim>::const_iterator const_iterator;
379
380 spIntegrand.set_subset(si);
381
382 return Integrate<TGridFunction::dim,dim,const_iterator>
383 (spGridFct.template begin<grid_base_object>(si),
384 spGridFct.template end<grid_base_object>(si),
385 spGridFct.domain()->position_accessor(),
386 spIntegrand,
387 quadOrder, quadType);
388}
389
390
391template <typename TGridFunction>
393 TGridFunction& spGridFct,
394 const char* subsets, int quadOrder,
395 std::string quadType = std::string())
396{
397// world dimensions
398 static const int dim = TGridFunction::dim;
399
400// read subsets
401 SubsetGroup ssGrp(spGridFct.domain()->subset_handler());
402 if(subsets != NULL)
403 {
404 ssGrp.add(TokenizeString(subsets));
405 UG_COND_THROW(!SameDimensionsInAllSubsets(ssGrp), "IntegrateSubsets: Subsets '"<<subsets<<"' do not have same dimension."
406 "Cannot integrate on subsets of different dimensions.");
407 UG_LOG("IntegrateSubsets for subsets="<<subsets<<"\n");
408 }
409 else
410 {
411 // add all subsets and remove lower dim subsets afterwards
412 ssGrp.add_all();
414 }
415
416// reset value
417 number value = 0;
418
419// loop subsets
420 for(size_t i = 0; i < ssGrp.size(); ++i)
421 {
422 // get subset index
423 const int si = ssGrp[i];
424
425 // check dimension
426 UG_COND_THROW(ssGrp.dim(i) > dim, "IntegrateSubsets: Dimension of subset is "<<ssGrp.dim(i)<<", but "
427 " world dimension is "<<dim<<". Cannot integrate this.");
428
429 // integrate elements of subset
430 try{
431 switch(ssGrp.dim(i))
432 {
433 case DIM_SUBSET_EMPTY_GRID: break;
434 case 1: value += IntegrateSubset<TGridFunction, 1>(spIntegrand, spGridFct, si, quadOrder, quadType); break;
435 case 2: value += IntegrateSubset<TGridFunction, 2>(spIntegrand, spGridFct, si, quadOrder, quadType); break;
436 case 3: value += IntegrateSubset<TGridFunction, 3>(spIntegrand, spGridFct, si, quadOrder, quadType); break;
437 default: UG_THROW("IntegrateSubsets: Dimension "<<ssGrp.dim(i)<<" not supported. "
438 " World dimension is "<<dim<<".");
439 }
440 }
441 UG_CATCH_THROW("IntegrateSubsets: Integration failed on subset "<<si);
442 }
443
444#ifdef UG_PARALLEL
445 // sum over processes
446 if(pcl::NumProcs() > 1)
447 {
449 number local = value;
450 com.allreduce(&local, &value, 1, PCL_DT_DOUBLE, PCL_RO_SUM);
451 }
452#endif
453
454// return the result
455 return value;
456}
457
458
460// UserData Integrand
462
464template <typename TData, typename TGridFunction>
466 : public StdIntegrand<TData, TGridFunction::dim, UserDataIntegrand<TData, TGridFunction> >
467{
468 public:
469 // world dimension of grid function
470 static const int worldDim = TGridFunction::dim;
471
472 // data type
473 typedef TData data_type;
474
475 private:
476 // data to integrate
478
479 // grid function
480 TGridFunction* m_spGridFct;
481
482 // time
484
485 public:
488 TGridFunction* spGridFct,
489 number time)
490 : m_spData(spData), m_spGridFct(spGridFct), m_time(time)
491 {
492 m_spData->set_function_pattern(spGridFct->function_pattern());
493 };
494
497 number time)
498 : m_spData(spData), m_spGridFct(NULL), m_time(time)
499 {
500 UG_COND_THROW(m_spData->requires_grid_fct(),
501 "UserDataIntegrand: Missing GridFunction, but data requires grid function.");
502 };
503
505 template <int elemDim>
506 void evaluate(TData vValue[],
507 const MathVector<worldDim> vGlobIP[],
508 GridObject* pElem,
509 const MathVector<worldDim> vCornerCoords[],
510 const MathVector<elemDim> vLocIP[],
512 const size_t numIP)
513 {
514 // get local solution if needed
515 if(m_spData->requires_grid_fct())
516 {
517 // create storage
518 LocalIndices ind;
519 LocalVector u;
520
521 // get global indices
522 m_spGridFct->indices(pElem, ind);
523
524 // adapt local algebra
525 u.resize(ind);
526
527 // read local values of u
529
530 // compute data
531 try{
532 (*m_spData)(vValue, vGlobIP, m_time, this->m_si, pElem,
533 vCornerCoords, vLocIP, numIP, &u, &vJT[0]);
534 }
535 UG_CATCH_THROW("UserDataIntegrand: Cannot evaluate data.");
536 }
537 else
538 {
539 // compute data
540 try{
541 (*m_spData)(vValue, vGlobIP, m_time, this->m_si, numIP);
542 }
543 UG_CATCH_THROW("UserDataIntegrand: Cannot evaluate data.");
544 }
545
546 }
547};
548
549
550
551
553template <typename TData, typename TGridFunction>
555 : public StdIntegrand<number, TGridFunction::dim, UserDataIntegrandSq<TData, TGridFunction> >
556{
557 public:
558 // world dimension of grid function
559 static const int worldDim = TGridFunction::dim;
560
561 // data type
562 typedef TData data_type;
563
564 private:
565 // data to integrate
567
568 // grid function
569 const TGridFunction* m_pGridFct;
570
571 // time
573
574 public:
577 const TGridFunction* pGridFct,
578 number time)
579 : m_spData(spData), m_pGridFct(pGridFct), m_time(time)
580 {
581 m_spData->set_function_pattern(pGridFct->function_pattern());
582 };
583
586 number time)
587 : m_spData(spData), m_pGridFct(NULL), m_time(time)
588 {
589 if(m_spData->requires_grid_fct())
590 UG_THROW("UserDataIntegrand: Missing GridFunction, but "
591 " data requires grid function.")
592 };
593
594
596 template <int elemDim>
597 void evaluate(number vValue[],
598 const MathVector<worldDim> vGlobIP[],
599 GridObject* pElem,
600 const MathVector<worldDim> vCornerCoords[],
601 const MathVector<elemDim> vLocIP[],
603 const size_t numIP)
604 {
605
606 std::vector<TData> tmpValues(numIP);
607
608 // get local solution if needed
609 if(m_spData->requires_grid_fct())
610 {
611 UG_ASSERT(m_pGridFct!=NULL, "Error: Requires valid pointer!")
612 // create storage
613 LocalIndices ind;
614 LocalVector u;
615
616 // get global indices
617 m_pGridFct->indices(pElem, ind);
618
619 // adapt local algebra
620 u.resize(ind);
621
622 // read local values of u
624
625 // compute data
626 try{
627 (*m_spData)(&tmpValues.front(), vGlobIP, m_time, this->m_si, pElem,
628 vCornerCoords, vLocIP, numIP, &u, &vJT[0]);
629 }
630 UG_CATCH_THROW("UserDataIntegrand: Cannot evaluate data.");
631 }
632 else
633 {
634 // compute data
635 try{
636 (*m_spData)(&tmpValues.front(), vGlobIP, m_time, this->m_si, numIP);
637 }
638 UG_CATCH_THROW("UserDataIntegrand: Cannot evaluate data.");
639 }
640
641 for (size_t i=0; i<numIP; ++i)
642 {
643 vValue[i]=inner_prod(tmpValues[i], tmpValues[i]);
644 }
645
646 }
647 protected:
648
649 number inner_prod(const number &d1, const number &d2)
650 {return d1*d2;}
651
653 {return VecDot(d1, d2);}
654
655 template<typename T>
656 number inner_prod(const T &d1, const T &d2)
657 { UG_ASSERT(0, "NOT IMPLEMENTED"); return 0.0;}
658};
659
660
661
662
664template <typename TData, typename TGridFunction>
666 : public StdIntegrand<number, TGridFunction::dim, UserDataDistIntegrandSq<TData, TGridFunction> >
667{
668 public:
670 static const int worldDim = TGridFunction::dim;
671 // typedef typename L2Integrand<TGridFunction>::weight_type weight_type;
672
673 protected:
675 const int m_fineTopLevel;
676
679
682
683
684
686 // ConstSmartPtr<weight_type> m_spWeight;
687
688 double m_time;
689 public:
690
692 UserDataDistIntegrandSq(SmartPtr<UserData<TData, worldDim> > spData, TGridFunction& fineGridFct, size_t fineCmp,
693 TGridFunction& coarseGridFct, size_t coarseCmp)
694 : m_fineData(fineGridFct, fineCmp), m_fineTopLevel(fineGridFct.dof_distribution()->grid_level().level()),
695 m_coarseData(coarseGridFct, coarseCmp), m_coarseTopLevel(coarseGridFct.dof_distribution()->grid_level().level()),
696 m_spMG(m_fineData.domain()->grid()), m_spData(spData), m_time(0.0) /*, m_spWeight(make_sp(new ConstUserNumber<TGridFunction::dim>(1.0)))*/
697 {
699 UG_THROW("UserDataDistIntegrandSq: fine and top level inverted.");
700
701 if(m_fineData.domain().get() != m_coarseData.domain().get())
702 UG_THROW("UserDataDistIntegrandSq: grid functions defined on different domains.");
703 };
704
706
708 virtual void set_subset(int si)
709 {
710 if(!m_fineData.is_def_in_subset(si))
711 UG_THROW("UserDataDistIntegrandSq: Grid function component"
712 <<m_fineData.fct()<<" not defined on subset "<<si);
713 if(!m_coarseData.is_def_in_subset(si))
714 UG_THROW("UserDataDistIntegrandSq: Grid function component"
715 <<m_coarseData.fct()<<" not defined on subset "<<si);
717 }
718
720 template <int elemDim>
721 void evaluate(number vValue[],
722 const MathVector<worldDim> vGlobIP[],
723 GridObject* pFineElem,
724 const MathVector<worldDim> vCornerCoords[],
725 const MathVector<elemDim> vFineLocIP[],
727 const size_t numIP)
728 {
729
730
731 // must return 0.0, if m_spData is independent of grid functions
732 if(!m_spData->requires_grid_fct()) {
733 for (size_t i=0; i<numIP; ++i) { vValue[i]=0.0; }
734 return;
735 }
736
737 // get coarse element
738 GridObject* pCoarseElem = pFineElem;
740 int parentLevel = m_spMG->get_level(pCoarseElem);
741 while(parentLevel > m_coarseTopLevel){
742 pCoarseElem = m_spMG->get_parent(pCoarseElem);
743 parentLevel = m_spMG->get_level(pCoarseElem);
744 }
745 }
746
747 // get corner coordinates
748 typedef typename TGridFunction::template dim_traits<elemDim>::grid_base_object TElem;
749 std::vector<MathVector<worldDim> > vCornerCoarse;
750 CollectCornerCoordinates(vCornerCoarse, *static_cast<TElem*>(pCoarseElem), *m_coarseData.domain());
751
752 // get Reference Mapping
753 const ReferenceObjectID coarseROID = pCoarseElem->reference_object_id();
755 = ReferenceMappingProvider::get<elemDim, worldDim>(coarseROID, vCornerCoarse);
756
757 std::vector<MathVector<elemDim> > vCoarseLocIP;
758 vCoarseLocIP.resize(numIP);
759 for(size_t ip = 0; ip < vCoarseLocIP.size(); ++ip) VecSet(vCoarseLocIP[ip], 0.0);
760 map.global_to_local(&vCoarseLocIP[0], vGlobIP, numIP);
761
762 // element weights
763 /* typedef typename weight_type::data_type ipdata_type;
764 std::vector<ipdata_type> fineElemWeights(numIP, 1.0);
765 UG_ASSERT(m_spWeight.valid(), "L2DistIntegrand::evaluate requires valid weights! ");
766 (*m_spWeight)(&fineElemWeights[0], vFineGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), numIP);*/
767
768
769 // get trial space
770 /* const LocalShapeFunctionSet<elemDim>& rFineLSFS =
771 LocalFiniteElementProvider::get<elemDim>(fineROID, m_fineData.id());
772 const LocalShapeFunctionSet<elemDim>& rCoarseLSFS =
773 LocalFiniteElementProvider::get<elemDim>(coarseROID, m_coarseData.id());*/
774
775 // get multiindices of element
776 /*std::vector<DoFIndex> vFineMI, vCoarseMI;
777 m_fineData.dof_indices(pFineElem, vFineMI);
778 m_coarseData.dof_indices(pCoarseElem, vCoarseMI);*/
779
780 std::vector<TData> fineValues(numIP);
781 std::vector<TData> coarseValues(numIP);
782
783
784
785 // compute coarse data
786 try{
787 LocalVector uCoarse;
788 LocalIndices indCoarse;
789
790 m_coarseData.grid_function().indices(pCoarseElem, indCoarse);
791 uCoarse.resize(indCoarse);
792 GetLocalVector(uCoarse, m_coarseData.grid_function());
793
794 (*m_spData)(&(coarseValues[0]), vGlobIP, m_time, this->m_si, pCoarseElem,
795 &vCornerCoarse[0], &vCoarseLocIP[0], numIP, &uCoarse, &vJT[0]);
796 } UG_CATCH_THROW("UserDataDistIntegrandSq: Cannot evaluate coarse data.");
797
798
799 // compute fine data
800 try{
801 LocalVector uFine;
802 LocalIndices indFine;
803
804 m_fineData.grid_function().indices(pFineElem, indFine);
805 uFine.resize(indFine);
806 GetLocalVector(uFine, m_fineData.grid_function());
807
808 (*m_spData)(&(fineValues[0]), vGlobIP, m_time, this->m_si, pFineElem,
809 vCornerCoords, vFineLocIP, numIP, &uFine, &vJT[0]);
810 } UG_CATCH_THROW("UserDataDistIntegrandSq: Cannot evaluate fine data.");
811
812 // loop all integration points
813 for(size_t ip = 0; ip < numIP; ++ip)
814 {
815 vValue[ip] = inner_dist2(fineValues[ip], coarseValues[ip]);
816 }
817
818 }
819
820
821 protected:
822
823 number inner_prod(const number &d1, const number &d2)
824 {return d1*d2;}
825
827 {return VecDot(d1, d2);}
828
829 template<typename T>
830 number inner_prod(const T &d1, const T &d2)
831 { UG_ASSERT(0, "NOT IMPLEMENTED"); return 0.0;}
832
833
834
835 number inner_dist2(const number &v1, const number &v2)
836 { return (v1-v2)*(v1-v2); }
837
839 { return VecDistanceSq(v1, v2); }
840
841 template<typename T>
842 number inner_dist2(const T &d1, const T &d2)
843 { UG_ASSERT(0, "NOT IMPLEMENTED"); return 0.0;}
844
845};
846
847
850// Volume Integrand implementations
853
854template <typename TGridFunction>
856 TGridFunction& spGridFct,
857 const char* subsets, number time,
858 int quadOrder, std::string quadType)
859{
860 UserDataIntegrand<number, TGridFunction> spIntegrand(spData, &spGridFct, time);
861 return IntegrateSubsets(spIntegrand, spGridFct, subsets, quadOrder, quadType);
862}
863
864template <typename TGridFunction>
866 const char* subsets, number time, int quadOrder, std::string quadType)
867{ return Integral(spData, *spGridFct, subsets, time, quadOrder, quadType); }
868
869template <typename TGridFunction>
870number Integral(SmartPtr<UserData<number, TGridFunction::dim> > spData, SmartPtr<TGridFunction> spGridFct,const char* subsets,number time, int order)
871{return Integral(spData, spGridFct, subsets, time, order, "best");}
872
873template <typename TGridFunction>
875{return Integral(spData, spGridFct, subsets, time, 1, "best");}
876
877template <typename TGridFunction>
879{return Integral(spData, spGridFct, NULL, time, 1, "best");}
880
881template <typename TGridFunction>
883{return Integral(spData, spGridFct, subsets, 0.0, 1, "best");}
884
885template <typename TGridFunction>
887{return Integral(spData, spGridFct, NULL, 0.0, 1, "best");}
888
890// const data
892
893template <typename TGridFunction>
895 const char* subsets,
896 number time, int quadOrder)
897{
898 static const int dim = TGridFunction::dim;
901 return Integral(sp, spGridFct, subsets, time, quadOrder);
902}
903
904template <typename TGridFunction>
905number Integral(number val, SmartPtr<TGridFunction> spGridFct,const char* subsets,number time)
906{return Integral(val, spGridFct, subsets, time, 1);}
907
908template <typename TGridFunction>
910{return Integral(val, spGridFct, NULL, time, 1);}
911
912template <typename TGridFunction>
913number Integral(number val, SmartPtr<TGridFunction> spGridFct,const char* subsets)
914{return Integral(val, spGridFct, subsets, 0.0, 1);}
915
916template <typename TGridFunction>
918{return Integral(val, spGridFct, NULL, 0.0, 1);}
919
921// lua data
923
924#ifdef UG_FOR_LUA
925template <typename TGridFunction>
926number Integral(const char* luaFct,
927 SmartPtr<TGridFunction> spGridFct,
928 const char* subsets, number time,
929 int quadOrder, std::string quadType)
930{
931 static const int dim = TGridFunction::dim;
934 return Integral(sp, *spGridFct, subsets, time, quadOrder, quadType);
935}
936
937template <typename TGridFunction>
938number Integral(const char* luaFct, SmartPtr<TGridFunction> spGridFct,const char* subsets,number time, int quadOrder)
939{return Integral(luaFct, spGridFct, subsets, time, quadOrder, "best");}
940
941template <typename TGridFunction>
942number Integral(const char* luaFct, SmartPtr<TGridFunction> spGridFct,const char* subsets,number time)
943{return Integral(luaFct, spGridFct, subsets, time, 1, "best");}
944
945template <typename TGridFunction>
946number Integral(const char* luaFct, SmartPtr<TGridFunction> spGridFct,number time)
947{return Integral(luaFct, spGridFct, NULL, time, 1, "best");}
948
949template <typename TGridFunction>
950number Integral(const char* luaFct, SmartPtr<TGridFunction> spGridFct,const char* subsets)
951{return Integral(luaFct, spGridFct, subsets, 0.0, 1, "best");}
952
953template <typename TGridFunction>
954number Integral(const char* luaFct, SmartPtr<TGridFunction> spGridFct)
955{return Integral(luaFct, spGridFct, NULL, 0.0, 1, "best");}
956
957#endif
958
959
960
961template <typename TGridFunction>
963 : public StdIntegrand<number, TGridFunction::dim, MaximumDistIntegrand<TGridFunction> >
964{
965 public:
967 static const int worldDim = TGridFunction::dim;
968
969 protected:
971
972 double m_max, m_min;
973
974 public:
976 MaximumDistIntegrand(TGridFunction& gridFct, size_t cmp)
977
978 : m_scalarData(gridFct, cmp),
979 m_max(-std::numeric_limits<float>::infinity()),
980 m_min(std::numeric_limits<float>::infinity())
981 {};
982
984
986 virtual void set_subset(int si)
987 {
988 UG_COND_THROW(!m_scalarData.is_def_in_subset(si), "L2ErrorIntegrand: Grid function component" <<
989 m_scalarData.fct()<<" not defined on subset "<<si);
991 }
992
993 void reset()
994 {
995 m_min = std::numeric_limits<double>::infinity();
996 m_max = -std::numeric_limits<double>::infinity();
997 }
998
999 double min() { return m_min; }
1000 double max() { return m_max; }
1001
1003 template <int elemDim>
1004 void evaluate(number vValue[],
1005 const MathVector<worldDim> vGlobIP[],
1006 GridObject* pElem,
1007 const MathVector<worldDim> vCornerCoords[],
1008 const MathVector<elemDim> vLocIP[],
1010 const size_t numIP)
1011 {
1012 // get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
1013 const ReferenceObjectID roid = pElem->reference_object_id();
1014
1015 try{
1016 // get trial space
1017 const LocalShapeFunctionSet<elemDim>& rTrialSpace =
1018 LocalFiniteElementProvider::get<elemDim>(roid, m_scalarData.id());
1019
1020 // number of dofs on element
1021 const size_t num_sh = rTrialSpace.num_sh();
1022
1023 // get multiindices of element
1024 std::vector<DoFIndex> ind; // aux. index array
1025 m_scalarData.dof_indices(pElem, ind);
1026
1027 // check multi indices
1028 UG_COND_THROW(ind.size() != num_sh, "L2ErrorIntegrand::evaluate: Wrong number of multi indices.");
1029
1030 // evaluate function in corners.
1031 for(size_t sh = 0; sh < num_sh; ++sh)
1032 {
1033 // get value at shape point (e.g. corner for P1 fct)
1034 const number val = DoFRef(m_scalarData.grid_function(), ind[sh]);
1035
1036 m_max = std::max(m_max, val);
1037 m_min = std::min(m_min, val);
1038 }
1039
1040
1041 } UG_CATCH_THROW("L2ErrorIntegrand::evaluate: trial space missing.");
1042 }
1043};
1044
1045
1046template <typename TGridFunction>
1047number GetMinimum(TGridFunction &gridFct, const char* cmp, const char* subsets)
1048{
1049 // get function id of name & check that function exists
1050 const size_t fct = gridFct.fct_id_by_name(cmp);
1051 UG_COND_THROW(fct >= gridFct.num_fct(),
1052 "L2Error: Function space does not contain a function with name " << cmp << ".");
1053
1054 // Find minimum.
1055 MaximumDistIntegrand<TGridFunction> spIntegrand(gridFct, fct);
1056 IntegrateSubsets(spIntegrand, gridFct, subsets, 2);
1057 return spIntegrand.min();
1058}
1059
1060template <typename TGridFunction>
1061number Minimum(SmartPtr<TGridFunction> spGridFct, const char* cmp, const char* subsets)
1062{ return GetMinimum(*spGridFct, cmp, subsets); }
1063
1064
1066// L2 Error Integrand
1068
1069template <typename TGridFunction>
1071 : public StdIntegrand<number, TGridFunction::dim, L2ErrorIntegrand<TGridFunction> >
1072{
1073 public:
1075 static const int worldDim = TGridFunction::dim;
1076
1077 private:
1079
1082
1085
1086 public:
1089 TGridFunction& gridFct, size_t cmp,
1090 number time)
1091 : m_scalarData(gridFct, cmp),
1092 m_spExactSolution(spExactSol), m_time(time)
1093 {};
1094
1095 virtual ~L2ErrorIntegrand() {};
1096
1098 virtual void set_subset(int si)
1099 {
1100 if(!m_scalarData.is_def_in_subset(si))
1101 UG_THROW("L2ErrorIntegrand: Grid function component"
1102 <<m_scalarData.fct()<<" not defined on subset "<<si);
1104 }
1105
1107 template <int elemDim>
1108 void evaluate(number vValue[],
1109 const MathVector<worldDim> vGlobIP[],
1110 GridObject* pElem,
1111 const MathVector<worldDim> vCornerCoords[],
1112 const MathVector<elemDim> vLocIP[],
1114 const size_t numIP)
1115 {
1116 // get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
1117 const ReferenceObjectID roid = pElem->reference_object_id();
1118
1119 try{
1120 // get trial space
1121 const LocalShapeFunctionSet<elemDim>& rTrialSpace =
1122 LocalFiniteElementProvider::get<elemDim>(roid, m_scalarData.id());
1123
1124 // number of dofs on element
1125 const size_t num_sh = rTrialSpace.num_sh();
1126
1127 // get multiindices of element
1128 std::vector<DoFIndex> ind; // aux. index array
1129 m_scalarData.dof_indices(pElem, ind);
1130
1131 // check multi indices
1132 if(ind.size() != num_sh)
1133 UG_THROW("L2ErrorIntegrand::evaluate: Wrong number of"
1134 " multi indices.");
1135
1136 // loop all integration points
1137 for(size_t ip = 0; ip < numIP; ++ip)
1138 {
1139 // compute exact solution at integration point
1140 number exactSolIP;
1141 (*m_spExactSolution)(exactSolIP, vGlobIP[ip], m_time, this->subset());
1142
1143 // compute approximated solution at integration point
1144 number approxSolIP = 0.0;
1145 for(size_t sh = 0; sh < num_sh; ++sh)
1146 {
1147 // get value at shape point (e.g. corner for P1 fct)
1148 const number valSH = DoFRef(m_scalarData.grid_function(), ind[sh]);
1149
1150 // add shape fct at ip * value at shape
1151 approxSolIP += valSH * rTrialSpace.shape(sh, vLocIP[ip]);
1152 }
1153
1154 // get squared of difference
1155 vValue[ip] = (exactSolIP - approxSolIP);
1156 vValue[ip] *= vValue[ip];
1157 }
1158
1159 }
1160 UG_CATCH_THROW("L2ErrorIntegrand::evaluate: trial space missing.");
1161 }
1162};
1163
1164
1165
1167// L2 Error Integrand
1169
1171
1183template <typename TGridFunction>
1185 TGridFunction& gridFct, const char* cmp,
1186 number time, int quadOrder, const char* subsets)
1187{
1188// get function id of name
1189 const size_t fct = gridFct.fct_id_by_name(cmp);
1190
1191// check that function exists
1192 UG_COND_THROW(fct >= gridFct.num_fct(),
1193 "L2Error: Function space does not contain a function with name " << cmp << ".");
1194
1195 L2ErrorIntegrand<TGridFunction> spIntegrand(spExactSol, gridFct, fct, time);
1196 return sqrt(IntegrateSubsets(spIntegrand, gridFct, subsets, quadOrder));
1197}
1198
1199template <typename TGridFunction>
1201 SmartPtr<TGridFunction> spGridFct, const char* cmp,
1202 number time, int quadOrder, const char* subsets)
1203{ return L2Error(spExactSol, *spGridFct, cmp, time, quadOrder, subsets); }
1204
1205template <typename TGridFunction>
1207 SmartPtr<TGridFunction> spGridFct, const char* cmp,
1208 number time, int quadOrder)
1209{ return L2Error(spExactSol, *spGridFct, cmp, time, quadOrder, NULL); }
1210
1211
1212
1213
1214#ifdef UG_FOR_LUA
1215template <typename TGridFunction>
1216number L2Error(const char* ExactSol,
1217 SmartPtr<TGridFunction> spGridFct, const char* cmp,
1218 number time, int quadOrder, const char* subsets)
1219{
1221 = make_sp(new LuaUserData<number, TGridFunction::domain_type::dim>(ExactSol));
1222 return L2Error(spExactSol, spGridFct, cmp, time, quadOrder, subsets);
1223}
1224
1225template <typename TGridFunction>
1226number L2Error(const char* ExactSol,
1227 SmartPtr<TGridFunction> spGridFct, const char* cmp,
1228 number time, int quadOrder)
1229{
1230 return L2Error(ExactSol, spGridFct, cmp, time, quadOrder, NULL);
1231}
1232#endif //UG_FOR_LUA
1233
1234
1235
1236#ifdef UG_DEBUG
1237// True, if max norm is less than SMALL.
1238template <int worldDim, int elemDim>
1239void CheckGeneralizedInverse(const MathMatrix<elemDim, worldDim> &JT, const MathMatrix<worldDim, elemDim> &JTInv)
1240{
1241 if (worldDim==elemDim) return;
1242
1243 MathMatrix<worldDim, elemDim> myTmp;
1244 GeneralizedInverse(myTmp, JT); //old algorithms with Inverse, but Inverse is only defined for NxN Matrix
1245 MatSubtract(myTmp, JTInv, myTmp);
1246
1247 UG_ASSERT(MatMaxNorm(myTmp)<SMALL,
1248 "The inverse matrix is not identity to the map jacobian transposed inverse.");
1249
1250}
1251#endif
1252
1253
1255// H1 Error Integrand
1257
1258template <typename TGridFunction>
1260 : public StdIntegrand<number, TGridFunction::dim, H1ErrorIntegrand<TGridFunction> >
1261{
1262 public:
1264 static const int worldDim = TGridFunction::dim;
1265
1266 private:
1269
1272
1275
1278
1279 public:
1283 TGridFunction& gridFct, size_t cmp,
1284 number time)
1285 : m_scalarData (gridFct, cmp),
1286 m_spExactSolution(spExactSol),
1287 m_spExactGrad(spExactGrad),
1288 m_time(time)
1289 {}
1290
1292 virtual void set_subset(int si)
1293 {
1294 if(!m_scalarData.is_def_in_subset(si))
1295 UG_THROW("H1Error: Grid function component"
1296 <<m_scalarData.fct()<<" not defined on subset "<<si);
1298 }
1299
1301 template <int elemDim>
1302 void evaluate(number vValue[],
1303 const MathVector<worldDim> vGlobIP[],
1304 GridObject* pElem,
1305 const MathVector<worldDim> vCornerCoords[],
1306 const MathVector<elemDim> vLocIP[],
1308 const size_t numIP)
1309 {
1310 // get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
1311 const ReferenceObjectID roid = pElem->reference_object_id();
1312
1314 = ReferenceMappingProvider::get<elemDim, worldDim>(roid, vCornerCoords);
1315
1316 try{
1317 // get trial space
1318 const LocalShapeFunctionSet<elemDim>& rTrialSpace =
1319 LocalFiniteElementProvider::get<elemDim>(roid, m_scalarData.id());
1320
1321 // number of dofs on element
1322 const size_t num_sh = rTrialSpace.num_sh();
1323
1324 // get multiindices of element
1325 std::vector<DoFIndex> ind; // aux. index array
1326 m_scalarData.dof_indices(pElem, ind);
1327
1328 // check multi indices
1329 if(ind.size() != num_sh)
1330 UG_THROW("H1ErrorIntegrand::evaluate: Wrong number of"
1331 " multi indices.");
1332
1333 // loop all integration points
1334 std::vector<MathVector<elemDim> > vLocGradient(num_sh);
1335 for(size_t ip = 0; ip < numIP; ++ip)
1336 {
1337 // compute exact solution at integration point
1338 number exactSolIP;
1339 (*m_spExactSolution)(exactSolIP, vGlobIP[ip], m_time, this->subset());
1340
1341 // compute exact gradient at integration point
1342 MathVector<worldDim> exactGradIP;
1343 (*m_spExactGrad)(exactGradIP, vGlobIP[ip], m_time, this->subset());
1344
1345 // compute shape gradients at ip
1346 rTrialSpace.grads(&vLocGradient[0], vLocIP[ip]);
1347
1348 // compute approximated solution at integration point
1349 number approxSolIP = 0.0;
1350 MathVector<elemDim> locTmp; VecSet(locTmp, 0.0);
1351 for(size_t sh = 0; sh < num_sh; ++sh)
1352 {
1353 // get value at shape point (e.g. corner for P1 fct)
1354 const number valSH = DoFRef(m_scalarData.grid_function(), ind[sh]);
1355
1356 // add shape fct at ip * value at shape
1357 approxSolIP += valSH * rTrialSpace.shape(sh, vLocIP[ip]);
1358
1359 // add gradient at ip
1360 VecScaleAppend(locTmp, valSH, vLocGradient[sh]);
1361 }
1362
1363 // compute global gradient
1364 MathVector<worldDim> approxGradIP;
1366 map.jacobian_transposed_inverse(JTInv, vLocIP[ip]); //Inverse(JTInv, vJT[ip]);
1367
1368#ifdef UG_DEBUG
1369 CheckGeneralizedInverse<worldDim,elemDim>(vJT[ip], JTInv);
1370#endif //UG_DEBUG
1371
1372 MatVecMult(approxGradIP, JTInv, locTmp);
1373
1374 // get squared of difference
1375 vValue[ip] = (exactSolIP - approxSolIP) * (exactSolIP - approxSolIP);
1376 vValue[ip] += VecDistanceSq(approxGradIP, exactGradIP);
1377 }
1378
1379 }
1380 UG_CATCH_THROW("H1ErrorIntegrand::evaluate: trial space missing.");
1381 }
1382};
1383
1385
1398template <typename TGridFunction>
1400 SmartPtr<UserData<MathVector<TGridFunction::dim>, TGridFunction::dim> > spExactGrad,
1401 SmartPtr<TGridFunction> spGridFct, const char* cmp,
1402 number time, int quadOrder, const char* subsets)
1403{
1404// get function id of name
1405 const size_t fct = spGridFct->fct_id_by_name(cmp);
1406
1407// check that function exists
1408 if(fct >= spGridFct->num_fct())
1409 UG_THROW("H1Error: Function space does not contain"
1410 " a function with name " << cmp << ".");
1411
1412 H1ErrorIntegrand<TGridFunction> spIntegrand(spExactSol, spExactGrad, *spGridFct, fct, time);
1413 return sqrt(IntegrateSubsets(spIntegrand, *spGridFct, subsets, quadOrder));
1414}
1415
1416template <typename TGridFunction>
1418 SmartPtr<UserData<MathVector<TGridFunction::dim>, TGridFunction::dim> > spExactGrad,
1419 SmartPtr<TGridFunction> spGridFct, const char* cmp,
1420 number time, int quadOrder)
1421{
1422 return H1Error(spExactSol, spExactGrad, spGridFct, cmp, time, quadOrder, NULL);
1423}
1424
1425#ifdef UG_FOR_LUA
1426template <typename TGridFunction>
1427number H1Error(const char* ExactSol, const char* ExactGrad,
1428 SmartPtr<TGridFunction> spGridFct, const char* cmp,
1429 number time, int quadOrder, const char* subsets)
1430{
1431 static const int dim = TGridFunction::domain_type::dim;
1433 = make_sp(new LuaUserData<number, dim>(ExactSol));
1434 SmartPtr<UserData<MathVector<dim>, dim> > spExactGrad
1435 = make_sp(new LuaUserData<MathVector<dim>, dim>(ExactGrad));
1436 return H1Error(spExactSol, spExactGrad, spGridFct, cmp, time, quadOrder, subsets);
1437}
1438
1439template <typename TGridFunction>
1440number H1Error(const char* ExactSol, const char* ExactGrad,
1441 SmartPtr<TGridFunction> spGridFct, const char* cmp,
1442 number time, int quadOrder)
1443{
1444 return H1Error(ExactSol, ExactGrad, spGridFct, cmp, time, quadOrder, NULL);
1445}
1446#endif
1447
1448
1449
1451
1464template <typename TDistIntegrand, typename TGridFunction>
1465number GridFunctionDistance2(TGridFunction& spGridFct1, const char* cmp1,
1466 TGridFunction& spGridFct2, const char* cmp2,
1467 int quadOrder, const char* subsets)
1468{
1469// get function id of name
1470 const size_t fct1 = spGridFct1.fct_id_by_name(cmp1);
1471 const size_t fct2 = spGridFct2.fct_id_by_name(cmp2);
1472
1473// check that function exists
1474 if(fct1 >= spGridFct1.num_fct())
1475 UG_THROW("GridFunctionDistance: Function space does not contain"
1476 " a function with name " << cmp1 << ".");
1477 if(fct2 >= spGridFct2.num_fct())
1478 UG_THROW("GridFunctionDistance: Function space does not contain"
1479 " a function with name " << cmp2 << ".");
1480
1481// get top level of grid functions
1482 const int level1 = spGridFct1.dof_distribution()->grid_level().level();
1483 const int level2 = spGridFct2.dof_distribution()->grid_level().level();
1484
1485 if(level1 > level2){
1486 // level check
1487 TDistIntegrand spIntegrand(spGridFct1, fct1, spGridFct2, fct2);
1488 return IntegrateSubsets(spIntegrand, spGridFct1, subsets, quadOrder);
1489 }else{
1490 TDistIntegrand spIntegrand(spGridFct2, fct2, spGridFct1, fct1);
1491 return IntegrateSubsets(spIntegrand, spGridFct2, subsets, quadOrder);
1492 }
1493
1494}
1495
1497template <typename TDistIntegrand, typename TGridFunction>
1498number GridFunctionDistance2(TGridFunction& spGridFct1, const char* cmp1,
1499 TGridFunction& spGridFct2, const char* cmp2,
1500 int quadOrder, const char* subsets, ConstSmartPtr<typename TDistIntegrand::weight_type> spWeights)
1501{
1502// get function id of name
1503 const size_t fct1 = spGridFct1.fct_id_by_name(cmp1);
1504 const size_t fct2 = spGridFct2.fct_id_by_name(cmp2);
1505
1506// check that function exists
1507 if(fct1 >= spGridFct1.num_fct())
1508 UG_THROW("GridFunctionDistance: Function space does not contain"
1509 " a function with name " << cmp1 << ".");
1510 if(fct2 >= spGridFct2.num_fct())
1511 UG_THROW("GridFunctionDistance: Function space does not contain"
1512 " a function with name " << cmp2 << ".");
1513
1514// get top level of gridfunctions
1515 const int level1 = spGridFct1.dof_distribution()->grid_level().level();
1516 const int level2 = spGridFct2.dof_distribution()->grid_level().level();
1517
1518 // w/ weights
1519 if(level1 > level2){
1520 TDistIntegrand spIntegrand(spGridFct1, fct1, spGridFct2, fct2, spWeights);
1521 return IntegrateSubsets(spIntegrand, spGridFct1, subsets, quadOrder);
1522 }else{
1523 TDistIntegrand spIntegrand(spGridFct2, fct2, spGridFct1, fct1, spWeights);
1524 return IntegrateSubsets(spIntegrand, spGridFct2, subsets, quadOrder);
1525 }
1526}
1527
1528
1530template <typename TDistIntegrand, typename TGridFunction>
1531number GridFunctionDistance2(TGridFunction& spGridFct1, const char* cmp1,
1532 TGridFunction& spGridFct2, const char* cmp2,
1533 int quadOrder, const char* subsets,
1535 number distAvg12)
1536{
1537// get function id of name
1538 const size_t fct1 = spGridFct1.fct_id_by_name(cmp1);
1539 const size_t fct2 = spGridFct2.fct_id_by_name(cmp2);
1540
1541// check that function exists
1542 if(fct1 >= spGridFct1.num_fct())
1543 UG_THROW("GridFunctionDistance: Function space does not contain"
1544 " a function with name " << cmp1 << ".");
1545 if(fct2 >= spGridFct2.num_fct())
1546 UG_THROW("GridFunctionDistance: Function space does not contain"
1547 " a function with name " << cmp2 << ".");
1548
1549// get top level of gridfunctions
1550 const int level1 = spGridFct1.dof_distribution()->grid_level().level();
1551 const int level2 = spGridFct2.dof_distribution()->grid_level().level();
1552
1553 // w/ weights
1554 if(level1 > level2){
1555 TDistIntegrand spIntegrand(spGridFct1, fct1, spGridFct2, fct2, spWeights, distAvg12);
1556 return IntegrateSubsets(spIntegrand, spGridFct1, subsets, quadOrder);
1557 }else{
1558 TDistIntegrand spIntegrand(spGridFct2, fct2, spGridFct1, fct1, spWeights, -distAvg12);
1559 return IntegrateSubsets(spIntegrand, spGridFct2, subsets, quadOrder);
1560 }
1561}
1562
1563
1564
1566// L2 Integrand
1568
1570template <typename TGridFunction>
1572 : public StdIntegrand<number, TGridFunction::dim, L2Integrand<TGridFunction> >
1573{
1574 public:
1575 // world dimension of grid function
1576 static const int worldDim = TGridFunction::dim;
1578
1579 protected:
1580 // grid function data
1582
1585
1586 public:
1588 L2Integrand(TGridFunction& spGridFct, size_t cmp)
1589 : m_scalarData(spGridFct, cmp), m_spWeight(make_sp(new ConstUserNumber<worldDim>(1.0)))
1590 {};
1591
1592 L2Integrand(TGridFunction& spGridFct, size_t cmp, ConstSmartPtr<weight_type> spWeight)
1593 : m_scalarData(spGridFct, cmp), m_spWeight(spWeight)
1594 {};
1595
1597 virtual ~L2Integrand() {};
1598
1600 virtual void set_subset(int si)
1601 {
1602 if(!m_scalarData.is_def_in_subset(si))
1603 UG_THROW("L2ErrorIntegrand: Grid function component" <<m_scalarData.fct() <<" not defined on subset "<<si);
1605 }
1606
1608 template <int elemDim>
1609 void evaluate(number vValue[],
1610 const MathVector<worldDim> vGlobIP[],
1611 GridObject* pElem,
1612 const MathVector<worldDim> vCornerCoords[],
1613 const MathVector<elemDim> vLocIP[],
1615 const size_t numIP)
1616 {
1617 // get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
1619
1620 // element weights
1621 typedef typename weight_type::data_type ipdata_type;
1622 std::vector<ipdata_type> locElemWeights(numIP, 1.0);
1623 UG_ASSERT(m_spWeight.valid(), "L2Integrand::evaluate requires valid weights!");
1624 (*m_spWeight)(&locElemWeights[0], vGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), numIP);
1625
1626 try{
1627 // get trial space
1628 const LocalShapeFunctionSet<elemDim>& rTrialSpace =
1629 LocalFiniteElementProvider::get<elemDim>(roid, m_scalarData.id());
1630
1631 // number of dofs on element
1632 const size_t num_sh = rTrialSpace.num_sh();
1633
1634 // get multiindices of element
1635 std::vector<DoFIndex> ind; // aux. index array
1636 m_scalarData.dof_indices(pElem, ind);
1637
1638 // check multi indices
1639 if(ind.size() != num_sh)
1640 UG_THROW("L2Integrand::evaluate: Wrong number of multi indices.");
1641
1642 // loop all integration points
1643 for(size_t ip = 0; ip < numIP; ++ip)
1644 {
1645
1646 // compute approximated solution at integration point
1647 number approxSolIP = 0.0;
1648 for(size_t sh = 0; sh < num_sh; ++sh)
1649 {
1650 // get value at shape point (e.g. corner for P1 fct)
1651 // and add shape fct at ip * value at shape
1652 const number valSH = DoFRef(m_scalarData.grid_function(), ind[sh]);
1653 approxSolIP += valSH * rTrialSpace.shape(sh, vLocIP[ip]);
1654 }
1655
1656 // get square
1657 vValue[ip] = locElemWeights[ip]*approxSolIP*approxSolIP;
1658
1659 }
1660
1661 }
1662 UG_CATCH_THROW("L2FuncIntegrand::values: trial space missing.");
1663 }
1664};
1665
1678template <typename TGridFunction>
1679number L2Norm2(TGridFunction& u, const char* cmp,
1680 int quadOrder, const char* subsets,
1682{
1683// get function id of name
1684 const size_t fct = u.fct_id_by_name(cmp);
1685
1686// check that function exists
1687 UG_COND_THROW(fct >= u.num_fct(), "L2Norm: Function space does not contain"
1688 " a function with name " << cmp << ".");
1689
1690 L2Integrand<TGridFunction> integrandL2(u, fct, spWeight);
1691 return IntegrateSubsets(integrandL2, u, subsets, quadOrder);
1692}
1693
1694template <typename TGridFunction>
1695number L2Norm2(TGridFunction& u, const char* cmp,
1696 int quadOrder, const char* subsets)
1697{
1698// get function id of name
1699 const size_t fct = u.fct_id_by_name(cmp);
1700
1701// check that function exists
1702 UG_COND_THROW(fct >= u.num_fct(), "L2Norm: Function space does not contain"
1703 " a function with name " << cmp << ".");
1704
1705 L2Integrand<TGridFunction> integrandL2(u, fct);
1706 return IntegrateSubsets(integrandL2, u, subsets, quadOrder);
1707}
1708
1709template <typename TGridFunction>
1710number L2Norm(TGridFunction& u, const char* cmp,
1711 int quadOrder, const char* subsets)
1712{
1713 return sqrt(L2Norm2(u, cmp, quadOrder, subsets));
1714}
1723template <typename TGridFunction>
1724number L2Norm(TGridFunction& gridFct, const char* cmp, int quadOrder)
1725{ return L2Norm(gridFct, cmp, quadOrder, NULL); }
1726
1727template <typename TGridFunction>
1728number L2Norm(SmartPtr<TGridFunction> spGridFct, const char* cmp, int quadOrder, const char* subsets)
1729{ return L2Norm(*spGridFct, cmp, quadOrder, subsets); }
1730
1731template <typename TGridFunction>
1732number L2Norm(SmartPtr<TGridFunction> spGridFct, const char* cmp, int quadOrder)
1733{ return L2Norm(spGridFct, cmp, quadOrder, NULL); }
1734
1735
1737template <typename TGridFunction>
1739 : public StdIntegrand<number, TGridFunction::dim, L2DistIntegrand<TGridFunction> >
1740{
1741 public:
1743 static const int worldDim = TGridFunction::dim;
1745
1746 protected:
1749
1752
1755
1757
1760
1761 public:
1762
1764 L2DistIntegrand(TGridFunction& fineGridFct, size_t fineCmp,
1765 TGridFunction& coarseGridFct, size_t coarseCmp)
1766 : m_fineData(fineGridFct, fineCmp), m_fineTopLevel(fineGridFct.dof_distribution()->grid_level().level()),
1767 m_coarseData(coarseGridFct, coarseCmp), m_coarseTopLevel(coarseGridFct.dof_distribution()->grid_level().level()),
1768 m_spMG(m_fineData.domain()->grid()), m_spWeight(make_sp(new ConstUserNumber<TGridFunction::dim>(1.0))),
1770 {
1772 "L2DiffIntegrand: fine and top level inverted.");
1773 UG_COND_THROW(m_fineData.domain().get() != m_coarseData.domain().get(),
1774 "L2DiffIntegrand: grid functions defined on different domains.");
1775 };
1776
1778 L2DistIntegrand(TGridFunction& fineGridFct, size_t fineCmp,
1779 TGridFunction& coarseGridFct, size_t coarseCmp, ConstSmartPtr<weight_type> spWeight)
1780 : m_fineData(fineGridFct, fineCmp), m_fineTopLevel(fineGridFct.dof_distribution()->grid_level().level()),
1781 m_coarseData(coarseGridFct, coarseCmp), m_coarseTopLevel(coarseGridFct.dof_distribution()->grid_level().level()),
1782 m_spMG(m_fineData.domain()->grid()), m_spWeight(spWeight),
1784 {
1786 "L2DiffIntegrand: fine and top level inverted.");
1787 UG_COND_THROW(m_fineData.domain().get() != m_coarseData.domain().get(),
1788 "L2DiffIntegrand: grid functions defined on different domains.");
1789 };
1790
1792 L2DistIntegrand(TGridFunction& fineGridFct, size_t fineCmp,
1793 TGridFunction& coarseGridFct, size_t coarseCmp, ConstSmartPtr<weight_type> spWeight, number dist12)
1794 : m_fineData(fineGridFct, fineCmp), m_fineTopLevel(fineGridFct.dof_distribution()->grid_level().level()),
1795 m_coarseData(coarseGridFct, coarseCmp), m_coarseTopLevel(coarseGridFct.dof_distribution()->grid_level().level()),
1796 m_spMG(m_fineData.domain()->grid()), m_spWeight(spWeight),
1797 m_deltaFineCoarse(dist12)
1798 {
1800 "L2DiffIntegrand: fine and top level inverted.");
1801 UG_COND_THROW(m_fineData.domain().get() != m_coarseData.domain().get(),
1802 "L2DiffIntegrand: grid functions defined on different domains.");
1803 };
1804
1805
1806 virtual ~L2DistIntegrand() {}
1807
1809 virtual void set_subset(int si)
1810 {
1811 UG_COND_THROW(!m_fineData.is_def_in_subset(si),
1812 "L2DiffIntegrand: Grid function component" <<m_fineData.fct()<<" not defined on subset "<<si);
1813 UG_COND_THROW(!m_coarseData.is_def_in_subset(si),
1814 "L2DiffIntegrand: Grid function component" <<m_coarseData.fct()<<" not defined on subset "<<si);
1816 }
1817
1819 template <int elemDim>
1820 void evaluate(number vValue[],
1821 const MathVector<worldDim> vFineGlobIP[],
1822 GridObject* pFineElem,
1823 const MathVector<worldDim> vCornerCoords[],
1824 const MathVector<elemDim> vFineLocIP[],
1826 const size_t numIP)
1827 {
1828 typedef typename TGridFunction::template dim_traits<elemDim>::grid_base_object Element;
1829
1830 // get coarse element
1831 GridObject* pCoarseElem = pFineElem;
1833 int parentLevel = m_spMG->get_level(pCoarseElem);
1834 while(parentLevel > m_coarseTopLevel){
1835 pCoarseElem = m_spMG->get_parent(pCoarseElem);
1836 parentLevel = m_spMG->get_level(pCoarseElem);
1837 }
1838 }
1839
1840 // get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
1841 const ReferenceObjectID fineROID = pFineElem->reference_object_id();
1842 const ReferenceObjectID coarseROID = pCoarseElem->reference_object_id();
1843
1844 // get corner coordinates
1845 std::vector<MathVector<worldDim> > vCornerCoarse;
1846 CollectCornerCoordinates(vCornerCoarse, *static_cast<Element*>(pCoarseElem), *m_coarseData.domain());
1847
1848 // get Reference Mapping
1850 = ReferenceMappingProvider::get<elemDim, worldDim>(coarseROID, vCornerCoarse);
1851
1852 std::vector<MathVector<elemDim> > vCoarseLocIP;
1853 vCoarseLocIP.resize(numIP);
1854 for(size_t ip = 0; ip < vCoarseLocIP.size(); ++ip) VecSet(vCoarseLocIP[ip], 0.0);
1855 map.global_to_local(&vCoarseLocIP[0], vFineGlobIP, numIP);
1856
1857 // element weights
1858 typedef typename weight_type::data_type ipdata_type;
1859 std::vector<ipdata_type> fineElemWeights(numIP, 1.0);
1860 UG_ASSERT(m_spWeight.valid(), "L2DistIntegrand::evaluate requires valid weights! ");
1861 (*m_spWeight)(&fineElemWeights[0], vFineGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), numIP);
1862
1863 try{
1864 // get trial space
1865 const LocalShapeFunctionSet<elemDim>& rFineLSFS =
1866 LocalFiniteElementProvider::get<elemDim>(fineROID, m_fineData.id());
1867 const LocalShapeFunctionSet<elemDim>& rCoarseLSFS =
1868 LocalFiniteElementProvider::get<elemDim>(coarseROID, m_coarseData.id());
1869
1870 // get multiindices of element
1871 std::vector<DoFIndex> vFineMI, vCoarseMI;
1872 m_fineData.dof_indices(pFineElem, vFineMI);
1873 m_coarseData.dof_indices(pCoarseElem, vCoarseMI);
1874
1875 // loop all integration points
1876 for(size_t ip = 0; ip < numIP; ++ip)
1877 {
1878 // compute approximated solution at integration point
1879 number fineSolIP = 0.0;
1880 for(size_t sh = 0; sh < vFineMI.size(); ++sh)
1881 {
1882 // get value at shape point (e.g. corner for P1 fct)
1883 const number val = DoFRef(m_fineData.grid_function(), vFineMI[sh]);
1884
1885 // add shape fct at ip * value at shape
1886 fineSolIP += val * rFineLSFS.shape(sh, vFineLocIP[ip]);
1887 }
1888 number coarseSolIP = 0.0;
1889 for(size_t sh = 0; sh < vCoarseMI.size(); ++sh)
1890 {
1891 // get value at shape point (e.g. corner for P1 fct)
1892 const number val = DoFRef(m_coarseData.grid_function(), vCoarseMI[sh]);
1893
1894 // add shape fct at ip * value at shape
1895 coarseSolIP += val * rCoarseLSFS.shape(sh, vCoarseLocIP[ip]);
1896 }
1897
1898 // get squared of difference
1899 vValue[ip] = fineElemWeights[ip]*(fineSolIP - coarseSolIP -m_deltaFineCoarse)*(fineSolIP-coarseSolIP-m_deltaFineCoarse);
1900 }
1901
1902 }
1903 UG_CATCH_THROW("L2DistIntegrand::evaluate: trial space missing.");
1904 }
1905};
1906
1907
1909template <typename TGridFunction>
1910number L2Distance2(TGridFunction& spGridFct1, const char* cmp1,
1911 TGridFunction& spGridFct2, const char* cmp2,
1912 int quadOrder, const char* subsets,
1913 ConstSmartPtr<typename L2Integrand<TGridFunction>::weight_type> spWeight, number avgDist12=0.0)
1914{
1915 return GridFunctionDistance2<L2DistIntegrand<TGridFunction>, TGridFunction>
1916 (spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, subsets, spWeight, avgDist12);
1917}
1918
1919
1921template <typename TGridFunction>
1922number L2Distance2(TGridFunction& spGridFct1, const char* cmp1,
1923 TGridFunction& spGridFct2, const char* cmp2,
1924 int quadOrder, const char* subsets)
1925{
1926 return GridFunctionDistance2<L2DistIntegrand<TGridFunction>, TGridFunction>
1927 (spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, subsets);
1928}
1929
1931template <typename TGridFunction>
1932number L2Distance(TGridFunction& spGridFct1, const char* cmp1,
1933 TGridFunction& spGridFct2, const char* cmp2,
1934 int quadOrder, const char* subsets)
1935{
1936 return sqrt(L2Distance2(spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, subsets));
1937}
1938
1939
1940template <typename TGridFunction>
1941number L2Error(SmartPtr<TGridFunction> spGridFct1, const char* cmp1,
1942 SmartPtr<TGridFunction> spGridFct2, const char* cmp2,
1943 int quadOrder)
1944{
1945 return L2Distance(*spGridFct1, cmp1, *spGridFct2, cmp2, quadOrder, NULL);
1946}
1947
1948template <typename TGridFunction>
1949number L2Error(SmartPtr<TGridFunction> spGridFct1, const char* cmp1,
1950 SmartPtr<TGridFunction> spGridFct2, const char* cmp2,
1951 int quadOrder, const char* subsets)
1952{
1953 return L2Distance(*spGridFct1, cmp1, *spGridFct2, cmp2, quadOrder, subsets);
1954}
1955
1957// H1 semi-norm Integrand
1959
1960
1961
1963template <typename TGridFunction>
1965 : public StdIntegrand<number, TGridFunction::dim, H1SemiIntegrand<TGridFunction> >
1966{
1967 public:
1969 static const int worldDim = TGridFunction::dim;
1971
1972 protected:
1975
1978
1979 public:
1981 H1SemiIntegrand(TGridFunction& gridFct, size_t cmp)
1982 : m_scalarData(gridFct, cmp), m_spWeight(make_sp(new ConstUserMatrix<worldDim>(1.0))) {}
1983
1985 H1SemiIntegrand(TGridFunction& gridFct, size_t cmp, ConstSmartPtr<weight_type> spWeight)
1986 : m_scalarData(gridFct, cmp), m_spWeight(spWeight) {}
1987
1989 virtual ~H1SemiIntegrand() {};
1990
1992 virtual void set_subset(int si)
1993 {
1994
1995 UG_COND_THROW(!m_scalarData.is_def_in_subset(si), "H1Error: Grid function component"
1996 <<m_scalarData.fct()<<" not defined on subset "<<si);
1998 }
1999
2001 template <int elemDim>
2002 void evaluate(number vValue[],
2003 const MathVector<worldDim> vGlobIP[],
2004 GridObject* pElem,
2005 const MathVector<worldDim> vCornerCoords[],
2006 const MathVector<elemDim> vLocIP[],
2008 const size_t numIP)
2009 {
2010 // get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
2011 const ReferenceObjectID roid = pElem->reference_object_id();
2012 const TGridFunction &gridFct= m_scalarData.grid_function();
2013
2015 = ReferenceMappingProvider::get<elemDim, worldDim>(roid, vCornerCoords);
2016
2017 typedef typename weight_type::data_type ipdata_type;
2018
2019 std::vector<ipdata_type> elemWeights(numIP, MathMatrix<worldDim, worldDim>());
2020 UG_ASSERT(m_spWeight.valid(), "H1SemiIntegrand::evaluate requires valid weights!");
2021
2022
2024 {
2025 // get local solution if needed
2026 LocalIndices ind;
2027 LocalVector uloc;
2028 gridFct.indices(pElem, ind); // get global indices
2029 uloc.resize(ind); // adapt local algebra
2030 GetLocalVector(uloc, gridFct); // read local values of u
2031
2032 // compute data
2033 try{
2034 (*m_spWeight)(&elemWeights[0], vGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), pElem,
2035 vCornerCoords, vLocIP, numIP, &uloc, NULL);
2036 } UG_CATCH_THROW("H1SemiIntegrand: Cannot evaluate weight data.");
2037 }
2038 else
2039 {
2040 // compute data
2041 try{
2042 (*m_spWeight)(&elemWeights[0], vGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), numIP);
2043 } UG_CATCH_THROW("H1SemiIntegrand: Cannot evaluate weight data.");
2044 }
2045
2046
2047 try{
2048
2049
2050
2051
2052 // get trial space
2053 const LocalShapeFunctionSet<elemDim>& rTrialSpace =
2054 LocalFiniteElementProvider::get<elemDim>(roid, m_scalarData.id());
2055
2056 // number of dofs on element
2057 const size_t num_sh = rTrialSpace.num_sh();
2058
2059 // get multiindices of element
2060 std::vector<DoFIndex> ind; // aux. index array
2061 gridFct.dof_indices(pElem, m_scalarData.fct(), ind);
2062
2063 // check multi indices
2064 UG_COND_THROW(ind.size() != num_sh, "H1SemiNormFuncIntegrand::evaluate: Wrong number of multi-)indices.");
2065
2066 // loop all integration points
2067 std::vector<MathVector<elemDim> > vLocGradient(num_sh);
2068 for(size_t ip = 0; ip < numIP; ++ip)
2069 {
2070 // compute shape gradients at ip
2071 rTrialSpace.grads(&vLocGradient[0], vLocIP[ip]);
2072
2073 // compute approximated solution at integration point
2074 number approxSolIP = 0.0;
2075 MathVector<elemDim> tmpVec(0.0);
2076 for(size_t sh = 0; sh < num_sh; ++sh)
2077 {
2078 // get value at shape point (e.g. corner for P1 fct)
2079 const number valSH = DoFRef(gridFct, ind[sh]);
2080
2081 // add shape fct at ip * value at shape
2082 approxSolIP += valSH * rTrialSpace.shape(sh, vLocIP[ip]);
2083
2084 // add gradient at ip
2085 VecScaleAppend(tmpVec, valSH, vLocGradient[sh]);
2086 }
2087
2088 // compute gradient
2089 MathVector<worldDim> approxGradIP;
2091 map.jacobian_transposed_inverse(JTInv, vLocIP[ip]);//Inverse(JTInv, vJT[ip]);
2092
2093#ifdef UG_DEBUG
2094 CheckGeneralizedInverse<worldDim,elemDim>(vJT[ip], JTInv);
2095#endif //UG_DEBUG
2096
2097 MatVecMult(approxGradIP, JTInv, tmpVec);
2098
2099 // get norm squared
2100 MathVector<worldDim> approxDGradIP;
2101 MatVecMult(approxDGradIP, elemWeights[ip], approxGradIP);
2102 vValue[ip] = VecDot(approxDGradIP, approxGradIP);
2103 }
2104
2105 }
2106 UG_CATCH_THROW("H1SemiIntegrand::evaluate: trial space missing.");
2107 }
2108};
2109
2110
2112
2123template <typename TGridFunction>
2124number H1SemiNorm2(TGridFunction& gridFct, const char* cmp, int quadOrder, const char* subsets=NULL,
2126{
2127// get function id of name
2128 const size_t fct = gridFct.fct_id_by_name(cmp);
2129
2130// check that function exists
2131 UG_COND_THROW(fct >= gridFct.num_fct(), "H1SemiNorm: Function space does not contain"
2132 " a function with name " << cmp << ".");
2133 if (weights.invalid()) {
2134 H1SemiIntegrand<TGridFunction> integrand(gridFct, fct);
2135 return IntegrateSubsets(integrand, gridFct, subsets, quadOrder);
2136 } else {
2137 H1SemiIntegrand<TGridFunction> integrand(gridFct, fct, weights);
2138 return IntegrateSubsets(integrand, gridFct, subsets, quadOrder);
2139 }
2140}
2141
2143template <typename TGridFunction>
2144number H1SemiNorm(TGridFunction& gridFct, const char* cmp, int quadOrder, const char* subsets=NULL,
2146{
2147 return (sqrt(H1SemiNorm2(gridFct, cmp, quadOrder, subsets, weights)));
2148}
2149
2150// Delegating to H1SemiNorm
2151template <typename TGridFunction>
2152number H1SemiNorm(SmartPtr<TGridFunction> spGridFct, const char* cmp, int quadOrder, const char* subsets)
2153{ return H1SemiNorm(*spGridFct, cmp, quadOrder, subsets); }
2154
2155template <typename TGridFunction>
2156number H1SemiNorm(SmartPtr<TGridFunction> spGridFct, const char* cmp, int quadOrder,
2157 const char* subsets, ConstSmartPtr<typename H1SemiIntegrand<TGridFunction>::weight_type> weights = SPNULL)
2158{ return H1SemiNorm(*spGridFct, cmp, quadOrder, subsets, weights); }
2159
2160template <typename TGridFunction>
2161number H1SemiNorm( SmartPtr<TGridFunction> spGridFct, const char* cmp, int quadOrder)
2162{ return H1SemiNorm(*spGridFct, cmp, quadOrder, NULL); }
2163
2164template <typename TGridFunction>
2165number H1SemiNorm( SmartPtr<TGridFunction> spGridFct, const char* cmp, int quadOrder,
2167{ return H1SemiNorm(*spGridFct, cmp, quadOrder, NULL, weights); }
2168
2170template <typename TGridFunction>
2171class H1SemiDistIntegrand : public StdIntegrand<number, TGridFunction::dim, H1SemiDistIntegrand<TGridFunction> >
2172{
2173 public:
2175 static const int worldDim = TGridFunction::dim;
2177
2178 private:
2181
2184
2187
2190
2191 public:
2193 H1SemiDistIntegrand(TGridFunction& fineGridFct, size_t fineCmp,
2194 TGridFunction& coarseGridFct, size_t coarseCmp)
2195 : m_fineData(fineGridFct, fineCmp),
2196 m_fineTopLevel(fineGridFct.dof_distribution()->grid_level().level()),
2197 m_coarseData(coarseGridFct, coarseCmp),
2198 m_coarseTopLevel(coarseGridFct.dof_distribution()->grid_level().level()),
2199 m_spMG(fineGridFct.domain()->grid()),
2200 m_spWeight(new ConstUserNumber<TGridFunction::dim>(1.0))
2201 {
2203 UG_THROW("H1SemiDiffIntegrand: fine and top level inverted.");
2204
2205 if(m_fineData.domain().get() != m_coarseData.domain().get())
2206 UG_THROW("H1SemiDiffIntegrand: grid functions defined on different domains.");
2207 };
2208
2210 H1SemiDistIntegrand(TGridFunction& fineGridFct, size_t fineCmp,
2211 TGridFunction& coarseGridFct, size_t coarseCmp,
2213 : m_fineData(fineGridFct, fineCmp),
2214 m_fineTopLevel(fineGridFct.dof_distribution()->grid_level().level()),
2215 m_coarseData(coarseGridFct, coarseCmp),
2216 m_coarseTopLevel(coarseGridFct.dof_distribution()->grid_level().level()),
2217 m_spMG(fineGridFct.domain()->grid()),
2218 m_spWeight(spWeight)
2219 {
2220 UG_COND_THROW(m_fineTopLevel < m_coarseTopLevel, "H1SemiDiffIntegrand: fine and top level inverted.");
2221 UG_COND_THROW(m_fineData.domain().get() != m_coarseData.domain().get(), "H1SemiDiffIntegrand: grid functions defined on different domains.");
2222 }
2224
2226 virtual void set_subset(int si)
2227 {
2228
2229 UG_COND_THROW(!m_fineData.is_def_in_subset(si), "H1SemiDiffIntegrand: Grid function component"
2230 <<m_fineData.fct()<<" not defined on subset "<<si);
2231 UG_COND_THROW(!m_coarseData.is_def_in_subset(si), "H1SemiDiffIntegrand: Grid function component"
2232 <<m_coarseData.fct()<<" not defined on subset "<<si);
2234 }
2235
2237 template <int elemDim>
2238 void evaluate(number vValue[],
2239 const MathVector<worldDim> vFineGlobIP[],
2240 GridObject* pFineElem,
2241 const MathVector<worldDim> vCornerCoords[],
2242 const MathVector<elemDim> vFineLocIP[],
2244 const size_t numIP)
2245 {
2246 typedef typename TGridFunction::template dim_traits<elemDim>::grid_base_object Element;
2247
2248 const TGridFunction &fineGridFct = m_fineData.grid_function();
2249 const TGridFunction &coarseGridFct = m_coarseData.grid_function();
2250
2251 // get coarse element
2252 GridObject* pCoarseElem = pFineElem;
2254 int parentLevel = m_spMG->get_level(pCoarseElem);
2255 while(parentLevel > m_coarseTopLevel){
2256 pCoarseElem = m_spMG->get_parent(pCoarseElem);
2257 parentLevel = m_spMG->get_level(pCoarseElem);
2258 }
2259 }
2260
2261 // get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
2262 const ReferenceObjectID fineROID = pFineElem->reference_object_id();
2263 const ReferenceObjectID coarseROID = pCoarseElem->reference_object_id();
2264
2265 // get corner coordinates
2266 std::vector<MathVector<worldDim> > vCornerCoarse;
2267 CollectCornerCoordinates(vCornerCoarse, *static_cast<Element*>(pCoarseElem), *m_coarseData.domain());
2268
2269 // get reference Mapping
2271 = ReferenceMappingProvider::get<elemDim, worldDim>(coarseROID, vCornerCoarse);
2273 = ReferenceMappingProvider::get<elemDim, worldDim>(fineROID, vCornerCoords);
2274
2275 std::vector<MathVector<elemDim> > vCoarseLocIP;
2276 vCoarseLocIP.resize(numIP);
2277 for(size_t ip = 0; ip < vCoarseLocIP.size(); ++ip) VecSet(vCoarseLocIP[ip], 0.0);
2278 map.global_to_local(&vCoarseLocIP[0], vFineGlobIP, numIP);
2279
2280
2281 // determine weights
2282 std::vector<typename weight_type::data_type> elemWeights(numIP, MathMatrix<worldDim, worldDim>());
2283 UG_ASSERT(m_spWeight.valid(), "H1SemiDistIntegrand::evaluate requires valid weights!");
2284
2285 // get local solution (if required)
2287 {
2288
2289 LocalIndices ind;
2290 LocalVector u;
2291 fineGridFct.indices(pFineElem, ind); // get global indices
2292 u.resize(ind); // adapt local algebra
2293 GetLocalVector(u, fineGridFct); // read local values of u
2294
2295 // compute data
2296 try{
2297 (*m_spWeight)(&elemWeights[0], vFineGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), pFineElem,
2298 vCornerCoords, vFineLocIP, numIP, &u, NULL);
2299 } UG_CATCH_THROW("H1SemiDistIntegrand: Cannot evaluate data.");
2300 }
2301 else
2302 {
2303 // compute data
2304 try{
2305 (*m_spWeight)(&elemWeights[0], vFineGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), numIP);
2306 } UG_CATCH_THROW("H1SemiDistIntegrand: Cannot evaluate data.");
2307 }
2308
2309 try{
2310
2311
2312 // get trial space
2313 const LocalShapeFunctionSet<elemDim>& rFineLSFS =
2314 LocalFiniteElementProvider::get<elemDim>(fineROID, m_fineData.id());
2315 const LocalShapeFunctionSet<elemDim>& rCoarseLSFS =
2316 LocalFiniteElementProvider::get<elemDim>(coarseROID, m_coarseData.id());
2317
2318 // get multiindices of element
2319 std::vector<DoFIndex> vFineMI, vCoarseMI;
2320 m_fineData.dof_indices(pFineElem, vFineMI);
2321 m_coarseData.dof_indices(pCoarseElem, vCoarseMI);
2322
2323 std::vector<MathVector<elemDim> > vFineLocGradient(vFineMI.size());
2324 std::vector<MathVector<elemDim> > vCoarseLocGradient(vCoarseMI.size());
2325
2326 // loop all integration points
2327 for(size_t ip = 0; ip < numIP; ++ip)
2328 {
2329 // compute shape gradients at ip
2330 rFineLSFS.grads(&vFineLocGradient[0], vFineLocIP[ip]);
2331 rCoarseLSFS.grads(&vCoarseLocGradient[0], vCoarseLocIP[ip]);
2332
2333 // compute approximated solutions at integration point
2334 number fineSolIP = 0.0;
2335 MathVector<elemDim> fineLocTmp(0.0);
2336 for(size_t sh = 0; sh < vFineMI.size(); ++sh)
2337 {
2338 const number val = DoFRef(fineGridFct, vFineMI[sh]);
2339 fineSolIP += val * rFineLSFS.shape(sh, vFineLocIP[ip]);
2340 VecScaleAppend(fineLocTmp, val, vFineLocGradient[sh]);
2341 }
2342
2343 number coarseSolIP = 0.0;
2344 MathVector<elemDim> coarseLocTmp(0.0);
2345 for(size_t sh = 0; sh < vCoarseMI.size(); ++sh)
2346 {
2347 const number val = DoFRef(coarseGridFct, vCoarseMI[sh]);
2348 coarseSolIP += val * rCoarseLSFS.shape(sh, vCoarseLocIP[ip]);
2349 VecScaleAppend(coarseLocTmp, val, vCoarseLocGradient[sh]);
2350 }
2351
2352 // compute global gradient
2353 MathVector<worldDim> fineGradIP;
2355 mapF.jacobian_transposed_inverse(fineJTInv, vFineLocIP[ip]);//Inverse(fineJTInv, vJT[ip]);
2356
2357#ifdef UG_DEBUG
2358 CheckGeneralizedInverse<worldDim,elemDim>(vJT[ip], fineJTInv);
2359#endif //UG_DEBUG
2360
2361 MatVecMult(fineGradIP, fineJTInv, fineLocTmp);
2362
2363 // compute global gradient
2364 MathVector<worldDim> coarseGradIP;
2366 map.jacobian_transposed_inverse(coarseJTInv, vCoarseLocIP[ip]);
2367 MatVecMult(coarseGradIP, coarseJTInv, coarseLocTmp);
2368
2369 // get squared of difference
2370 /*vValue[ip] = (coarseSolIP - fineSolIP);
2371 vValue[ip] *= vValue[ip]; */
2372 vValue[ip] = VecDistanceSq(coarseGradIP, fineGradIP, elemWeights[ip]);
2373 }
2374
2375 }
2376 UG_CATCH_THROW("H1SemiDiffIntegrand::evaluate: trial space missing.");
2377 }
2378};
2379
2380
2382template <typename TGridFunction>
2383number H1SemiError2(SmartPtr<TGridFunction> spGridFct1, const char* cmp1,
2384 SmartPtr<TGridFunction> spGridFct2, const char* cmp2,
2385 int quadOrder, const char* subsets)
2386{
2387 return GridFunctionDistance2<H1SemiDistIntegrand<TGridFunction>, TGridFunction>
2388 (*spGridFct1, cmp1, *spGridFct2, cmp2, quadOrder, subsets);
2389}
2390
2392template <typename TGridFunction>
2393number H1SemiError(SmartPtr<TGridFunction> spGridFct1, const char* cmp1,
2394 SmartPtr<TGridFunction> spGridFct2, const char* cmp2,
2395 int quadOrder, const char* subsets)
2396{
2397 return sqrt(H1SemiError2(*spGridFct1, cmp1, *spGridFct2, cmp2, quadOrder, subsets));
2398}
2399
2401template <typename TGridFunction>
2402number H1SemiError(SmartPtr<TGridFunction> spGridFct1, const char* cmp1,
2403 SmartPtr<TGridFunction> spGridFct2, const char* cmp2,
2404 int quadOrder)
2405{
2406 return H1SemiError(*spGridFct1, cmp1, *spGridFct2, cmp2, quadOrder, NULL);
2407}
2408
2410template <typename TGridFunction>
2411number H1SemiDistance2(TGridFunction& spGridFct1, const char* cmp1,
2412 TGridFunction& spGridFct2, const char* cmp2,
2413 int quadOrder, const char* subsets,
2415{
2416 return GridFunctionDistance2<H1SemiDistIntegrand<TGridFunction>, TGridFunction>
2417 (spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, subsets, weights);
2418}
2419
2421template <typename TGridFunction>
2422number H1SemiDistance(TGridFunction& spGridFct1, const char* cmp1,
2423 TGridFunction& spGridFct2, const char* cmp2,
2424 int quadOrder, const char* subsets,
2426{ return sqrt(H1SemiDistance2(spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, subsets, weights)); }
2427
2429template <typename TGridFunction>
2430number H1SemiDistance2(TGridFunction& spGridFct1, const char* cmp1,
2431 TGridFunction& spGridFct2, const char* cmp2,
2432 int quadOrder, ConstSmartPtr<typename H1SemiDistIntegrand<TGridFunction>::weight_type > weights)
2433{ return H1SemiDistance2(spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, NULL, weights); }
2434
2436template <typename TGridFunction>
2437number H1SemiDistance(TGridFunction& spGridFct1, const char* cmp1,
2438 TGridFunction& spGridFct2, const char* cmp2,
2439 int quadOrder, ConstSmartPtr<typename H1SemiDistIntegrand<TGridFunction>::weight_type > weights)
2440{ return sqrt(H1SemiDistance2(spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, NULL, weights)); }
2441
2442
2443
2444
2446// H1 semi-norm Integrand
2448
2450template <typename TGridFunction>
2452 : public StdIntegrand<number, TGridFunction::dim, H1EnergyIntegrand<TGridFunction> >
2453{
2454 public:
2456 static const int worldDim = TGridFunction::dim;
2458
2459 protected:
2462
2465
2466 public:
2468 H1EnergyIntegrand(TGridFunction& gridFct, size_t cmp)
2469 : m_scalarData(gridFct, cmp), m_spWeight(make_sp(new ConstUserMatrix<worldDim>(1.0))) {}
2470
2472 H1EnergyIntegrand(TGridFunction& gridFct, size_t cmp, ConstSmartPtr<weight_type> spWeight)
2473 : m_scalarData(gridFct, cmp), m_spWeight(spWeight) {}
2474
2477
2479 virtual void set_subset(int si)
2480 {
2481
2482 UG_COND_THROW(!m_scalarData.is_def_in_subset(si), "H1EnergyIntegrand: Grid function component"
2483 <<m_scalarData.fct()<<" not defined on subset "<<si);
2485 }
2486
2488 template <int elemDim>
2489 void evaluate(number vValue[],
2490 const MathVector<worldDim> vGlobIP[],
2491 GridObject* pElem,
2492 const MathVector<worldDim> vCornerCoords[],
2493 const MathVector<elemDim> vLocIP[],
2495 const size_t numIP)
2496 {
2497 // get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
2498 const ReferenceObjectID roid = pElem->reference_object_id();
2499 const TGridFunction &gridFct= m_scalarData.grid_function();
2500
2502 = ReferenceMappingProvider::get<elemDim, worldDim>(roid, vCornerCoords);
2503
2504 typedef typename weight_type::data_type ipdata_type;
2505
2506 std::vector<ipdata_type> elemWeights(numIP, MathMatrix<worldDim, worldDim>());
2507 UG_ASSERT(m_spWeight.valid(), "H1EnergyIntegrand::evaluate requires valid weights!");
2508
2509
2510 if(m_spWeight->requires_grid_fct())
2511 {
2512 // get local solution if needed
2513 LocalIndices ind;
2514 LocalVector uloc;
2515 gridFct.indices(pElem, ind); // get global indices
2516 uloc.resize(ind); // adapt local algebra
2517 GetLocalVector(uloc, gridFct); // read local values of u
2518
2519 // compute data
2520 try{
2521 (*m_spWeight)(&elemWeights[0], vGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), pElem,
2522 vCornerCoords, vLocIP, numIP, &uloc, NULL);
2523 } UG_CATCH_THROW("H1EnergyIntegrand: Cannot evaluate weight data.");
2524 }
2525 else
2526 {
2527 // compute data
2528 try{
2529 (*m_spWeight)(&elemWeights[0], vGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), numIP);
2530 } UG_CATCH_THROW("H1EnergyIntegrand: Cannot evaluate weight data.");
2531 }
2532
2533
2534 try{
2535
2536
2537
2538
2539 // get trial space
2540 const LocalShapeFunctionSet<elemDim>& rTrialSpace =
2541 LocalFiniteElementProvider::get<elemDim>(roid, m_scalarData.id());
2542
2543 // number of dofs on element
2544 const size_t num_sh = rTrialSpace.num_sh();
2545
2546 // get multiindices of element
2547 std::vector<DoFIndex> ind; // aux. index array
2548 gridFct.dof_indices(pElem, m_scalarData.fct(), ind);
2549
2550 // check multi indices
2551 UG_COND_THROW(ind.size() != num_sh, "H1EnergyIntegrand::evaluate: Wrong number of multi-)indices.");
2552
2553 // loop all integration points
2554 std::vector<MathVector<elemDim> > vLocGradient(num_sh);
2555 for(size_t ip = 0; ip < numIP; ++ip)
2556 {
2557 // compute shape gradients at ip
2558 rTrialSpace.grads(&vLocGradient[0], vLocIP[ip]);
2559
2560 // compute approximated solution at integration point
2561 number approxSolIP = 0.0;
2562 MathVector<elemDim> tmpVec(0.0);
2563 for(size_t sh = 0; sh < num_sh; ++sh)
2564 {
2565 // get value at shape point (e.g. corner for P1 fct)
2566 const number valSH = DoFRef(gridFct, ind[sh]);
2567
2568 // add shape fct at ip * value at shape
2569 approxSolIP += valSH * rTrialSpace.shape(sh, vLocIP[ip]);
2570
2571 // add gradient at ip
2572 VecScaleAppend(tmpVec, valSH, vLocGradient[sh]);
2573 }
2574
2575 // compute gradient
2576 MathVector<worldDim> approxGradIP;
2578 map.jacobian_transposed_inverse(JTInv, vLocIP[ip]);//Inverse(JTInv, vJT[ip]);
2579
2580#ifdef UG_DEBUG
2581 CheckGeneralizedInverse<worldDim,elemDim>(vJT[ip], JTInv);
2582#endif //UG_DEBUG
2583
2584
2585 MatVecMult(approxGradIP, JTInv, tmpVec);
2586
2587 // get norm squared
2588 MathVector<worldDim> approxDGradIP;
2589 MatVecMult(approxDGradIP, elemWeights[ip], approxGradIP);
2590 vValue[ip] = VecTwoNormSq(approxDGradIP);
2591 }
2592
2593 }
2594 UG_CATCH_THROW("H1EnergyIntegrand::evaluate: trial space missing.");
2595 }
2596};
2597
2598
2600
2611template <typename TGridFunction>
2612number H1EnergyNorm2(TGridFunction& gridFct, const char* cmp, int quadOrder, const char* subsets=NULL,
2614{
2615// get function id of name
2616 const size_t fct = gridFct.fct_id_by_name(cmp);
2617
2618// check that function exists
2619 UG_COND_THROW(fct >= gridFct.num_fct(), "H1SemiNorm: Function space does not contain"
2620 " a function with name " << cmp << ".");
2621 if (weights.invalid()) {
2622 H1EnergyIntegrand<TGridFunction> integrand(gridFct, fct);
2623 return IntegrateSubsets(integrand, gridFct, subsets, quadOrder);
2624 } else {
2625 H1EnergyIntegrand<TGridFunction> integrand(gridFct, fct, weights);
2626 return IntegrateSubsets(integrand, gridFct, subsets, quadOrder);
2627 }
2628}
2629template <typename TGridFunction>
2630number H1EnergyNorm(TGridFunction& gridFct, const char* cmp, int quadOrder, const char* subsets=NULL,
2632{
2633 return (sqrt(H1EnergyNorm2(gridFct, cmp, quadOrder, subsets, weights)));
2634}
2635
2636template <typename TGridFunction>
2637number H1EnergyNorm(SmartPtr<TGridFunction> spGridFct, const char* cmp, int quadOrder,
2638 const char* subsets, ConstSmartPtr<typename H1SemiIntegrand<TGridFunction>::weight_type> weights = SPNULL)
2639{ return H1EnergyNorm(*spGridFct, cmp, quadOrder, subsets, weights); }
2640
2641template <typename TGridFunction>
2642number H1EnergyNorm( SmartPtr<TGridFunction> spGridFct, const char* cmp, int quadOrder)
2643{ return H1EnergyNorm(spGridFct, cmp, quadOrder, NULL); }
2644
2645template <typename TGridFunction>
2646number H1EnergyNorm( SmartPtr<TGridFunction> spGridFct, const char* cmp, int quadOrder,
2648{ return H1EnergyNorm(spGridFct, cmp, quadOrder, NULL, weights); }
2649
2650
2651
2652
2654template <typename TGridFunction>
2656 : public StdIntegrand<number, TGridFunction::dim, H1EnergyDistIntegrand<TGridFunction> >
2657{
2658 public:
2660 static const int worldDim = TGridFunction::dim;
2662
2663 private:
2666
2669
2672
2675
2676 public:
2678 H1EnergyDistIntegrand(TGridFunction& fineGridFct, size_t fineCmp,
2679 TGridFunction& coarseGridFct, size_t coarseCmp)
2680 : m_fineData(fineGridFct, fineCmp),
2681 m_fineTopLevel(fineGridFct.dof_distribution()->grid_level().level()),
2682 m_coarseData(coarseGridFct, coarseCmp),
2683 m_coarseTopLevel(coarseGridFct.dof_distribution()->grid_level().level()),
2684 m_spMG(fineGridFct.domain()->grid()),
2685 m_spWeight(new ConstUserNumber<TGridFunction::dim>(1.0))
2686 {
2688 UG_THROW("H1EnergyDistIntegrand: fine and top level inverted.");
2689
2690 if(m_fineData.domain().get() != m_coarseData.domain().get())
2691 UG_THROW("H1EnergyDistIntegrand: grid functions defined on different domains.");
2692 };
2693
2695 H1EnergyDistIntegrand(TGridFunction& fineGridFct, size_t fineCmp,
2696 TGridFunction& coarseGridFct, size_t coarseCmp,
2698 : m_fineData(fineGridFct, fineCmp),
2699 m_fineTopLevel(fineGridFct.dof_distribution()->grid_level().level()),
2700 m_coarseData(coarseGridFct, coarseCmp),
2701 m_coarseTopLevel(coarseGridFct.dof_distribution()->grid_level().level()),
2702 m_spMG(fineGridFct.domain()->grid()),
2703 m_spWeight(spWeight)
2704 {
2706 UG_THROW("H1EnergyDistIntegrand: fine and top level inverted.");
2707
2708 if(m_fineData.domain().get() != m_coarseData.domain().get())
2709 UG_THROW("H1EnergyDistIntegrand: grid functions defined on different domains.");
2710 }
2712
2714 virtual void set_subset(int si)
2715 {
2716 if(!m_fineData.is_def_in_subset(si))
2717 UG_THROW("H1EnergyDistIntegrand: Grid function component"
2718 <<m_fineData.fct()<<" not defined on subset "<<si);
2719 if(!m_coarseData.is_def_in_subset(si))
2720 UG_THROW("H1EnergyDistIntegrand: Grid function component"
2721 <<m_coarseData.fct()<<" not defined on subset "<<si);
2723 }
2724
2726 template <int elemDim>
2727 void evaluate(number vValue[],
2728 const MathVector<worldDim> vFineGlobIP[],
2729 GridObject* pFineElem,
2730 const MathVector<worldDim> vCornerCoords[],
2731 const MathVector<elemDim> vFineLocIP[],
2733 const size_t numIP)
2734 {
2735 typedef typename TGridFunction::template dim_traits<elemDim>::grid_base_object Element;
2736
2737 const TGridFunction &fineGridFct = m_fineData.grid_function();
2738 const TGridFunction &coarseGridFct = m_coarseData.grid_function();
2739
2740 // get coarse element
2741 GridObject* pCoarseElem = pFineElem;
2743 int parentLevel = m_spMG->get_level(pCoarseElem);
2744 while(parentLevel > m_coarseTopLevel){
2745 pCoarseElem = m_spMG->get_parent(pCoarseElem);
2746 parentLevel = m_spMG->get_level(pCoarseElem);
2747 }
2748 }
2749
2750 // get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
2751 const ReferenceObjectID fineROID = pFineElem->reference_object_id();
2752 const ReferenceObjectID coarseROID = pCoarseElem->reference_object_id();
2753
2754 // get corner coordinates
2755 std::vector<MathVector<worldDim> > vCornerCoarse;
2756 CollectCornerCoordinates(vCornerCoarse, *static_cast<Element*>(pCoarseElem), *m_coarseData.domain());
2757
2758 // get reference Mapping
2760 = ReferenceMappingProvider::get<elemDim, worldDim>(coarseROID, vCornerCoarse);
2762 = ReferenceMappingProvider::get<elemDim, worldDim>(fineROID, vCornerCoords);
2763
2764 std::vector<MathVector<elemDim> > vCoarseLocIP;
2765 vCoarseLocIP.resize(numIP);
2766 for(size_t ip = 0; ip < vCoarseLocIP.size(); ++ip) VecSet(vCoarseLocIP[ip], 0.0);
2767 map.global_to_local(&vCoarseLocIP[0], vFineGlobIP, numIP);
2768
2769
2770 // determine weights
2771 std::vector<typename weight_type::data_type> elemWeights(numIP, MathMatrix<worldDim, worldDim>());
2772 UG_ASSERT(m_spWeight.valid(), "H1SemiDistIntegrand::evaluate requires valid weights!");
2773
2774 // get local solution if needed
2776 {
2777
2778 LocalIndices ind;
2779 LocalVector u;
2780 fineGridFct.indices(pFineElem, ind); // get global indices
2781 u.resize(ind); // adapt local algebra
2782 GetLocalVector(u, fineGridFct); // read local values of u
2783
2784 // compute data
2785 try{
2786 (*m_spWeight)(&elemWeights[0], vFineGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), pFineElem,
2787 vCornerCoords, vFineLocIP, numIP, &u, NULL);
2788 } UG_CATCH_THROW("H1SemiDistIntegrand: Cannot evaluate data.");
2789 }
2790 else
2791 {
2792 // compute data
2793 try{
2794 (*m_spWeight)(&elemWeights[0], vFineGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), numIP);
2795 } UG_CATCH_THROW("H1SemiDistIntegrand: Cannot evaluate data.");
2796 }
2797
2798 try{
2799
2800
2801 // get trial space
2802 const LocalShapeFunctionSet<elemDim>& rFineLSFS =
2803 LocalFiniteElementProvider::get<elemDim>(fineROID, m_fineData.id());
2804 const LocalShapeFunctionSet<elemDim>& rCoarseLSFS =
2805 LocalFiniteElementProvider::get<elemDim>(coarseROID, m_coarseData.id());
2806
2807 // get multiindices of element
2808 std::vector<DoFIndex> vFineMI, vCoarseMI;
2809 m_fineData.dof_indices(pFineElem, vFineMI);
2810 m_coarseData.dof_indices(pCoarseElem, vCoarseMI);
2811
2812 std::vector<MathVector<elemDim> > vFineLocGradient(vFineMI.size());
2813 std::vector<MathVector<elemDim> > vCoarseLocGradient(vCoarseMI.size());
2814
2815 // loop all integration points
2816 for(size_t ip = 0; ip < numIP; ++ip)
2817 {
2818 // compute shape gradients at ip
2819 rFineLSFS.grads(&vFineLocGradient[0], vFineLocIP[ip]);
2820 rCoarseLSFS.grads(&vCoarseLocGradient[0], vCoarseLocIP[ip]);
2821
2822 // compute approximated solutions at integration point
2823 number fineSolIP = 0.0;
2824 MathVector<elemDim> fineLocTmp(0.0);
2825 for(size_t sh = 0; sh < vFineMI.size(); ++sh)
2826 {
2827 const number val = DoFRef(fineGridFct, vFineMI[sh]);
2828 fineSolIP += val * rFineLSFS.shape(sh, vFineLocIP[ip]);
2829 VecScaleAppend(fineLocTmp, val, vFineLocGradient[sh]);
2830 }
2831
2832 number coarseSolIP = 0.0;
2833 MathVector<elemDim> coarseLocTmp(0.0);
2834 for(size_t sh = 0; sh < vCoarseMI.size(); ++sh)
2835 {
2836 const number val = DoFRef(coarseGridFct, vCoarseMI[sh]);
2837 coarseSolIP += val * rCoarseLSFS.shape(sh, vCoarseLocIP[ip]);
2838 VecScaleAppend(coarseLocTmp, val, vCoarseLocGradient[sh]);
2839 }
2840
2841 // compute global D*gradient
2842 MathVector<worldDim> fineGradIP;
2844 mapF.jacobian_transposed_inverse(fineJTInv, vFineLocIP[ip]);//Inverse(fineJTInv, vJT[ip]);
2845
2846#ifdef UG_DEBUG
2847 CheckGeneralizedInverse<worldDim,elemDim>(vJT[ip], fineJTInv);
2848#endif //UG_DEBUG
2849
2850
2851 MatVecMult(fineGradIP, fineJTInv, fineLocTmp);
2852 MathVector<worldDim> fineWorldLocTmp(0.0);
2853 MatVecMult(fineWorldLocTmp, elemWeights[ip], fineGradIP);
2854
2855 // compute global D*gradient
2856 MathVector<worldDim> coarseGradIP;
2858 map.jacobian_transposed_inverse(coarseJTInv, vCoarseLocIP[ip]);
2859 MatVecMult(coarseGradIP, coarseJTInv, coarseLocTmp);
2860 MathVector<worldDim> coarseWorldLocTmp(0.0);
2861 MatVecMult(coarseWorldLocTmp, elemWeights[ip], coarseGradIP);
2862
2863 // get squared difference
2864 vValue[ip] = VecDistanceSq(fineWorldLocTmp, coarseWorldLocTmp);
2865 //vValue[ip] = VecDistanceSq(fineGradIP, coarseGradIP, elemWeights[ip]);
2866 }
2867
2868 }
2869 UG_CATCH_THROW("H1EnergyDiffIntegrand::evaluate: trial space missing.");
2870 }
2871};
2872
2873
2875template <typename TGridFunction>
2876number H1EnergyDistance2(TGridFunction& spGridFct1, const char* cmp1,
2877 TGridFunction& spGridFct2, const char* cmp2,
2878 int quadOrder, const char* subsets,
2880{
2881 return GridFunctionDistance2<H1EnergyDistIntegrand<TGridFunction>, TGridFunction>
2882 (spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, subsets, weights);
2883}
2884
2886template <typename TGridFunction>
2887number H1EnergyDistance(TGridFunction& spGridFct1, const char* cmp1,
2888 TGridFunction& spGridFct2, const char* cmp2,
2889 int quadOrder, const char* subsets,
2891{ return sqrt(H1EnergyDistance2(spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, subsets, weights)); }
2892
2894template <typename TGridFunction>
2895number H1EnergyDistance2(TGridFunction& spGridFct1, const char* cmp1,
2896 TGridFunction& spGridFct2, const char* cmp2,
2897 int quadOrder, ConstSmartPtr<typename H1SemiDistIntegrand<TGridFunction>::weight_type > weights)
2898{ return H1EnergyDistance2(spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, NULL, weights); }
2899
2901template <typename TGridFunction>
2902number H1EnergyDistance(TGridFunction& spGridFct1, const char* cmp1,
2903 TGridFunction& spGridFct2, const char* cmp2,
2904 int quadOrder, ConstSmartPtr<typename H1SemiDistIntegrand<TGridFunction>::weight_type > weights)
2905{ return sqrt(H1EnergyDistance2(spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, NULL, weights)); }
2906
2907
2908
2909
2911// H1 norm integrand
2913template <typename TGridFunction>
2915 : public StdIntegrand<number, TGridFunction::dim, H1NormIntegrand<TGridFunction> >
2916{
2917 public:
2919 static const int worldDim = TGridFunction::dim;
2920
2921 private:
2923
2924 public:
2926 H1NormIntegrand(TGridFunction& gridFct, size_t cmp)
2927 : m_scalarData(gridFct, cmp) {}
2928
2930 virtual ~H1NormIntegrand() {}
2931
2933 virtual void set_subset(int si)
2934 {
2935 if(!m_scalarData.is_def_in_subset(si))
2936 UG_THROW("H1Norm: Grid function component"
2937 <<m_scalarData.fct()<<" not defined on subset "<<si);
2939 }
2940
2942 template <int elemDim>
2943 void evaluate(number vValue[],
2944 const MathVector<worldDim> vGlobIP[],
2945 GridObject* pElem,
2946 const MathVector<worldDim> vCornerCoords[],
2947 const MathVector<elemDim> vLocIP[],
2949 const size_t numIP)
2950 {
2951 // get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
2952 const ReferenceObjectID roid = pElem->reference_object_id();
2953
2955 = ReferenceMappingProvider::get<elemDim, worldDim>(roid, vCornerCoords);
2956
2957 try{
2958 // get trial space
2959 const LocalShapeFunctionSet<elemDim>& rTrialSpace =
2960 LocalFiniteElementProvider::get<elemDim>(roid, m_scalarData.id());
2961
2962 // number of dofs on element
2963 const size_t num_sh = rTrialSpace.num_sh();
2964
2965 // get multiindices of element
2966 std::vector<DoFIndex> ind; // aux. index array
2967 m_scalarData.dof_indices(pElem, ind);
2968
2969 // check multi indices
2970 if(ind.size() != num_sh)
2971 UG_THROW("H1ErrorIntegrand::evaluate: Wrong number of"
2972 " multi indices.");
2973
2974 // loop all integration points
2975 std::vector<MathVector<elemDim> > vLocGradient(num_sh);
2976 for(size_t ip = 0; ip < numIP; ++ip)
2977 {
2978
2979 // compute shape gradients at ip
2980 rTrialSpace.grads(&vLocGradient[0], vLocIP[ip]);
2981
2982 // compute approximated solution at integration point
2983 number approxSolIP = 0.0;
2984 MathVector<elemDim> locTmp; VecSet(locTmp, 0.0);
2985 for(size_t sh = 0; sh < num_sh; ++sh)
2986 {
2987 // get value at shape point (e.g. corner for P1 fct)
2988 const number valSH = DoFRef(m_scalarData.grid_function(), ind[sh]);
2989
2990 // add shape fct at ip * value at shape
2991 approxSolIP += valSH * rTrialSpace.shape(sh, vLocIP[ip]);
2992
2993 // add gradient at ip
2994 VecScaleAppend(locTmp, valSH, vLocGradient[sh]);
2995 }
2996
2997 // compute global gradient
2998 MathVector<worldDim> approxGradIP;
3000 map.jacobian_transposed_inverse(JTInv, vLocIP[ip]);//RightInverse(JTInv, vJT[ip]);
3001
3002#ifdef UG_DEBUG
3003 CheckGeneralizedInverse<worldDim,elemDim>(vJT[ip], JTInv);
3004#endif //UG_DEBUG
3005
3006 MatVecMult(approxGradIP, JTInv, locTmp);
3007
3008 // get squared of difference
3009 vValue[ip] = approxSolIP * approxSolIP;
3010 vValue[ip] += VecDot(approxGradIP, approxGradIP);
3011 }
3012
3013 }
3014 UG_CATCH_THROW("H1SemiNormFuncIntegrand::evaluate: trial space missing.");
3015 }
3016};
3017
3018
3019
3020
3021template <typename TGridFunction>
3022number H1Norm2(TGridFunction& u, const char* cmp,
3023 int quadOrder, const char* subsets=NULL)
3024{
3025// get function id of name
3026 const size_t fct = u.fct_id_by_name(cmp);
3027
3028// check that function exists
3029 if(fct >= u.num_fct())
3030 UG_THROW("H1Norm: Function space does not contain"
3031 " a function with name " << cmp << ".");
3032
3033 H1NormIntegrand<TGridFunction> spIntegrand(u, fct);
3034 return IntegrateSubsets(spIntegrand, u, subsets, quadOrder);
3035}
3036
3037
3038template <typename TGridFunction>
3039number H1Norm(TGridFunction& u, const char* cmp,
3040 int quadOrder, const char* subsets=NULL)
3041{
3042 return sqrt(H1Norm2(u, cmp, quadOrder,subsets));
3043}
3044
3045template <typename TGridFunction>
3046number H1Norm(SmartPtr<TGridFunction> spGridFct, const char* cmp,
3047 int quadOrder, const char* subsets)
3048{
3049 return H1Norm(*spGridFct, cmp, quadOrder, subsets);
3050}
3051
3052template <typename TGridFunction>
3053number H1Norm(SmartPtr<TGridFunction> spGridFct, const char* cmp, int quadOrder)
3054{
3055 return H1Norm(*spGridFct, cmp, quadOrder, NULL);
3056}
3057
3058
3059
3061template <typename TGridFunction>
3063 : public StdIntegrand<number, TGridFunction::dim, H1DistIntegrand<TGridFunction> >
3064{
3065 public:
3067 static const int worldDim = TGridFunction::dim;
3068
3069 private:
3072
3075
3078
3079 public:
3081 H1DistIntegrand(TGridFunction& fineGridFct, size_t fineCmp,
3082 TGridFunction& coarseGridFct, size_t coarseCmp)
3083 : m_fineData(fineGridFct, fineCmp),
3084 m_fineTopLevel(fineGridFct.dof_distribution()->grid_level().level()),
3085 m_coarseData(coarseGridFct, coarseCmp),
3086 m_coarseTopLevel(coarseGridFct.dof_distribution()->grid_level().level()),
3087 m_spMG(fineGridFct.domain()->grid())
3088 {
3090 UG_THROW("H1DiffIntegrand: fine and top level inverted.");
3091
3092 if(fineGridFct.domain().get() !=
3093 coarseGridFct.domain().get())
3094 UG_THROW("H1DiffIntegrand: grid functions defined on different domains.");
3095 };
3096
3098 virtual ~H1DistIntegrand() {};
3099
3101 virtual void set_subset(int si)
3102 {
3103 if(!m_fineData.is_def_in_subset(si))
3104 UG_THROW("H1DiffIntegrand: Grid function component"
3105 <<m_fineData.fct()<<" not defined on subset "<<si);
3106 if(!m_coarseData.is_def_in_subset(si))
3107 UG_THROW("H1DiffIntegrand: Grid function component"
3108 <<m_coarseData.fct()<<" not defined on subset "<<si);
3110 }
3111
3113 template <int elemDim>
3114 void evaluate(number vValue[],
3115 const MathVector<worldDim> vFineGlobIP[],
3116 GridObject* pFineElem,
3117 const MathVector<worldDim> vCornerCoords[],
3118 const MathVector<elemDim> vFineLocIP[],
3120 const size_t numIP)
3121 {
3122 typedef typename TGridFunction::template dim_traits<elemDim>::grid_base_object Element;
3123
3124 // get coarse element
3125 GridObject* pCoarseElem = pFineElem;
3127 int parentLevel = m_spMG->get_level(pCoarseElem);
3128 while(parentLevel > m_coarseTopLevel){
3129 pCoarseElem = m_spMG->get_parent(pCoarseElem);
3130 parentLevel = m_spMG->get_level(pCoarseElem);
3131 }
3132 }
3133
3134 // get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
3135 const ReferenceObjectID fineROID = pFineElem->reference_object_id();
3136 const ReferenceObjectID coarseROID = pCoarseElem->reference_object_id();
3137
3138 // get corner coordinates
3139 std::vector<MathVector<worldDim> > vCornerCoarse;
3140 CollectCornerCoordinates(vCornerCoarse, *static_cast<Element*>(pCoarseElem), *m_coarseData.domain());
3141
3142 // get Reference Mapping
3144 = ReferenceMappingProvider::get<elemDim, worldDim>(coarseROID, vCornerCoarse);
3146 = ReferenceMappingProvider::get<elemDim, worldDim>(fineROID, vCornerCoords);
3147
3148 std::vector<MathVector<elemDim> > vCoarseLocIP;
3149 vCoarseLocIP.resize(numIP);
3150 for(size_t ip = 0; ip < vCoarseLocIP.size(); ++ip) VecSet(vCoarseLocIP[ip], 0.0);
3151 map.global_to_local(&vCoarseLocIP[0], vFineGlobIP, numIP);
3152
3153 try{
3154 // get trial space
3155 const LocalShapeFunctionSet<elemDim>& rFineLSFS =
3156 LocalFiniteElementProvider::get<elemDim>(fineROID, m_fineData.id());
3157 const LocalShapeFunctionSet<elemDim>& rCoarseLSFS =
3158 LocalFiniteElementProvider::get<elemDim>(coarseROID, m_coarseData.id());
3159
3160 // get multiindices of element
3161 std::vector<DoFIndex> vFineMI, vCoarseMI;
3162 m_fineData.dof_indices(pFineElem, vFineMI);
3163 m_coarseData.dof_indices(pCoarseElem, vCoarseMI);
3164
3165 std::vector<MathVector<elemDim> > vFineLocGradient(vFineMI.size());
3166 std::vector<MathVector<elemDim> > vCoarseLocGradient(vCoarseMI.size());
3167
3168 // loop all integration points
3169 for(size_t ip = 0; ip < numIP; ++ip)
3170 {
3171 // compute shape gradients at ip
3172 rFineLSFS.grads(&vFineLocGradient[0], vFineLocIP[ip]);
3173 rCoarseLSFS.grads(&vCoarseLocGradient[0], vCoarseLocIP[ip]);
3174
3175 // compute approximated solution at integration point
3176 number fineSolIP = 0.0;
3177 MathVector<elemDim> fineLocTmp; VecSet(fineLocTmp, 0.0);
3178 for(size_t sh = 0; sh < vFineMI.size(); ++sh)
3179 {
3180 const number val = DoFRef(m_fineData.grid_function(), vFineMI[sh]);
3181 fineSolIP += val * rFineLSFS.shape(sh, vFineLocIP[ip]);
3182 VecScaleAppend(fineLocTmp, val, vFineLocGradient[sh]);
3183 }
3184 number coarseSolIP = 0.0;
3185 MathVector<elemDim> coarseLocTmp; VecSet(coarseLocTmp, 0.0);
3186 for(size_t sh = 0; sh < vCoarseMI.size(); ++sh)
3187 {
3188 const number val = DoFRef(m_coarseData.grid_function(), vCoarseMI[sh]);
3189 coarseSolIP += val * rCoarseLSFS.shape(sh, vCoarseLocIP[ip]);
3190 VecScaleAppend(coarseLocTmp, val, vCoarseLocGradient[sh]);
3191 }
3192
3193 // compute global gradient
3194 MathVector<worldDim> fineGradIP;
3196 mapF.jacobian_transposed_inverse(fineJTInv, vFineLocIP[ip]);//RightInverse(fineJTInv, vJT[ip]);
3197
3198#ifdef UG_DEBUG
3199 CheckGeneralizedInverse<worldDim,elemDim>(vJT[ip], fineJTInv);
3200#endif //UG_DEBUG
3201
3202
3203 MatVecMult(fineGradIP, fineJTInv, fineLocTmp);
3204
3205 // compute global gradient
3206 MathVector<worldDim> coarseGradIP;
3208 map.jacobian_transposed_inverse(coarseJTInv, vCoarseLocIP[ip]);
3209 MatVecMult(coarseGradIP, coarseJTInv, coarseLocTmp);
3210
3211 // get squared of difference
3212 vValue[ip] = (coarseSolIP - fineSolIP);
3213 vValue[ip] *= vValue[ip];
3214 vValue[ip] += VecDistanceSq(coarseGradIP, fineGradIP);
3215 }
3216
3217 }
3218 UG_CATCH_THROW("H1DiffIntegrand::evaluate: trial space missing.");
3219 }
3220};
3221
3222
3223
3224template <typename TGridFunction>
3225number H1Distance2(TGridFunction& spGridFct1, const char* cmp1,
3226 TGridFunction& spGridFct2, const char* cmp2,
3227 int quadOrder, const char* subsets=NULL)
3228{
3229 return GridFunctionDistance2<H1DistIntegrand<TGridFunction>, TGridFunction>
3230 (spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, subsets);
3231}
3232
3233
3234template <typename TGridFunction>
3235number H1Distance(TGridFunction& spGridFct1, const char* cmp1,
3236 TGridFunction& spGridFct2, const char* cmp2,
3237 int quadOrder, const char* subsets=NULL)
3238{
3239 return sqrt(H1Distance2(spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, subsets));
3240}
3242template <typename TGridFunction>
3243number H1Error(SmartPtr<TGridFunction> spGridFct1, const char* cmp1,
3244 SmartPtr<TGridFunction> spGridFct2, const char* cmp2,
3245 int quadOrder, const char* subsets)
3246{
3247 return H1Distance(*spGridFct1, cmp1, *spGridFct2, cmp2, quadOrder, subsets);
3248}
3249
3251template <typename TGridFunction>
3252number H1Error(SmartPtr<TGridFunction> spGridFct1, const char* cmp1,
3253 SmartPtr<TGridFunction> spGridFct2, const char* cmp2,
3254 int quadOrder)
3255{
3256 return H1Distance(*spGridFct1, cmp1, *spGridFct2, cmp2, quadOrder, NULL);
3257}
3258
3259
3261// Standard Integrand
3263
3264template <typename TGridFunction>
3266 : public StdIntegrand<number, TGridFunction::dim, StdFuncIntegrand<TGridFunction> >
3267{
3268 public:
3269 // world dimension of grid function
3270 static const int worldDim = TGridFunction::dim;
3271
3272 private:
3273 // grid function
3274 TGridFunction* m_pGridFct;
3275
3276 // component of function
3277 const size_t m_fct;
3278
3279 public:
3281 StdFuncIntegrand(TGridFunction* pGridFct, size_t cmp)
3282 : m_pGridFct(pGridFct), m_fct(cmp)
3283 {};
3284
3286
3288 virtual void set_subset(int si)
3289 {
3290 if(!m_pGridFct->is_def_in_subset(m_fct, si))
3291 UG_THROW("L2ErrorIntegrand: Grid function component"
3292 <<m_fct<<" not defined on subset "<<si);
3294 }
3295
3297 template <int elemDim>
3298 void evaluate(number vValue[],
3299 const MathVector<worldDim> vGlobIP[],
3300 GridObject* pElem,
3301 const MathVector<worldDim> vCornerCoords[],
3302 const MathVector<elemDim> vLocIP[],
3304 const size_t numIP)
3305 {
3306 // get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
3308
3309 const LFEID m_id = m_pGridFct->local_finite_element_id(m_fct);
3310
3311 try{
3312 // get trial space
3313 const LocalShapeFunctionSet<elemDim>& rTrialSpace =
3314 LocalFiniteElementProvider::get<elemDim>(roid, m_id);
3315
3316 // number of dofs on element
3317 const size_t num_sh = rTrialSpace.num_sh();
3318
3319 // get multiindices of element
3320
3321 std::vector<DoFIndex> ind; // aux. index array
3322 m_pGridFct->dof_indices(pElem, m_fct, ind);
3323
3324 // check multi indices
3325 UG_COND_THROW(ind.size() != num_sh,
3326 "StdFuncIntegrand::evaluate: Wrong number of multi indices.");
3327
3328 // loop all integration points
3329 for(size_t ip = 0; ip < numIP; ++ip)
3330 {
3331
3332 // compute approximated solution at integration point
3333 number approxSolIP = 0.0;
3334 for(size_t sh = 0; sh < num_sh; ++sh)
3335 {
3336 // get value at shape point (e.g. corner for P1 fct)
3337 // and add shape fct at ip * value at shape
3338 const number valSH = DoFRef((*m_pGridFct), ind[sh]);
3339 approxSolIP += valSH * rTrialSpace.shape(sh, vLocIP[ip]);
3340 }
3341
3342 // get function value at ip
3343 vValue[ip] = approxSolIP;
3344
3345 }
3346
3347 }
3348 UG_CATCH_THROW("StdFuncIntegrand::evaluate: trial space missing.");
3349 }
3350};
3351
3352
3353template <typename TGridFunction>
3354number StdFuncIntegralOnVertex(TGridFunction& gridFct,
3355 size_t fct,
3356 int si)
3357{
3358// integrate elements of subset
3359 typedef typename TGridFunction::template dim_traits<0>::grid_base_object grid_base_object;
3360 typedef typename TGridFunction::template dim_traits<0>::const_iterator const_iterator;
3361
3362 // reset the result
3363 number integral = 0;
3364
3365// note: this iterator is for the base elements, e.g. Face and not
3366// for the special type, e.g. Triangle, Quadrilateral
3367 const_iterator iter = gridFct.template begin<grid_base_object>(si);
3368 const_iterator iterEnd = gridFct.template end<grid_base_object>(si);
3369
3370// iterate over all elements
3371 for(; iter != iterEnd; ++iter)
3372 {
3373 // get element
3374 grid_base_object* pElem = *iter;
3375
3376 std::vector<DoFIndex> ind; // aux. index array
3377 gridFct.dof_indices(pElem, fct, ind);
3378
3379 // compute approximated solution at integration point
3380 number value = 0.0;
3381 for(size_t sh = 0; sh < ind.size(); ++sh)
3382 {
3383 value += DoFRef(gridFct, ind[sh]);
3384 }
3385
3386 // add to global sum
3387 integral += value;
3388
3389 } // end elem
3390
3391// return the summed integral contributions of all elements
3392 return integral;
3393}
3394
3395template <typename TGridFunction>
3397{ return StdFuncIntegralOnVertex(*spGridFct, fct, si); }
3398
3399
3400template <typename TGridFunction>
3401number Integral(TGridFunction& gridFct, const char* cmp,
3402 const char* subsets, int quadOrder)
3403{
3404// get function id of name
3405 const size_t fct = gridFct.fct_id_by_name(cmp);
3406
3407// check that function exists
3408 UG_COND_THROW(fct >= gridFct.num_fct(), "L2Norm: Function space does not contain"
3409 " a function with name " << cmp << ".");
3410
3411// read subsets
3412 SubsetGroup ssGrp(gridFct.domain()->subset_handler());
3413 if(subsets != NULL)
3414 {
3415 ssGrp.add(TokenizeString(subsets));
3416 if(!SameDimensionsInAllSubsets(ssGrp))
3417 UG_THROW("IntegrateSubsets: Subsets '"<<subsets<<"' do not have same dimension."
3418 "Can not integrate on subsets of different dimensions.");
3419 }
3420 else
3421 {
3422 // add all subsets and remove lower dim subsets afterwards
3423 ssGrp.add_all();
3424 RemoveLowerDimSubsets(ssGrp);
3425 }
3426
3427 // \TODO: This should be generalite in IntegrateSubset instead of doing it directly here
3428 bool bOnlyVertex = true;
3429 for(size_t s = 0; s < ssGrp.size(); ++s)
3430 if(ssGrp.dim(s) != 0) bOnlyVertex = false;
3431
3432 if(bOnlyVertex)
3433 {
3434 number value = 0;
3435 for(size_t s = 0; s < ssGrp.size(); ++s)
3436 value += StdFuncIntegralOnVertex(gridFct, fct, ssGrp[s]);
3437
3438#ifdef UG_PARALLEL
3439 // sum over processes
3440 if(pcl::NumProcs() > 1)
3441 {
3443 number local = value;
3444 com.allreduce(&local, &value, 1, PCL_DT_DOUBLE, PCL_RO_SUM);
3445 }
3446#endif
3447 return value;
3448 }
3449
3450 StdFuncIntegrand<TGridFunction> integrand(&gridFct, fct);
3451 return IntegrateSubsets(integrand, gridFct, subsets, quadOrder);
3452}
3453
3454template <typename TGridFunction>
3455number Integral(SmartPtr<TGridFunction> spGridFct, const char* cmp,
3456 const char* subsets, int quadOrder)
3457{ return Integral(*spGridFct, cmp, subsets, quadOrder); }
3458
3459
3460template <typename TGridFunction>
3461number Integral(SmartPtr<TGridFunction> spGridFct, const char* cmp,
3462 const char* subsets)
3463{
3464 return Integral(spGridFct, cmp, subsets, 1);
3465}
3466template <typename TGridFunction>
3467number Integral(SmartPtr<TGridFunction> spGridFct, const char* cmp)
3468{
3469 return Integral(spGridFct, cmp, NULL, 1);
3470}
3471
3472
3475// Generic Boundary Integration Routine
3478
3479template <int WorldDim, int dim, typename TConstIterator>
3481 TConstIterator iterEnd,
3483 const ISubsetHandler* ish,
3484 IIntegrand<MathVector<WorldDim>, WorldDim>& integrand,
3485 const SubsetGroup& bndSSGrp)
3486{
3487// reset the result
3488 number integral = 0;
3489
3490// note: this iterator is for the base elements, e.g. Face and not
3491// for the special type, e.g. Triangle, Quadrilateral
3492 TConstIterator iter = iterBegin;
3493
3494// this is the base element type (e.g. Face). This is the type when the
3495// iterators above are dereferenciated.
3496 typedef typename domain_traits<dim>::grid_base_object grid_base_object;
3497
3498// create a FV1 Geometry
3500
3501// specify, which subsets are boundary
3502 for(size_t s = 0; s < bndSSGrp.size(); ++s)
3503 {
3504 // get subset index
3505 const int bndSubset = bndSSGrp[s];
3506
3507 // request this subset index as boundary subset. This will force the
3508 // creation of boundary subsets when calling geo.update
3509 geo.add_boundary_subset(bndSubset);
3510 }
3511
3512// vector of corner coordinates of element corners (to be filled for each elem)
3513 std::vector<MathVector<WorldDim> > vCorner;
3514
3515// iterate over all elements
3516 for(; iter != iterEnd; ++iter)
3517 {
3518 // get element
3519 grid_base_object* pElem = *iter;
3520
3521 // get all corner coordinates
3522 CollectCornerCoordinates(vCorner, *pElem, aaPos, true);
3523
3524 // compute bf and grads at bip for element
3525 try{
3526 geo.update(pElem, &vCorner[0], ish);
3527 }
3528 UG_CATCH_THROW("IntegralNormalComponentOnManifold: "
3529 "Cannot update Finite Volume Geometry.");
3530
3531 // specify, which subsets are boundary
3532 for(size_t s = 0; s < bndSSGrp.size(); ++s)
3533 {
3534 // get subset index
3535 const int bndSubset = bndSSGrp[s];
3536
3537 // get all bf of this subset
3538 typedef typename DimFV1Geometry<dim>::BF BF;
3539 const std::vector<BF>& vBF = geo.bf(bndSubset);
3540
3541 // loop boundary faces
3542 for(size_t b = 0; b < vBF.size(); ++b)
3543 {
3544 // get bf
3545 const BF& bf = vBF[b];
3546
3547 // value
3549
3550 // jacobian
3552 Inverse(JT, bf.JTInv());
3553
3554 // compute integrand values at integration points
3555 try
3556 {
3557 integrand.values(&value, &(bf.global_ip()),
3558 pElem, &vCorner[0], &(bf.local_ip()),
3559 &(JT),
3560 1);
3561 }
3562 UG_CATCH_THROW("IntegralNormalComponentOnManifold: Unable to compute values of "
3563 "integrand at integration point.");
3564
3565 // sum up contribution (normal includes area)
3566 integral += VecDot(value, bf.normal());
3567
3568 } // end bf
3569 } // end bnd subsets
3570 } // end elem
3571
3572// return the summed integral contributions of all elements
3573 return integral;
3574}
3575
3576
3577template <int WorldDim, int dim, typename TConstIterator>
3579 TConstIterator iterBegin,
3580 TConstIterator iterEnd,
3582 const ISubsetHandler* ish,
3583 IIntegrand<MathVector<WorldDim>, WorldDim>& integrand,
3584 const SubsetGroup& bndSSGrp,
3585 int quadOrder,
3586 Grid& grid)
3587{
3588// reset the result
3589 number integral = 0;
3590
3591// note: this iterator is for the base elements, e.g. Face and not
3592// for the special type, e.g. Triangle, Quadrilateral
3593 TConstIterator iter = iterBegin;
3594
3595// this is the base element type (e.g. Face). This is the type when the
3596// iterators above are dereferenciated.
3597 typedef typename domain_traits<dim>::element_type Element;
3598 typedef typename domain_traits<dim>::side_type Side;
3599
3600// vector of corner coordinates of element corners (to be filled for each elem)
3601 std::vector<MathVector<WorldDim> > vCorner;
3602 std::vector<int> vSubsetIndex;
3603
3604// iterate over all elements
3605 for(; iter != iterEnd; ++iter)
3606 {
3607 // get element
3608 Element* pElem = *iter;
3609
3610 // get all corner coordinates
3611 CollectCornerCoordinates(vCorner, *pElem, aaPos, true);
3612
3613 // get reference object id
3614 const ReferenceObjectID elemRoid = pElem->reference_object_id();
3615
3616 // get sides
3618 grid.associated_elements_sorted(vSide, pElem);
3619 vSubsetIndex.resize(vSide.size());
3620 for(size_t i = 0; i < vSide.size(); ++i)
3621 vSubsetIndex[i] = ish->get_subset_index(vSide[i]);
3622
3624 = ReferenceMappingProvider::get<dim, WorldDim>(elemRoid, vCorner);
3625
3626 const DimReferenceElement<dim>& rRefElem
3627 = ReferenceElementProvider::get<dim>(elemRoid);
3628
3629 // loop sub elements
3630 for(size_t side = 0; side < vSide.size(); ++side)
3631 {
3632 // check if side used
3633 if(!bndSSGrp.contains(vSubsetIndex[side])) continue;
3634
3635 // get side
3636 Side* pSide = vSide[side];
3637
3638 std::vector<MathVector<WorldDim> > vSideCorner(rRefElem.num(dim-1, side, 0));
3639 std::vector<MathVector<dim> > vLocalSideCorner(rRefElem.num(dim-1, side, 0));
3640 for(size_t co = 0; co < vSideCorner.size(); ++co){
3641 vSideCorner[co] = vCorner[rRefElem.id(dim-1, side, 0, co)];
3642 vLocalSideCorner[co] = rRefElem.corner(rRefElem.id(dim-1, side, 0, co));
3643 }
3644
3645 // side quad rule
3646 const ReferenceObjectID sideRoid = pSide->reference_object_id();
3647 const QuadratureRule<dim-1>& rSideQuadRule
3648 = QuadratureRuleProvider<dim-1>::get(sideRoid, quadOrder);
3649
3650 // normal
3651 MathVector<WorldDim> Normal;
3652 ElementNormal<WorldDim>(sideRoid, Normal, &vSideCorner[0]);
3653
3654 // quadrature points
3655 const number* vWeight = rSideQuadRule.weights();
3656 const size_t nip = rSideQuadRule.size();
3657 std::vector<MathVector<dim> > vLocalIP(nip);
3658 std::vector<MathVector<dim> > vGlobalIP(nip);
3659
3660 DimReferenceMapping<dim-1, dim>& map
3661 = ReferenceMappingProvider::get<dim-1, dim>(sideRoid, vLocalSideCorner);
3662
3663 for(size_t ip = 0; ip < nip; ++ip)
3664 map.local_to_global(vLocalIP[ip], rSideQuadRule.point(ip));
3665
3666 for(size_t ip = 0; ip < nip; ++ip)
3667 rMapping.local_to_global(vGlobalIP[ip], vLocalIP[ip]);
3668
3669 // compute transformation matrices
3670 std::vector<MathMatrix<dim-1, WorldDim> > vJT(nip);
3671 map.jacobian_transposed(&(vJT[0]), rSideQuadRule.points(), nip);
3672
3673 std::vector<MathMatrix<dim, WorldDim> > vElemJT(nip);
3674 rMapping.jacobian_transposed(&(vElemJT[0]), &vLocalIP[0], nip);
3675
3676 std::vector<MathVector<WorldDim> > vValue(nip);
3677
3678 // compute integrand values at integration points
3679 try
3680 {
3681 integrand.values(&vValue[0], &vGlobalIP[0],
3682 pElem, &vCorner[0], &vLocalIP[0],
3683 &(vElemJT[0]),
3684 nip);
3685 }
3686 UG_CATCH_THROW("IntegralNormalComponentOnManifold: Unable to compute values of "
3687 "integrand at integration point.");
3688
3689 // loop integration points
3690 for(size_t ip = 0; ip < nip; ++ip)
3691 {
3692 // get quadrature weight
3693 const number weightIP = vWeight[ip];
3694
3695 // get determinate of mapping
3696 const number det = SqrtGramDeterminant(vJT[ip]);
3697
3698 // add contribution of integration point
3699 integral += VecDot(vValue[ip], Normal) * weightIP * det;
3700 }
3701 } // end bf
3702 } // end elem
3703
3704// return the summed integral contributions of all elements
3705 return integral;
3706}
3707
3708template <typename TGridFunction, int dim>
3710 SmartPtr<TGridFunction> spGridFct,
3711 int si, const SubsetGroup& bndSSGrp, int quadOrder)
3712{
3713// integrate elements of subset
3714 typedef typename TGridFunction::template dim_traits<dim>::grid_base_object grid_base_object;
3715 typedef typename TGridFunction::template dim_traits<dim>::const_iterator const_iterator;
3716 static const int WorldDim = TGridFunction::dim;
3717
3718 spIntegrand->set_subset(si);
3719
3720 if(quadOrder == 1)
3721 return IntegralNormalComponentOnManifoldUsingFV1Geom<WorldDim,dim,const_iterator>
3722 (spGridFct->template begin<grid_base_object>(si),
3723 spGridFct->template end<grid_base_object>(si),
3724 spGridFct->domain()->position_accessor(),
3725 spGridFct->domain()->subset_handler().get(),
3726 *spIntegrand, bndSSGrp);
3727 else{
3728 UG_LOG(" #### IntegralNormalComponentOnManifoldSubset ####:\n")
3729 return IntegralNormalComponentOnManifoldGeneral<WorldDim,dim,const_iterator>
3730 (spGridFct->template begin<grid_base_object>(si),
3731 spGridFct->template end<grid_base_object>(si),
3732 spGridFct->domain()->position_accessor(),
3733 spGridFct->domain()->subset_handler().get(),
3734 *spIntegrand, bndSSGrp, quadOrder, *spGridFct->domain()->grid());
3735 }
3736}
3737
3738template <typename TGridFunction>
3740 SmartPtr<IIntegrand<MathVector<TGridFunction::dim>, TGridFunction::dim> > spIntegrand,
3741 SmartPtr<TGridFunction> spGridFct,
3742 const char* BndSubsets, const char* InnerSubsets,
3743 int quadOrder)
3744{
3745// world dimensions
3746 static const int dim = TGridFunction::dim;
3747
3748// read subsets
3749 SubsetGroup innerSSGrp(spGridFct->domain()->subset_handler());
3750 if(InnerSubsets != NULL)
3751 {
3752 innerSSGrp.add(TokenizeString(InnerSubsets));
3753 if(!SameDimensionsInAllSubsets(innerSSGrp))
3754 UG_THROW("IntegralNormalComponentOnManifold: Subsets '"<<InnerSubsets<<"' do not have same dimension."
3755 "Can not integrate on subsets of different dimensions.");
3756 }
3757 else
3758 {
3759 // add all subsets and remove lower dim subsets afterwards
3760 innerSSGrp.add_all();
3761 RemoveLowerDimSubsets(innerSSGrp);
3762 }
3763
3764// read subsets
3765 SubsetGroup bndSSGrp(spGridFct->domain()->subset_handler());
3766 if(BndSubsets != NULL)
3767 bndSSGrp.add(TokenizeString(BndSubsets));
3768 else
3769 UG_THROW("IntegralNormalComponentOnManifold: No boundary subsets passed.");
3770
3771// reset value
3772 number value = 0;
3773
3774// loop subsets
3775 for(size_t i = 0; i < innerSSGrp.size(); ++i)
3776 {
3777 // get subset index
3778 const int si = innerSSGrp[i];
3779
3780 // check dimension
3781 if(innerSSGrp.dim(i) != dim && innerSSGrp.dim(i) != DIM_SUBSET_EMPTY_GRID)
3782 UG_THROW("IntegralNormalComponentOnManifold: Dimension of inner subset is "<<
3783 innerSSGrp.dim(i)<<", but only World Dimension "<<dim<<
3784 " subsets can be used for inner subsets.");
3785
3786 // integrate elements of subset
3787 switch(innerSSGrp.dim(i))
3788 {
3789 case DIM_SUBSET_EMPTY_GRID: break;
3790 case dim: value += IntegralNormalComponentOnManifoldSubset<TGridFunction, dim>(spIntegrand, spGridFct, si, bndSSGrp, quadOrder); break;
3791 default: UG_THROW("IntegralNormalComponentOnManifold: Dimension "<<innerSSGrp.dim(i)<<" not supported. "
3792 " World dimension is "<<dim<<".");
3793 }
3794 }
3795
3796#ifdef UG_PARALLEL
3797 // sum over processes
3798 if(pcl::NumProcs() > 1)
3799 {
3801 number local = value;
3802 com.allreduce(&local, &value, 1, PCL_DT_DOUBLE, PCL_RO_SUM);
3803 }
3804#endif
3805
3806// return the result
3807 return value;
3808}
3809
3810template <typename TGridFunction>
3812 SmartPtr<UserData<MathVector<TGridFunction::dim>, TGridFunction::dim> > spData,
3813 SmartPtr<TGridFunction> spGridFct,
3814 const char* BndSubset, const char* InnerSubset,
3815 number time,
3816 int quadOrder)
3817{
3818 SmartPtr<IIntegrand<MathVector<TGridFunction::dim>, TGridFunction::dim> > spIntegrand
3819 = make_sp(new UserDataIntegrand<MathVector<TGridFunction::dim>, TGridFunction>(spData, &(*spGridFct), time));
3820
3821 return IntegralNormalComponentOnManifoldSubsets(spIntegrand, spGridFct, BndSubset, InnerSubset, quadOrder);
3822}
3823
3824template <typename TGridFunction>
3826 SmartPtr<UserData<MathVector<TGridFunction::dim>, TGridFunction::dim> > spData,
3827 SmartPtr<TGridFunction> spGridFct,
3828 const char* BndSubset, const char* InnerSubset,
3829 number time)
3830{return IntegralNormalComponentOnManifold(spData, spGridFct, BndSubset, InnerSubset, time, 1);}
3831
3832template <typename TGridFunction>
3834 SmartPtr<UserData<MathVector<TGridFunction::dim>, TGridFunction::dim> > spData,
3835 SmartPtr<TGridFunction> spGridFct,
3836 const char* BndSubset,
3837 number time)
3838{return IntegralNormalComponentOnManifold(spData, spGridFct, BndSubset, NULL, time, 1);}
3839
3840template <typename TGridFunction>
3842 SmartPtr<UserData<MathVector<TGridFunction::dim>, TGridFunction::dim> > spData,
3843 SmartPtr<TGridFunction> spGridFct,
3844 const char* BndSubset, const char* InnerSubset)
3845{return IntegralNormalComponentOnManifold(spData, spGridFct, BndSubset, InnerSubset, 0.0, 1);}
3846
3847template <typename TGridFunction>
3849 SmartPtr<UserData<MathVector<TGridFunction::dim>, TGridFunction::dim> > spData,
3850 SmartPtr<TGridFunction> spGridFct,
3851 const char* BndSubset)
3852{return IntegralNormalComponentOnManifold(spData, spGridFct, BndSubset, NULL, 0.0, 1);}
3853
3855// lua data
3857
3858#ifdef UG_FOR_LUA
3859template <typename TGridFunction>
3861 const char* luaFct, SmartPtr<TGridFunction> spGridFct,
3862 const char* BndSubset, const char* InnerSubset,
3863 number time, int quadOrder)
3864{
3865 static const int dim = TGridFunction::dim;
3867 LuaUserDataFactory<MathVector<dim>, dim>::create(luaFct);
3868 return IntegralNormalComponentOnManifold(sp, spGridFct, BndSubset, InnerSubset, time, quadOrder);
3869}
3870
3871template <typename TGridFunction>
3873 const char* luaFct, SmartPtr<TGridFunction> spGridFct,
3874 const char* BndSubset, const char* InnerSubset,
3875 number time)
3876{return IntegralNormalComponentOnManifold(luaFct, spGridFct, BndSubset, InnerSubset, time, 1);}
3877
3878template <typename TGridFunction>
3880 const char* luaFct, SmartPtr<TGridFunction> spGridFct,
3881 const char* BndSubset,
3882 number time)
3883{return IntegralNormalComponentOnManifold(luaFct, spGridFct, BndSubset, NULL, time, 1);}
3884
3885template <typename TGridFunction>
3887 const char* luaFct, SmartPtr<TGridFunction> spGridFct,
3888 const char* BndSubset, const char* InnerSubset)
3889{return IntegralNormalComponentOnManifold(luaFct, spGridFct, BndSubset, InnerSubset, 0.0, 1);}
3890
3891template <typename TGridFunction>
3893 const char* luaFct, SmartPtr<TGridFunction> spGridFct,
3894 const char* BndSubset)
3895{return IntegralNormalComponentOnManifold(luaFct, spGridFct, BndSubset, NULL, 0.0, 1);}
3896#endif
3897
3899// Boundary Integral
3902
3913template <typename TGridFunction>
3914number IntegrateNormalComponentOnManifold(TGridFunction& u, const char* cmp,
3915 const char* BndSubset)
3916{
3917// get function id of name
3918 const size_t fct = u.fct_id_by_name(cmp);
3919
3920// check that function exists
3921 if(fct >= u.num_fct())
3922 UG_THROW("IntegrateNormalComponentOnManifold: Function space does not contain"
3923 " a function with name " << cmp << ".");
3924
3925 if(u.local_finite_element_id(fct) != LFEID(LFEID::LAGRANGE, TGridFunction::dim, 1))
3926 UG_THROW("IntegrateNormalComponentOnManifold:"
3927 "Only implemented for Lagrange P1 functions.");
3928
3929// read bnd subsets
3930 SubsetGroup bndSSGrp(u.domain()->subset_handler());
3931 bndSSGrp.add(TokenizeString(BndSubset));
3932
3933// reset value
3934 number value = 0;
3935
3936// loop subsets
3937 for(size_t i = 0; i < bndSSGrp.size(); ++i)
3938 {
3939 // get subset index
3940 const int si = bndSSGrp[i];
3941
3942 // skip if function is not defined in subset
3943 if(!u.is_def_in_subset(fct, si)) continue;
3944
3945 // create integration kernel
3946 static const int dim = TGridFunction::dim;
3947
3948 // integrate elements of subset
3949 typedef typename domain_traits<dim>::grid_base_object grid_base_object;
3950
3951 // get iterators for all elems on subset
3952 typedef typename TGridFunction::template dim_traits<dim>::const_iterator const_iterator;
3953 const_iterator iter = u.template begin<grid_base_object>();
3954 const_iterator iterEnd = u.template end<grid_base_object>();
3955
3956 // create a FV1 Geometry
3958
3959 // specify, which subsets are boundary
3960 for(size_t s = 0; s < bndSSGrp.size(); ++s)
3961 {
3962 // get subset index
3963 const int bndSubset = bndSSGrp[s];
3964
3965 // request this subset index as boundary subset. This will force the
3966 // creation of boundary subsets when calling geo.update
3967 geo.add_boundary_subset(bndSubset);
3968 }
3969
3970 // vector of corner coordinates of element corners (to be filled for each elem)
3971 std::vector<MathVector<dim> > vCorner;
3972
3973 // loop elements of subset
3974 for( ; iter != iterEnd; ++iter)
3975 {
3976 // get element
3977 grid_base_object* elem = *iter;
3978
3979 // get all corner coordinates
3980 CollectCornerCoordinates(vCorner, *elem, u.domain()->position_accessor(), true);
3981
3982 // compute bf and grads at bip for element
3983 try{
3984 geo.update(elem, &vCorner[0], u.domain()->subset_handler().get());
3985 }
3986 UG_CATCH_THROW("IntegrateNormalComponenOnManifold: "
3987 "Cannot update Finite Volume Geometry.");
3988
3989 // get fct multi-indices of element
3990 std::vector<DoFIndex> ind;
3991 u.dof_indices(elem, fct, ind);
3992
3993 // specify, which subsets are boundary
3994 for(size_t s = 0; s < bndSSGrp.size(); ++s)
3995 {
3996 // get subset index
3997 const int bndSubset = bndSSGrp[s];
3998
3999 // get all bf of this subset
4000 typedef typename DimFV1Geometry<dim>::BF BF;
4001 const std::vector<BF>& vBF = geo.bf(bndSubset);
4002
4003 // loop boundary faces
4004 for(size_t b = 0; b < vBF.size(); ++b)
4005 {
4006 // get bf
4007 const BF& bf = vBF[b];
4008
4009 // get normal on bf
4010 const MathVector<dim>& normal = bf.normal();
4011
4012 // check multi indices
4013 UG_ASSERT(ind.size() == bf.num_sh(),
4014 "IntegrateNormalComponentOnManifold::values: Wrong number of"
4015 " multi indices, ind: "<<ind.size() << ", bf.num_sh: "
4016 << bf.num_sh());
4017
4018 MathVector<dim> val; VecSet(val, 0.0);
4019 for(size_t sh = 0; sh < bf.num_sh(); ++sh)
4020 {
4021 const number fctVal = DoFRef(u, ind[sh]);
4022 const MathVector<dim>& ip = bf.global_ip();
4023 VecScaleAdd(val, 1.0, val, fctVal, ip);
4024 }
4025
4026 // sum up contributions
4027 value -= VecDot(val, normal);
4028 }
4029 }
4030 }
4031 }
4032
4033#ifdef UG_PARALLEL
4034 // sum over processes
4035 if(pcl::NumProcs() > 1)
4036 {
4038 number local = value;
4039 com.allreduce(&local, &value, 1, PCL_DT_DOUBLE, PCL_RO_SUM);
4040 }
4041#endif
4042
4043// return the result
4044 return value;
4045}
4046
4048
4062template <typename TGridFunction>
4063number IntegrateNormalGradientOnManifold(TGridFunction& u, const char* cmp,
4064 const char* BndSubset, const char* InnerSubset = NULL)
4065{
4066// get function id of name
4067 const size_t fct = u.fct_id_by_name(cmp);
4068
4069// check that function exists
4070 if(fct >= u.num_fct())
4071 UG_THROW("IntegrateNormalGradientOnManifold: Function space does not contain"
4072 " a function with name " << cmp << ".");
4073
4074 if(u.local_finite_element_id(fct) != LFEID(LFEID::LAGRANGE, TGridFunction::dim, 1))
4075 UG_THROW("IntegrateNormalGradientOnManifold:"
4076 "Only implemented for Lagrange P1 functions.");
4077
4078// read subsets
4079 SubsetGroup innerSSGrp(u.domain()->subset_handler());
4080 if(InnerSubset != NULL)
4081 innerSSGrp.add(TokenizeString(InnerSubset));
4082 else // add all if no subset specified
4083 innerSSGrp.add_all();
4084
4085// read bnd subsets
4086 SubsetGroup bndSSGrp(u.domain()->subset_handler());
4087 if(InnerSubset != NULL){
4088 bndSSGrp.add(TokenizeString(BndSubset));
4089 }
4090 else{
4091 UG_THROW("IntegrateNormalGradientOnManifold: No boundary subsets specified. Aborting.");
4092 }
4093
4094// reset value
4095 number value = 0;
4096
4097// loop subsets
4098 for(size_t i = 0; i < innerSSGrp.size(); ++i)
4099 {
4100 // get subset index
4101 const int si = innerSSGrp[i];
4102
4103 // skip if function is not defined in subset
4104 if(!u.is_def_in_subset(fct, si)) continue;
4105
4106
4107 if (innerSSGrp.dim(i) != TGridFunction::dim)
4108 UG_THROW("IntegrateNormalGradientOnManifold: Element dimension does not match world dimension!");
4109
4110 // create integration kernel
4111 static const int dim = TGridFunction::dim;
4112
4113 // integrate elements of subset
4114 typedef typename domain_traits<dim>::grid_base_object grid_base_object;
4115
4116 // get iterators for all elems on subset
4117 typedef typename TGridFunction::template dim_traits<dim>::const_iterator const_iterator;
4118 const_iterator iter = u.template begin<grid_base_object>();
4119 const_iterator iterEnd = u.template end<grid_base_object>();
4120
4121 // create a FV1 Geometry
4123
4124 // specify, which subsets are boundary
4125 for(size_t s = 0; s < bndSSGrp.size(); ++s)
4126 {
4127 // get subset index
4128 const int bndSubset = bndSSGrp[s];
4129
4130 // request this subset index as boundary subset. This will force the
4131 // creation of boundary subsets when calling geo.update
4132 geo.add_boundary_subset(bndSubset);
4133 }
4134
4135 // vector of corner coordinates of element corners (to be filled for each elem)
4136 std::vector<MathVector<dim> > vCorner;
4137
4138 // loop elements of subset
4139 for( ; iter != iterEnd; ++iter)
4140 {
4141 // get element
4142 grid_base_object* elem = *iter;
4143
4144 // get all corner coordinates
4145 CollectCornerCoordinates(vCorner, *elem, u.domain()->position_accessor(), true);
4146
4147 // compute bf and grads at bip for element
4148 try{
4149 geo.update(elem, &vCorner[0], u.domain()->subset_handler().get());
4150 }
4151 UG_CATCH_THROW("IntegrateNormalGradientOnManifold: "
4152 "Cannot update Finite Volume Geometry.");
4153
4154 // get fct multi-indeces of element
4155 std::vector<DoFIndex> ind;
4156 u.dof_indices(elem, fct, ind);
4157
4158 // specify, which subsets are boundary
4159 for(size_t s = 0; s < bndSSGrp.size(); ++s)
4160 {
4161 // get subset index
4162 const int bndSubset = bndSSGrp[s];
4163
4164 // get all bf of this subset
4165 typedef typename DimFV1Geometry<dim>::BF BF;
4166 const std::vector<BF>& vBF = geo.bf(bndSubset);
4167
4168 // loop boundary faces
4169 for(size_t b = 0; b < vBF.size(); ++b)
4170 {
4171 // get bf
4172 const BF& bf = vBF[b];
4173
4174 // get normal on bf
4175 const MathVector<dim>& normal = bf.normal();
4176
4177 // check multi indices
4178 UG_ASSERT(ind.size() == bf.num_sh(),
4179 "IntegrateNormalGradientOnManifold::values: Wrong number of"
4180 " multi indices, ind: "<<ind.size() << ", bf.num_sh: "
4181 << bf.num_sh());
4182
4183 // compute gradient of solution at bip
4184 MathVector<dim> grad; VecSet(grad, 0.0);
4185 for(size_t sh = 0; sh < bf.num_sh(); ++sh)
4186 {
4187 const number fctVal = DoFRef(u, ind[sh]);
4188
4189 VecScaleAdd(grad, 1.0, grad, fctVal, bf.global_grad(sh));
4190 }
4191
4192 // sum up contributions
4193 value -= VecDot(grad, normal);
4194 }
4195 }
4196 }
4197 }
4198
4199#ifdef UG_PARALLEL
4200 // sum over processes
4201 if(pcl::NumProcs() > 1)
4202 {
4204 number local = value;
4205 com.allreduce(&local, &value, 1, PCL_DT_DOUBLE, PCL_RO_SUM);
4206 }
4207#endif
4208
4209// return the result
4210 return value;
4211}
4212
4213} // namespace ug
4214
4215#endif /*__H__UG__LIB_DISC__FUNCTION_SPACES__INTEGRATE__*/
parameterString s
Definition smart_pointer.h:296
bool valid() const
returns true if the pointer is valid, false if not.
Definition smart_pointer.h:415
Definition smart_pointer.h:107
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
dimension dependent base class for reference elements
Definition reference_element.h:183
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:3064
const int m_fineTopLevel
Definition integrate.h:3071
const int m_coarseTopLevel
Definition integrate.h:3074
ScalarGridFunctionData< TGridFunction > m_fineData
Definition integrate.h:3070
SmartPtr< MultiGrid > m_spMG
multigrid
Definition integrate.h:3077
virtual ~H1DistIntegrand()
DTOR.
Definition integrate.h:3098
ScalarGridFunctionData< TGridFunction > m_coarseData
Definition integrate.h:3073
static const int worldDim
world dimension of grid function
Definition integrate.h:3067
virtual void set_subset(int si)
sets subset
Definition integrate.h:3101
H1DistIntegrand(TGridFunction &fineGridFct, size_t fineCmp, TGridFunction &coarseGridFct, size_t coarseCmp)
constructor (1 is fine grid function)
Definition integrate.h:3081
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:3114
Integrand for the distance of two grid functions - evaluated in the norm .
Definition integrate.h:2657
ConstSmartPtr< weight_type > m_spWeight
scalar weight (optional)
Definition integrate.h:2674
static const int worldDim
world dimension of grid function
Definition integrate.h:2660
SmartPtr< MultiGrid > m_spMG
multigrid
Definition integrate.h:2671
H1SemiIntegrand< TGridFunction >::weight_type weight_type
Definition integrate.h:2661
virtual void set_subset(int si)
sets subset
Definition integrate.h:2714
ScalarGridFunctionData< TGridFunction > m_fineData
Definition integrate.h:2664
virtual ~H1EnergyDistIntegrand()
Definition integrate.h:2711
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:2727
const int m_fineTopLevel
Definition integrate.h:2665
ScalarGridFunctionData< TGridFunction > m_coarseData
Definition integrate.h:2667
H1EnergyDistIntegrand(TGridFunction &fineGridFct, size_t fineCmp, TGridFunction &coarseGridFct, size_t coarseCmp, ConstSmartPtr< weight_type > spWeight)
constructor
Definition integrate.h:2695
H1EnergyDistIntegrand(TGridFunction &fineGridFct, size_t fineCmp, TGridFunction &coarseGridFct, size_t coarseCmp)
constructor
Definition integrate.h:2678
const int m_coarseTopLevel
Definition integrate.h:2668
Norm of a grid function, evaluated in (weighted) H1-semi norm.
Definition integrate.h:2453
ConstSmartPtr< weight_type > m_spWeight
scalar weight (optional)
Definition integrate.h:2464
virtual void set_subset(int si)
sets subset
Definition integrate.h:2479
static const int worldDim
world dimension of grid function
Definition integrate.h:2456
UserData< MathMatrix< worldDim, worldDim >, worldDim > weight_type
Definition integrate.h:2457
ScalarGridFunctionData< TGridFunction > m_scalarData
grid function data
Definition integrate.h:2461
virtual ~H1EnergyIntegrand()
DTOR.
Definition integrate.h:2476
H1EnergyIntegrand(TGridFunction &gridFct, size_t cmp, ConstSmartPtr< weight_type > spWeight)
constructor
Definition integrate.h:2472
H1EnergyIntegrand(TGridFunction &gridFct, size_t cmp)
constructor
Definition integrate.h:2468
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:2489
Definition integrate.h:1261
virtual void set_subset(int si)
sets subset
Definition integrate.h:1292
SmartPtr< UserData< MathVector< worldDim >, worldDim > > m_spExactGrad
exact gradient
Definition integrate.h:1274
H1ErrorIntegrand(SmartPtr< UserData< number, worldDim > > spExactSol, SmartPtr< UserData< MathVector< worldDim >, worldDim > > spExactGrad, TGridFunction &gridFct, size_t cmp, number time)
constructor
Definition integrate.h:1281
ScalarGridFunctionData< TGridFunction > m_scalarData
grid function
Definition integrate.h:1268
SmartPtr< UserData< number, worldDim > > m_spExactSolution
exact solution
Definition integrate.h:1271
static const int worldDim
world dimension of grid function
Definition integrate.h:1264
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:1302
number m_time
time
Definition integrate.h:1277
Definition integrate.h:2916
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:2943
ScalarGridFunctionData< TGridFunction > m_scalarData
Definition integrate.h:2922
virtual ~H1NormIntegrand()
DTOR.
Definition integrate.h:2930
virtual void set_subset(int si)
sets subset
Definition integrate.h:2933
static const int worldDim
world dimension of grid function
Definition integrate.h:2919
H1NormIntegrand(TGridFunction &gridFct, size_t cmp)
CTOR.
Definition integrate.h:2926
Integrand for the distance of two grid functions - evaluated in the (weighted) H1-semi norm.
Definition integrate.h:2172
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:2238
H1SemiDistIntegrand(TGridFunction &fineGridFct, size_t fineCmp, TGridFunction &coarseGridFct, size_t coarseCmp, ConstSmartPtr< weight_type > spWeight)
constructor
Definition integrate.h:2210
const int m_fineTopLevel
Definition integrate.h:2180
H1SemiDistIntegrand(TGridFunction &fineGridFct, size_t fineCmp, TGridFunction &coarseGridFct, size_t coarseCmp)
constructor
Definition integrate.h:2193
ScalarGridFunctionData< TGridFunction > m_fineData
Definition integrate.h:2179
virtual ~H1SemiDistIntegrand()
Definition integrate.h:2223
ConstSmartPtr< weight_type > m_spWeight
scalar weight (optional)
Definition integrate.h:2189
H1SemiIntegrand< TGridFunction >::weight_type weight_type
Definition integrate.h:2176
virtual void set_subset(int si)
sets subset
Definition integrate.h:2226
static const int worldDim
world dimension of grid function
Definition integrate.h:2175
SmartPtr< MultiGrid > m_spMG
multigrid
Definition integrate.h:2186
ScalarGridFunctionData< TGridFunction > m_coarseData
Definition integrate.h:2182
const int m_coarseTopLevel
Definition integrate.h:2183
Norm of a grid function, evaluated in (weighted) H1-semi norm.
Definition integrate.h:1966
UserData< MathMatrix< worldDim, worldDim >, worldDim > weight_type
Definition integrate.h:1970
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:2002
static const int worldDim
world dimension of grid function
Definition integrate.h:1969
H1SemiIntegrand(TGridFunction &gridFct, size_t cmp, ConstSmartPtr< weight_type > spWeight)
constructor
Definition integrate.h:1985
ScalarGridFunctionData< TGridFunction > m_scalarData
grid function data
Definition integrate.h:1974
ConstSmartPtr< weight_type > m_spWeight
scalar weight (optional)
Definition integrate.h:1977
virtual void set_subset(int si)
sets subset
Definition integrate.h:1992
H1SemiIntegrand(TGridFunction &gridFct, size_t cmp)
constructor
Definition integrate.h:1981
virtual ~H1SemiIntegrand()
DTOR.
Definition integrate.h:1989
Abstract integrand interface.
Definition integrate.h:120
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:167
static const int worldDim
world dimension
Definition integrate.h:123
int subset() const
returns the subset
Definition integrate.h:170
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:174
TData data_type
data type
Definition integrate.h:126
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:163
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:1740
const int m_coarseTopLevel
Definition integrate.h:1751
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:1820
virtual ~L2DistIntegrand()
Definition integrate.h:1806
double m_deltaFineCoarse
shift
Definition integrate.h:1759
static const int worldDim
world dimension of grid function
Definition integrate.h:1743
L2DistIntegrand(TGridFunction &fineGridFct, size_t fineCmp, TGridFunction &coarseGridFct, size_t coarseCmp, ConstSmartPtr< weight_type > spWeight)
constructor (1st is fine grid function)
Definition integrate.h:1778
ConstSmartPtr< weight_type > m_spWeight
Definition integrate.h:1756
const int m_fineTopLevel
Definition integrate.h:1748
L2DistIntegrand(TGridFunction &fineGridFct, size_t fineCmp, TGridFunction &coarseGridFct, size_t coarseCmp)
constructor (1st is fine grid function)
Definition integrate.h:1764
ScalarGridFunctionData< TGridFunction > m_coarseData
Definition integrate.h:1750
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:1792
virtual void set_subset(int si)
sets subset
Definition integrate.h:1809
L2Integrand< TGridFunction >::weight_type weight_type
Definition integrate.h:1744
SmartPtr< MultiGrid > m_spMG
multigrid
Definition integrate.h:1754
ScalarGridFunctionData< TGridFunction > m_fineData
Definition integrate.h:1747
Definition integrate.h:1072
L2ErrorIntegrand(SmartPtr< UserData< number, worldDim > > spExactSol, TGridFunction &gridFct, size_t cmp, number time)
constructor
Definition integrate.h:1088
static const int worldDim
world dimension of grid function
Definition integrate.h:1075
number m_time
time
Definition integrate.h:1084
ScalarGridFunctionData< TGridFunction > m_scalarData
Definition integrate.h:1078
SmartPtr< UserData< number, worldDim > > m_spExactSolution
exact solution
Definition integrate.h:1081
virtual void set_subset(int si)
sets subset
Definition integrate.h:1098
virtual ~L2ErrorIntegrand()
Definition integrate.h:1095
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:1108
Grid function as L2 integrand.
Definition integrate.h:1573
ScalarGridFunctionData< TGridFunction > m_scalarData
Definition integrate.h:1581
virtual void set_subset(int si)
sets subset
Definition integrate.h:1600
UserData< number, worldDim > weight_type
Definition integrate.h:1577
L2Integrand(TGridFunction &spGridFct, size_t cmp, ConstSmartPtr< weight_type > spWeight)
Definition integrate.h:1592
virtual ~L2Integrand()
DTOR.
Definition integrate.h:1597
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:1609
static const int worldDim
Definition integrate.h:1576
L2Integrand(TGridFunction &spGridFct, size_t cmp)
CTOR.
Definition integrate.h:1588
ConstSmartPtr< weight_type > m_spWeight
scalar weight (optional, default is 1.0)
Definition integrate.h:1584
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:63
a mathematical Vector with N entries.
Definition math_vector.h:97
Definition integrate.h:964
ScalarGridFunctionData< TGridFunction > m_scalarData
Definition integrate.h:970
double max()
Definition integrate.h:1000
virtual void set_subset(int si)
sets subset
Definition integrate.h:986
static const int worldDim
world dimension of grid function
Definition integrate.h:967
MaximumDistIntegrand(TGridFunction &gridFct, size_t cmp)
constructor
Definition integrate.h:976
void reset()
Definition integrate.h:993
double m_min
Definition integrate.h:972
double min()
Definition integrate.h:999
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:1004
double m_max
Definition integrate.h:972
virtual ~MaximumDistIntegrand()
Definition integrate.h:983
provides quadrature rule for a Reference Dimension
Definition quadrature.h:70
number weight(size_t i) const
return the i'th weight
Definition quadrature.h:105
size_t size() const
number of integration points
Definition quadrature.h:92
const MathVector< dim > * points() const
returns all positions in an array of size()
Definition quadrature.h:102
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:65
TGridFunction & grid_function()
Definition integrate.h:74
TGridFunction::domain_type domain_type
Definition integrate.h:67
const TGridFunction & grid_function() const
Definition integrate.h:77
size_t m_fct
component of function
Definition integrate.h:105
size_t fct()
Definition integrate.h:80
TGridFunction & m_gridFct
grid function
Definition integrate.h:102
ConstSmartPtr< domain_type > domain() const
returns const domain (forward)
Definition integrate.h:94
ScalarGridFunctionData(TGridFunction &gridFct, size_t cmp)
Definition integrate.h:69
SmartPtr< domain_type > domain()
returns domain (forward)
Definition integrate.h:91
size_t dof_indices(TElem *elem, std::vector< DoFIndex > &ind, bool bHang=false, bool bClear=true) const
Definition integrate.h:97
LFEID m_id
local finite element id
Definition integrate.h:108
const LFEID & id() const
Definition integrate.h:83
bool is_def_in_subset(int si) const
returns true, iff scalar function is defined in subset si
Definition integrate.h:87
Definition integrate.h:3267
const size_t m_fct
Definition integrate.h:3277
virtual void set_subset(int si)
sets subset
Definition integrate.h:3288
TGridFunction * m_pGridFct
Definition integrate.h:3274
static const int worldDim
Definition integrate.h:3270
virtual ~StdFuncIntegrand()
Definition integrate.h:3285
StdFuncIntegrand(TGridFunction *pGridFct, size_t cmp)
constructor
Definition integrate.h:3281
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:3298
Abstract integrand interface (using CRTP)
Definition integrate.h:180
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:190
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:200
TImpl & getImpl()
access to implementation
Definition integrate.h:224
const TImpl & getImpl() const
const access to implementation
Definition integrate.h:227
static const int worldDim
world dimension
Definition integrate.h:183
TData data_type
data type
Definition integrate.h:186
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:210
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:667
ScalarGridFunctionData< TGridFunction > m_coarseData
Definition integrate.h:677
number inner_prod(const MathVector< worldDim > &d1, const MathVector< worldDim > &d2)
Definition integrate.h:826
number inner_dist2(const number &v1, const number &v2)
Definition integrate.h:835
number inner_prod(const number &d1, const number &d2)
Definition integrate.h:823
virtual ~UserDataDistIntegrandSq()
Definition integrate.h:705
ScalarGridFunctionData< TGridFunction > m_fineData
Definition integrate.h:674
const int m_fineTopLevel
Definition integrate.h:675
static const int worldDim
world dimension of grid function
Definition integrate.h:670
SmartPtr< MultiGrid > m_spMG
multigrid
Definition integrate.h:681
number inner_prod(const T &d1, const T &d2)
Definition integrate.h:830
number inner_dist2(const MathVector< worldDim > &v1, const MathVector< worldDim > &v2)
Definition integrate.h:838
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:692
double m_time
Definition integrate.h:688
const int m_coarseTopLevel
Definition integrate.h:678
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:721
SmartPtr< UserData< TData, worldDim > > m_spData
Definition integrate.h:685
virtual void set_subset(int si)
sets subset
Definition integrate.h:708
number inner_dist2(const T &d1, const T &d2)
Definition integrate.h:842
Type based UserData.
Definition user_data.h:144
virtual bool requires_grid_fct() const =0
returns if grid function is needed for evaluation
number data_type
Definition user_data.h:146
For arbitrary UserData , this class defines the integrand .
Definition integrate.h:467
UserDataIntegrand(SmartPtr< UserData< TData, worldDim > > spData, number time)
constructor
Definition integrate.h:496
static const int worldDim
Definition integrate.h:470
TData data_type
Definition integrate.h:473
TGridFunction * m_spGridFct
Definition integrate.h:480
UserDataIntegrand(SmartPtr< UserData< TData, worldDim > > spData, TGridFunction *spGridFct, number time)
constructor
Definition integrate.h:487
number m_time
Definition integrate.h:483
SmartPtr< UserData< TData, worldDim > > m_spData
Definition integrate.h:477
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:506
For arbitrary UserData (of type TData), this class defines the integrand .
Definition integrate.h:556
number inner_prod(const MathVector< worldDim > &d1, const MathVector< worldDim > &d2)
Definition integrate.h:652
UserDataIntegrandSq(SmartPtr< UserData< TData, worldDim > > spData, const TGridFunction *pGridFct, number time)
constructor
Definition integrate.h:576
SmartPtr< UserData< TData, worldDim > > m_spData
Definition integrate.h:566
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:597
static const int worldDim
Definition integrate.h:559
TData data_type
Definition integrate.h:562
number m_time
Definition integrate.h:572
const TGridFunction * m_pGridFct
Definition integrate.h:569
number inner_prod(const number &d1, const number &d2)
Definition integrate.h:649
number inner_prod(const T &d1, const T &d2)
Definition integrate.h:656
UserDataIntegrandSq(SmartPtr< UserData< TData, worldDim > > spData, number time)
constructor
Definition integrate.h:585
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 GeneralizedInverse(MathMatrix< N, M, T > &mOut, const MathMatrix< M, N, T > &m)
Definition math_matrix_functions_common_impl.hpp:751
matrix_t::value_type MatMaxNorm(matrix_t &m)
Definition math_matrix_functions_common_impl.hpp:1024
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:560
void MatSubtract(matrix_t &mOut, const matrix_t &m1, const matrix_t &m2)
subtracts m2 from m1 and stores the result in a mOut
Definition math_matrix_functions_common_impl.hpp:68
#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
const NullSmartPtr SPNULL
The equivalent to NULL for smart pointers.
Definition smart_pointer.h:89
#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:817
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:2411
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:2383
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:4063
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:259
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:1910
number H1Norm(TGridFunction &u, const char *cmp, int quadOrder, const char *subsets=NULL)
Definition integrate.h:3039
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:2124
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:3578
number IntegrateNormalComponentOnManifold(TGridFunction &u, const char *cmp, const char *BndSubset)
Integrates a component over some boundary subsets.
Definition integrate.h:3914
number L2Norm2(TGridFunction &u, const char *cmp, int quadOrder, const char *subsets, ConstSmartPtr< typename L2Integrand< TGridFunction >::weight_type > spWeight)
Definition integrate.h:1679
const number SMALL
Definition math_constants.h:41
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:1932
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:1399
number IntegrateSubsets(IIntegrand< number, TGridFunction::dim > &spIntegrand, TGridFunction &spGridFct, const char *subsets, int quadOrder, std::string quadType=std::string())
Definition integrate.h:392
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:3480
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:2422
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:372
number H1EnergyNorm(TGridFunction &gridFct, const char *cmp, int quadOrder, const char *subsets=NULL, ConstSmartPtr< typename H1SemiIntegrand< TGridFunction >::weight_type > weights=SPNULL)
Definition integrate.h:2630
number H1Distance2(TGridFunction &spGridFct1, const char *cmp1, TGridFunction &spGridFct2, const char *cmp2, int quadOrder, const char *subsets=NULL)
Definition integrate.h:3225
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:3811
bool SameDimensionsInAllSubsets(const SubsetGroup &subsetGroup)
Definition subset_group.cpp:299
number Minimum(SmartPtr< TGridFunction > spGridFct, const char *cmp, const char *subsets)
Definition integrate.h:1061
number StdFuncIntegralOnVertex(TGridFunction &gridFct, size_t fct, int si)
Definition integrate.h:3354
number IntegralNormalComponentOnManifoldSubsets(SmartPtr< IIntegrand< MathVector< TGridFunction::dim >, TGridFunction::dim > > spIntegrand, SmartPtr< TGridFunction > spGridFct, const char *BndSubsets, const char *InnerSubsets, int quadOrder)
Definition integrate.h:3739
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:2144
number IntegralNormalComponentOnManifoldSubset(SmartPtr< IIntegrand< MathVector< TGridFunction::dim >, TGridFunction::dim > > spIntegrand, SmartPtr< TGridFunction > spGridFct, int si, const SubsetGroup &bndSSGrp, int quadOrder)
Definition integrate.h:3709
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:3022
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:1184
number H1Distance(TGridFunction &spGridFct1, const char *cmp1, TGridFunction &spGridFct2, const char *cmp2, int quadOrder, const char *subsets=NULL)
Definition integrate.h:3235
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:1465
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:2393
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:2887
number L2Norm(TGridFunction &u, const char *cmp, int quadOrder, const char *subsets)
Definition integrate.h:1710
number Integral(SmartPtr< UserData< number, TGridFunction::dim > > spData, TGridFunction &spGridFct, const char *subsets, number time, int quadOrder, std::string quadType)
Definition integrate.h:855
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:2876
number & DoFRef(TMatrix &mat, const DoFIndex &iInd, const DoFIndex &jInd)
Definition multi_index.h:276
number GetMinimum(TGridFunction &gridFct, const char *cmp, const char *subsets)
Definition integrate.h:1047
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:2612
@ 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:839
PointerConstArray< TElem * > secure_container
Definition grid.h:146
Definition domain_traits.h:53