Plugins
Loading...
Searching...
No Matches
level_set_user_data.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012-2015: G-CSC, Goethe University Frankfurt
3 * Author: Christian Wehner
4 *
5 * This file is part of UG4.
6 *
7 * UG4 is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License version 3 (as published by the
9 * Free Software Foundation) with the following additional attribution
10 * requirements (according to LGPL/GPL v3 §7):
11 *
12 * (1) The following notice must be displayed in the Appropriate Legal Notices
13 * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14 *
15 * (2) The following notice must be displayed at a prominent place in the
16 * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17 *
18 * (3) The following bibliography is recommended for citation and must be
19 * preserved in all covered files:
20 * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21 * parallel geometric multigrid solver on hierarchically distributed grids.
22 * Computing and visualization in science 16, 4 (2013), 151-164"
23 * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24 * flexible software system for simulating pde based models on high performance
25 * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26 *
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU Lesser General Public License for more details.
31 */
32
33#ifndef __LEVEL_SET__LEVEL_SET_USER_DATA__
34#define __LEVEL_SET__LEVEL_SET_USER_DATA__
35
36#include "common/common.h"
37
39
40#include "lib_disc/lib_disc.h"
48
49
50namespace ug{
51namespace LevelSet{
52
53template <typename TData, int dim, typename TImpl>
55: public StdUserData<LevelSetUserDataBase<TData,dim,TImpl>, TData, dim>
56{
57 public:
58 virtual void operator() (TData& value,
59 const MathVector<dim>& globIP,
60 number time, int si) const
61 {
62 UG_THROW("LevelSetUserData: Need element.");
63 }
64
65 virtual void operator() (TData vValue[],
66 const MathVector<dim> vGlobIP[],
67 number time, int si, const size_t nip) const
68 {
69 UG_THROW("LevelSetUserData: Need element.");
70 }
71
72 template <int refDim>
73 void evaluate(TData vValue[],
74 const MathVector<dim> vGlobIP[],
75 number time, int si,
76 GridObject* elem,
77 const MathVector<dim> vCornerCoords[],
78 const MathVector<refDim> vLocIP[],
79 const size_t nip,
80 LocalVector* u,
81 const MathMatrix<refDim, dim>* vJT = NULL) const
82 {
83 getImpl().template evaluate<refDim>(vValue,vGlobIP,time,si,elem,
84 vCornerCoords,vLocIP,nip,u,vJT);
85 }
86
87 virtual void compute(LocalVector* u, GridObject* elem,
88 const MathVector<dim> vCornerCoords[], bool bDeriv = false)
89 {
90 const number t = this->time();
91 const int si = this->subset();
92 for(size_t s = 0; s < this->num_series(); ++s)
93 getImpl().template evaluate<dim>(this->values(s), this->ips(s), t, si,
94 elem, vCornerCoords, this->template local_ips<dim>(s),
95 this->num_ip(s), u);
96 }
97
99 const MathVector<dim> vCornerCoords[], bool bDeriv = false)
100 {
101 const int si = this->subset();
102 for(size_t s = 0; s < this->num_series(); ++s)
103 getImpl().template evaluate<dim>(this->values(s), this->ips(s), this->time(s), si,
104 elem, vCornerCoords, this->template local_ips<dim>(s),
105 this->num_ip(s), &(u->solution(this->time_point(s))));
106 }
107
109 virtual bool continuous() const {return false;}
110
112 virtual bool requires_grid_fct() const {return true;}
113
114 protected:
116 TImpl& getImpl() {return static_cast<TImpl&>(*this);}
117
119 const TImpl& getImpl() const {return static_cast<const TImpl&>(*this);}
120};
121
122
123
124template <typename TGridFunction>
126: public LevelSetUserDataBase<number, TGridFunction::dim,
127 LevelSetUserData<TGridFunction> >, virtual public INewtonUpdate
128 {
130 typedef typename TGridFunction::domain_type domain_type;
131
133 typedef typename TGridFunction::algebra_type algebra_type;
134
136 typedef typename domain_type::position_accessor_type position_accessor_type;
137
139 static const int dim = domain_type::dim;
140
142 typedef typename domain_type::grid_type grid_type;
143
145 typedef typename TGridFunction::template dim_traits<dim>::grid_base_object elem_type;
146
148
149 public:
150 // set evaluation type, implemented so far:
151 // 0 sharp (compute lsf in ip and give out inside value if inside or outside value if outside)
152 // 1 cr_ip_average (compute averaged value in ip, if in CR-FV-Geometry from-value in ip and to-value in ip have different signs,
153 // harmonic average is computed using intersection position from from and to node which is computed from level set function,
154 // the ips given in evaluate must be the CR-FV ips)
156 if (type==0) m_eval_type=sharp;
158 }
159
161
162 private:
163 // level set grid function
165
166 // approximation space for level and surface grid
168
169 // grid
171
172 /* // component of function
173 size_t m_fct;
174
175 // local finite element id
176 LFEID m_lfeID; */
177
178 public:
185#ifdef UG_FOR_LUA
186 void set_inside_data(const char* fctName){
188 }
189#endif
196#ifdef UG_FOR_LUA
197 void set_outside_data(const char* fctName){
199 }
200#endif
201
202 private:
206
207 public:
210 m_phi = spGridFct;
211 domain_type& domain = *m_phi->domain().get();
212 grid_type& grid = *domain.grid();
213 m_grid = &grid;
214 m_spApproxSpace = approxSpace;
216 }
217
218 virtual ~LevelSetUserData(){};
219
220 template <int refDim>
221 inline void evaluate(number vValue[],
222 const MathVector<dim> vGlobIP[],
223 number time, int si,
224 GridObject* elem,
225 const MathVector<dim> vCornerCoords[],
226 const MathVector<refDim> vLocIP[],
227 const size_t nip,
228 LocalVector* u,
229 const MathMatrix<refDim, dim>* vJT = NULL) const
230 {
231 UG_ASSERT(dynamic_cast<elem_type*>(elem) != NULL, "Unsupported element type");
232 elem_type* element = static_cast<elem_type*>(elem);
233
234 const size_t numVertices = element->num_vertices();
235 std::vector<Vertex*> childVertex(numVertices);
236 std::vector<number> phi(numVertices);
237
238 // for (size_t i=0;i<nip;i++){
239 // UG_LOG("co(" << i << ",:)=" << vGlobIP[i] << "\n");
240 // }
241
242 // find child vertices by injection
243 for(size_t i = 0; i < numVertices; ++i){
244 childVertex[i] = element->vertex(i);
245 };
246
247 // find out level, then get child vertices on finest level
248 size_t numChildren = m_grid->template num_children<elem_type>(element);
249 if (numChildren!=0){
250 size_t lowerLevel=0;
251 elem_type* childElem = m_grid->template get_child<elem_type>(element,0);
252 numChildren = m_grid->template num_children<elem_type>(childElem);
253 lowerLevel++;
254 while (numChildren>0){
255 childElem = m_grid->template get_child<elem_type>(childElem,0);
256 numChildren = m_grid->template num_children<elem_type>(childElem);
257 lowerLevel++;
258 };
259 for (size_t i=0;i<nip;i++){
260 for (size_t j=0;j<lowerLevel;j++){
261 childVertex[i]=m_grid->template get_child<Vertex>(childVertex[i],0);
262 }
263 }
264 }
265 // create Multiindex
266 std::vector<DoFIndex> ind;
267 for (size_t i=0;i<numVertices;i++){
268 m_phi->dof_indices(childVertex[i], 0, ind);
269 phi[i]=DoFRef(*m_phi, ind[0]);
270 };
271 bool onls=false;
272 bool inside=false;
273 for (size_t i=0;i<numVertices;i++){
274 if (phi[i]==0){
275 continue;
276 };
277 if (phi[i]<0) inside=true;
278 for (size_t j=i+1;j<numVertices;j++){
279 if (phi[i]*phi[j]<0){
280 onls = true;
281 break;
282 };
283 }
284 }
285 if (onls==false){
286 if (inside==false){
287 (*m_imInsideData)(vValue,
288 vGlobIP,
289 time, si,
290 elem,
291 vCornerCoords,
292 vLocIP,
293 nip,
294 u,
295 vJT);
296 } else {
297 (*m_imOutsideData)(vValue,
298 vGlobIP,
299 time, si,
300 elem,
301 vCornerCoords,
302 vLocIP,
303 nip,
304 u,
305 vJT);
306 };
307 return;
308 };
309 number vValueInside[max_number_of_ips];
310 number vValueOutside[max_number_of_ips];
311 (*m_imInsideData)(vValueInside,
312 vGlobIP,
313 time, si,
314 elem,
315 vCornerCoords,
316 vLocIP,
317 nip,
318 u,
319 vJT);
320 (*m_imOutsideData)(vValueOutside,
321 vGlobIP,
322 time, si,
323 elem,
324 vCornerCoords,
325 vLocIP,
326 nip,
327 u,
328 vJT);
329 if (m_eval_type == sharp){
330 for(size_t ip = 0; ip < nip; ++ip)
331 {
332 // reference object id
334
335 // memory for shapes
336 std::vector<number> vShape;
337
338 // compute lsf value in ip (from Lagrange-1 shape function) and set value according to position (inside or outside)
339 const LocalShapeFunctionSet<refDim>& rTrialSpace =
340 LocalFiniteElementProvider::get<refDim>(roid, LFEID(LFEID::LAGRANGE, dim, 1));
341
342 // evaluate shapes at ip
343 rTrialSpace.shapes(vShape, vLocIP[ip]);
344
345 // get multiindices of element
346 std::vector<DoFIndex> ind;
347 m_phi->dof_indices(elem, 0, ind);
348
349 // compute lsf at integration point
350 number phiValue = 0.0;
351 for(size_t sh = 0; sh < vShape.size(); ++sh)
352 {
353 phiValue += phi[sh] * vShape[sh];
354 }
355 if (phiValue<0) vValue[ip] = vValueInside[ip];
356 else vValue[ip] = vValueOutside[ip];
357 // UG_LOG("vValue(" << ip << ")=" << vValueOutside[ip] << "\n");
358 };
359 }
360
362 // reference object id
364
365 // memory for shapes
366 std::vector<number> vShape;
367
368 // get domain of grid function
369 const domain_type& domain = *m_phi->domain().get();
370
371 // get position accessor
372 typedef typename domain_type::position_accessor_type position_accessor_type;
373 const position_accessor_type& posAcc = domain.position_accessor();
374
375 //position_accessor_type aaPos = m_phi->domain()->position_accessor();
376
377 // coord and vertex array
381
382 for(size_t i = 0; i < numVertices; ++i){
383 vVrt[i] = element->vertex(i);
384 coCoord[i] = posAcc[vVrt[i]];
385 // UG_LOG("co_coord(" << i<< "+1,:)=" << coCoord[i] << "\n");
386 };
387 // evaluate finite volume geometry
388 geo.update(elem, &(coCoord[0]), domain.subset_handler().get());
389 std::vector<number> phiSideValue(geo.num_sh());
390 // compute interpolated lsf values in cr dofs
391 for (size_t i=0;i<geo.num_scv();i++){
392 // compute lsf value in ip (from Lagrange-1 shape function) and set value according to position (inside or outside)
393 const LocalShapeFunctionSet<dim>& rTrialSpace =
394 LocalFiniteElementProvider::get<dim>(roid, LFEID(LFEID::LAGRANGE, dim, 1));
395
396 // evaluate shapes at ip
397 rTrialSpace.shapes(vShape, geo.scv(i).local_ip());
398
399 // get multiindices of element
400 std::vector<DoFIndex> ind;
401 m_phi->dof_indices(elem, 0, ind);
402
403 // compute lsf at integration point
404 phiSideValue[i] = 0.0;
405 for(size_t sh = 0; sh < vShape.size(); ++sh)
406 {
407 phiSideValue[i] += phi[sh] * vShape[sh];
408 }
409 }
410 for (size_t ip=0;ip<nip;ip++){
411 const typename DimCRFVGeometry<dim>::SCVF& scvf = geo.scvf(ip);
412 number phiFrom = phiSideValue[scvf.from()];
413 number phiTo = phiSideValue[scvf.to()];
414 // UG_LOG("ip=" << ip << " inside=" << vValueInside[ip] << " outside=" << vValueOutside[ip] << "\n");
415 if (phiFrom==0){
416 if (phiTo<=0){
417 vValue[ip] = vValueInside[ip];
418 } else {
419 vValue[ip] = vValueOutside[ip];
420 }
421 } else {
422 number theta;
423 if (phiFrom<0){
424 if (phiTo<=0){
425 vValue[ip] = vValueInside[ip];
426 } else {
427 theta = phiFrom/(phiFrom-phiTo);
428 vValue[ip] = vValueInside[ip]*vValueOutside[ip]/(theta*vValueInside[ip]+(1-theta)*vValueOutside[ip]);
429 // UG_LOG("theta=" << theta << " vValue=" << vValue[ip] << "\n");
430 }
431 } else {
432 if (phiTo>=0){
433 vValue[ip] = vValueOutside[ip];
434 } else {
435 theta = phiFrom/(phiFrom-phiTo);
436 vValue[ip] = vValueOutside[ip]*vValueInside[ip]/(theta*vValueOutside[ip]+(1-theta)*vValueInside[ip]);
437 // UG_LOG("theta=" << theta << " vValue=" << vValue[ip] << "\n");
438 }
439 }
440 }
441 }
442 }; // ip-cr-average
443 }; // evaluate
444
445 void update(){}
446
447 private:
448 static const size_t max_number_of_ips = 20;
449 };
450
451template <typename TGridFunction>
453: public LevelSetUserDataBase<MathVector<TGridFunction::dim>, TGridFunction::dim,
454 LevelSetUserVectorData<TGridFunction> >, virtual public INewtonUpdate
455 {
457 typedef typename TGridFunction::domain_type domain_type;
458
460 typedef typename TGridFunction::algebra_type algebra_type;
461
463 typedef typename domain_type::position_accessor_type position_accessor_type;
464
466 static const int dim = domain_type::dim;
467
469 typedef typename domain_type::grid_type grid_type;
470
472 typedef typename TGridFunction::template dim_traits<dim>::grid_base_object elem_type;
473
475
476 public:
477 // set evaluation type, implemented so far:
478 // 0 sharp (compute lsf in ip and give out inside value if inside or outside value if outside)
479 // 1 cr_ip_average (compute averaged value in ip, if in CR-FV-Geometry from-value in ip and to-value in ip have different signs,
480 // harmonic average is computed using intersection position from from and to node which is computed from level set function,
481 // the ips given in evaluate must be the CR-FV ips)
483 if (type==0) m_eval_type=sharp;
485 }
486
488
489 private:
490 // level set grid function
492
493 // approximation space for level and surface grid
495
496 // grid
498
499 /* // component of function
500 size_t m_fct;
501
502 // local finite element id
503 LFEID m_lfeID; */
504
505 public:
510
512 {
514 for (int i=0;i<dim;i++){
515 f->set_entry(i, f_x);
516 }
518 }
519
521 {
522 if (dim!=2){
523 UG_THROW("NavierStokes: Setting source vector of dimension 2"
524 " to a Discretization for world dim " << dim);
525 } else {
527 f->set_entry(0, f_x);
528 f->set_entry(1, f_y);
530 }
531 }
532
534 {
535 if (dim<3){
536 UG_THROW("NavierStokes: Setting source vector of dimension 3"
537 " to a Discretization for world dim " << dim);
538 }
539 else
540 {
542 f->set_entry(0, f_x);
543 f->set_entry(1, f_y);
544 f->set_entry(2, f_z);
546 }
547 }
548
549#ifdef UG_FOR_LUA
550 void set_inside_data(const char* fctName)
551 {
553 }
554#endif
555
560
562 {
564 for (int i=0;i<dim;i++){
565 f->set_entry(i, f_x);
566 }
568 }
569
571 {
572 if (dim!=2){
573 UG_THROW("NavierStokes: Setting source vector of dimension 2"
574 " to a Discretization for world dim " << dim);
575 } else {
577 f->set_entry(0, f_x);
578 f->set_entry(1, f_y);
580 }
581 }
582
584 {
585 if (dim<3){
586 UG_THROW("NavierStokes: Setting source vector of dimension 3"
587 " to a Discretization for world dim " << dim);
588 }
589 else
590 {
592 f->set_entry(0, f_x);
593 f->set_entry(1, f_y);
594 f->set_entry(2, f_z);
596 }
597 }
598
599#ifdef UG_FOR_LUA
600 void set_outside_data(const char* fctName)
601 {
603 }
604#endif
605
606 private:
610
611 public:
614 m_phi = spGridFct;
615 domain_type& domain = *m_phi->domain().get();
616 grid_type& grid = *domain.grid();
617 m_grid = &grid;
618 m_spApproxSpace = approxSpace;
620 }
621
623
624 template <int refDim>
625 inline void evaluate(MathVector<dim> vValue[],
626 const MathVector<dim> vGlobIP[],
627 number time, int si,
628 GridObject* elem,
629 const MathVector<dim> vCornerCoords[],
630 const MathVector<refDim> vLocIP[],
631 const size_t nip,
632 LocalVector* u,
633 const MathMatrix<refDim, dim>* vJT = NULL) const
634 {
635 UG_ASSERT(dynamic_cast<elem_type*>(elem) != NULL, "Unsupported element type");
636 elem_type* element = static_cast<elem_type*>(elem);
637
638 const size_t numVertices = element->num_vertices();
639 std::vector<Vertex*> childVertex(numVertices);
640 std::vector<number> phi(numVertices);
641
642 for (size_t i=0;i<nip;i++){
643 // UG_LOG("co(" << i << ",:)=" << vGlobIP[i] << "\n");
644 }
645
646 // find child vertices by injection
647 for(size_t i = 0; i < numVertices; ++i){
648 childVertex[i] = element->vertex(i);
649 };
650
651 // find out level, then get child vertices on finest level
652 size_t numChildren = m_grid->template num_children<elem_type>(element);
653 if (numChildren!=0){
654 size_t lowerLevel=0;
655 elem_type* childElem = m_grid->template get_child<elem_type>(element,0);
656 numChildren = m_grid->template num_children<elem_type>(childElem);
657 lowerLevel++;
658 while (numChildren>0){
659 childElem = m_grid->template get_child<elem_type>(childElem,0);
660 numChildren = m_grid->template num_children<elem_type>(childElem);
661 lowerLevel++;
662 };
663 for (size_t i=0;i<nip;i++){
664 for (size_t j=0;j<lowerLevel;j++){
665 childVertex[i]=m_grid->template get_child<Vertex>(childVertex[i],0);
666 }
667 }
668 }
669 // create Multiindex
670 std::vector<DoFIndex> ind;
671 for (size_t i=0;i<numVertices;i++){
672 m_phi->dof_indices(childVertex[i], 0, ind);
673 phi[i]=DoFRef(*m_phi, ind[0]);
674 };
675 bool onls=false;
676 bool inside=false;
677 for (size_t i=0;i<numVertices;i++){
678 if (phi[i]==0){
679 continue;
680 };
681 if (phi[i]<0) inside=true;
682 for (size_t j=i+1;j<numVertices;j++){
683 if (phi[i]*phi[j]<0){
684 onls = true;
685 break;
686 };
687 }
688 }
689 if (onls==false){
690 if (inside==false){
691 (*m_imInsideData)(vValue,
692 vGlobIP,
693 time, si,
694 elem,
695 vCornerCoords,
696 vLocIP,
697 nip,
698 u,
699 vJT);
700 } else {
701 (*m_imOutsideData)(vValue,
702 vGlobIP,
703 time, si,
704 elem,
705 vCornerCoords,
706 vLocIP,
707 nip,
708 u,
709 vJT);
710 };
711 return;
712 };
714 MathVector<dim> vValueOutside[max_number_of_ips];
715 (*m_imInsideData)(vValueInside,
716 vGlobIP,
717 time, si,
718 elem,
719 vCornerCoords,
720 vLocIP,
721 nip,
722 u,
723 vJT);
724 (*m_imOutsideData)(vValueOutside,
725 vGlobIP,
726 time, si,
727 elem,
728 vCornerCoords,
729 vLocIP,
730 nip,
731 u,
732 vJT);
733 if (m_eval_type == sharp){
734 for(size_t ip = 0; ip < nip; ++ip)
735 {
736 // reference object id
738
739 // memory for shapes
740 std::vector<number> vShape;
741
742 // compute lsf value in ip (from Lagrange-1 shape function) and set value according to position (inside or outside)
743 const LocalShapeFunctionSet<refDim>& rTrialSpace =
744 LocalFiniteElementProvider::get<refDim>(roid, LFEID(LFEID::LAGRANGE, dim, 1));
745
746 // evaluate shapes at ip
747 rTrialSpace.shapes(vShape, vLocIP[ip]);
748
749 // get multiindices of element
750 std::vector<DoFIndex> ind;
751 m_phi->dof_indices(elem, 0, ind);
752
753 // compute lsf at integration point
754 number phiValue = 0.0;
755 for(size_t sh = 0; sh < vShape.size(); ++sh)
756 {
757 phiValue += phi[sh] * vShape[sh];
758 }
759 if (phiValue<0) vValue[ip] = vValueInside[ip];
760 else vValue[ip] = vValueOutside[ip];
761 // UG_LOG("vValue(" << ip << ")=" << vValueOutside[ip] << "\n");
762 };
763 }
764
766 // reference object id
768
769 // memory for shapes
770 std::vector<number> vShape;
771
772 // get domain of grid function
773 const domain_type& domain = *m_phi->domain().get();
774
775 // get position accessor
776 typedef typename domain_type::position_accessor_type position_accessor_type;
777 const position_accessor_type& posAcc = domain.position_accessor();
778
779 //position_accessor_type aaPos = m_phi->domain()->position_accessor();
780
781 // coord and vertex array
785
786 for(size_t i = 0; i < numVertices; ++i){
787 vVrt[i] = element->vertex(i);
788 coCoord[i] = posAcc[vVrt[i]];
789 // UG_LOG("co_coord(" << i<< "+1,:)=" << coCoord[i] << "\n");
790 };
791 // evaluate finite volume geometry
792 geo.update(elem, &(coCoord[0]), domain.subset_handler().get());
793 std::vector<number> phiSideValue(geo.num_sh());
794 // compute interpolated lsf values in cr dofs
795 for (size_t i=0;i<geo.num_scv();i++){
796 // compute lsf value in ip (from Lagrange-1 shape function) and set value according to position (inside or outside)
797 const LocalShapeFunctionSet<dim>& rTrialSpace =
798 LocalFiniteElementProvider::get<dim>(roid, LFEID(LFEID::LAGRANGE, dim, 1));
799
800 // evaluate shapes at ip
801 rTrialSpace.shapes(vShape, geo.scv(i).local_ip());
802
803 // get multiindices of element
804 std::vector<DoFIndex> ind;
805 m_phi->dof_indices(elem, 0, ind);
806
807 // compute lsf at integration point
808 phiSideValue[i] = 0.0;
809 for(size_t sh = 0; sh < vShape.size(); ++sh)
810 {
811 phiSideValue[i] += phi[sh] * vShape[sh];
812 }
813 }
814 for (size_t ip=0;ip<nip;ip++){
815 const typename DimCRFVGeometry<dim>::SCVF& scvf = geo.scvf(ip);
816 number phiFrom = phiSideValue[scvf.from()];
817 number phiTo = phiSideValue[scvf.to()];
818 // UG_LOG("ip=" << ip << " inside=" << vValueInside[ip] << " outside=" << vValueOutside[ip] << "\n");
819 if (phiFrom==0){
820 if (phiTo<=0){
821 vValue[ip] = vValueInside[ip];
822 } else {
823 vValue[ip] = vValueOutside[ip];
824 }
825 } else {
826 number theta;
827 if (phiFrom<0){
828 if (phiTo<=0){
829 vValue[ip] = vValueInside[ip];
830 } else {
831 theta = phiFrom/(phiFrom-phiTo);
832 for (int d=0;d<dim;d++)
833 vValue[ip][d] = vValueInside[ip][d]*vValueOutside[ip][d]/(theta*vValueInside[ip][d]+(1-theta)*vValueOutside[ip][d]);
834 // UG_LOG("theta=" << theta << " vValue=" << vValue[ip] << "\n");
835 }
836 } else {
837 if (phiTo>=0){
838 vValue[ip] = vValueOutside[ip];
839 } else {
840 theta = phiFrom/(phiFrom-phiTo);
841 for (int d=0;d<dim;d++)
842 vValue[ip][d] = vValueOutside[ip][d]*vValueInside[ip][d]/(theta*vValueOutside[ip][d]+(1-theta)*vValueInside[ip][d]);
843 // UG_LOG("theta=" << theta << " vValue=" << vValue[ip] << "\n");
844 }
845 }
846 }
847 }
848 }; // ip-cr-average
849 }; // evaluate
850
851 void update(){}
852
853 private:
854 static const size_t max_number_of_ips = 20;
855 };
856
857
858template<typename TElem,typename TGrid>
859void collect_finest_level_children(std::vector<TElem*>& childElemVector,TElem* elem,TGrid* grid){
860 size_t numChildren = grid->template num_children<TElem>(elem);
861 if (numChildren==0){
862 childElemVector.push_back(elem);
863 } else {
864 for (size_t i=0;i<numChildren;i++){
865 TElem* childElem = grid->template get_child<TElem>(elem,i);
866 size_t nc=grid->template num_children<TElem>(childElem);
867 if (nc==0){
868 childElemVector.push_back(childElem);
869 } else {
870 collect_finest_level_children<TElem,TGrid>(childElemVector,childElem,grid);
871 };
872 };
873 }
874};
875
876template<typename TElem,typename TPos,int dim>
877void computeElemBarycenter(MathVector<dim>& bary,TElem* elem,TPos posA){
878 bary = 0;
879 size_t noc=elem->num_vertices();
880 for (size_t i=0;i<noc;i++){
881 bary+=posA[elem->vertex(i)];
882 }
883 bary/=noc;
884}
885
886template <typename TGridFunction>
888: public LevelSetUserDataBase<MathVector<TGridFunction::dim>, TGridFunction::dim,
889 CRTwoPhaseSource<TGridFunction> >, virtual public INewtonUpdate
890 {
892 typedef typename TGridFunction::domain_type domain_type;
893
895 typedef typename TGridFunction::algebra_type algebra_type;
896
898 typedef typename domain_type::position_accessor_type position_accessor_type;
899
901 static const int dim = domain_type::dim;
902
904 typedef typename domain_type::grid_type grid_type;
905
907 typedef typename TGridFunction::template dim_traits<dim>::grid_base_object elem_type;
908
909 private:
910 // level set grid function
912
913 // approximation space for level and surface grid
915
916 // grid
918
919 private:
920
921 // gravitational constant
923
924 // surface tension factor
926
929
930 public:
931 void set_gravitation(number gravityconst){
932 m_gravitational_constant = gravityconst;
933 }
934
935 void set_sigma(number sigma){
936 m_sigma = sigma;
937 }
938
940
942 {
943 m_imSource = data;
944 }
945
947 {
949 for (int i=0;i<dim;i++){
950 f->set_entry(i, f_x);
951 }
952 set_source(f);
953 }
954
955 void set_source(number f_x, number f_y)
956 {
957 if (dim!=2){
958 UG_THROW("NavierStokes: Setting source vector of dimension 2"
959 " to a Discretization for world dim " << dim);
960 } else {
962 f->set_entry(0, f_x);
963 f->set_entry(1, f_y);
964 set_source(f);
965 }
966 }
967
968 void set_source(number f_x, number f_y, number f_z)
969 {
970 if (dim<3){
971 UG_THROW("NavierStokes: Setting source vector of dimension 3"
972 " to a Discretization for world dim " << dim);
973 }
974 else
975 {
977 f->set_entry(0, f_x);
978 f->set_entry(1, f_y);
979 f->set_entry(2, f_z);
980 set_source(f);
981 }
982 }
983
984#ifdef UG_FOR_LUA
985 void set_source(const char* fctName)
986 {
988 }
989#endif
990
991 public:
998#ifdef UG_FOR_LUA
999 void set_density(const char* fctName){
1001 }
1002#endif
1003
1004 private:
1007
1008 public:
1011 m_phi = spGridFct;
1012 for (int si=0;si<m_phi->num_subsets();++si){
1013 if (m_phi->num_fct(si)<2){
1014 UG_THROW("No curvature component in approximation space.");
1015 }
1016 if (m_phi->local_finite_element_id(0) != LFEID(LFEID::LAGRANGE, dim,1)){
1017 UG_THROW("First component in approximation space must be of Lagrange 1 type.");
1018 }
1019 if (m_phi->local_finite_element_id(1) != LFEID(LFEID::PIECEWISE_CONSTANT,dim,0)){
1020 UG_THROW("Second component in approximation space must be of piecewise constant type.");
1021 }
1022 };
1023 domain_type& domain = *m_phi->domain().get();
1024 grid_type& grid = *domain.grid();
1025 m_grid = &grid;
1026 m_spApproxSpace = approxSpace;
1027 set_gravitation(980);
1028 set_source(0.0);
1029 set_density(1);
1030 }
1031
1033
1034 template <int refDim>
1035 inline void evaluate(MathVector<dim> vValue[],
1036 const MathVector<dim> vGlobIP[],
1037 number time, int si,
1038 GridObject* elem,
1039 const MathVector<dim> vCornerCoords[],
1040 const MathVector<refDim> vLocIP[],
1041 const size_t nip,
1042 LocalVector* u,
1043 const MathMatrix<refDim, dim>* vJT = NULL) const
1044 {
1045 // evaluate source data
1046 // for (size_t i=0;i<nip;i++) vValue[i]=0;
1047 (*m_imSource)(vValue,
1048 vGlobIP,
1049 time, si,
1050 elem,
1051 vCornerCoords,
1052 vLocIP,
1053 nip,
1054 u,
1055 vJT);
1056 // find corner values of level set function on finest level
1057 UG_ASSERT(dynamic_cast<elem_type*>(elem) != NULL, "Unsupported element type");
1058 elem_type* element = static_cast<elem_type*>(elem);
1059
1060 const size_t numVertices = element->num_vertices();
1061 std::vector<Vertex*> childVertex(numVertices);
1062 std::vector<number> phi(numVertices);
1063
1064 // find child vertices by injection
1065 for(size_t i = 0; i < numVertices; ++i){
1066 childVertex[i] = element->vertex(i);
1067 };
1068
1069 bool onfinestlevel;
1070 // find out level, then get child vertices on finest level
1071 size_t numChildren = m_grid->template num_children<elem_type>(element);
1072 if (numChildren!=0){
1073 size_t lowerLevel=0;
1074 elem_type* childElem = m_grid->template get_child<elem_type>(element,0);
1075 numChildren = m_grid->template num_children<elem_type>(childElem);
1076 lowerLevel++;
1077 while (numChildren>0){
1078 childElem = m_grid->template get_child<elem_type>(childElem,0);
1079 numChildren = m_grid->template num_children<elem_type>(childElem);
1080 lowerLevel++;
1081 };
1082 for (size_t i=0;i<nip;i++){
1083 for (size_t j=0;j<lowerLevel;j++){
1084 childVertex[i]=m_grid->template get_child<Vertex>(childVertex[i],0);
1085 }
1086 }
1087 } else onfinestlevel=true;
1088
1089 // create Multiindex
1090 std::vector<DoFIndex> ind;
1091 for (size_t i=0;i<numVertices;i++){
1092 m_phi->dof_indices(childVertex[i], 0, ind);
1093 phi[i]=DoFRef(*m_phi, ind[0]);
1094 };
1095 bool onls=false;
1096 //bool inside=false; // inside seems to be unused (a.vogel)
1097 for (size_t i=0;i<numVertices;i++){
1098 //debug UG_LOG("phi(" << i+1 << ")=" << phi[i] << "\n");
1099 if (phi[i]==0){
1100 continue;
1101 };
1102 //if (phi[i]<0) inside=true;
1103 for (size_t j=i+1;j<numVertices;j++){
1104 //debug UG_LOG(" phi(" << j+1 << ")=" << phi[j] << "\n");
1105 if (phi[i]*phi[j]<0){
1106 onls = true;
1107 break;
1108 };
1109 }
1110 if (onls==true) break;
1111 }
1113 number densityValue[max_number_of_ips];
1114 (*m_imDensity)(densityValue,
1115 vGlobIP,
1116 time, si,
1117 elem,
1118 vCornerCoords,
1119 vLocIP,
1120 nip,
1121 u,
1122 vJT);
1123 for (int d=0;d<dim;d++){
1124 for (size_t i=0;i<nip;i++){
1125 vValue[i][d] += m_gravitational_constant * densityValue[i];
1126 }
1127 }
1128 }
1129 if (onls==true){
1130 // reference object id
1132
1133 // memory for shapes
1134 std::vector<number> vShape;
1135
1136 // get domain of grid function
1137 const domain_type& domain = *m_phi->domain().get();
1138
1139 // get position accessor
1140 typedef typename domain_type::position_accessor_type position_accessor_type;
1141 const position_accessor_type& posAcc = domain.position_accessor();
1142
1143 position_accessor_type aaPos = m_phi->domain()->position_accessor();
1144
1145 // coord and vertex array
1148 elem_type* evaluationElem;
1149 MathVector<dim> surftensSource[max_number_of_ips];
1150 for (size_t i=0;i<nip;i++){
1151 surftensSource[i]=0;
1152 }
1153 if (onfinestlevel==true){
1154 evaluationElem = element;
1155 } else {
1156 // compute barycenter
1157 MathVector<dim> coarseElementBary;
1158 computeElemBarycenter<elem_type,position_accessor_type,dim>(coarseElementBary,element,aaPos);
1159 // collect child elements
1160 std::vector<elem_type*> childElems;
1161 collect_finest_level_children<elem_type,grid_type>(childElems,element,m_grid);
1162 evaluationElem = childElems[0];
1163 number dist=1e+9;
1164 for (size_t ce=0;ce<childElems.size();ce++){
1165 MathVector<dim> bary;
1166 elem_type* currentElem = childElems[ce];
1167 size_t elnoc = currentElem->num_vertices();
1168 bool currentElemOnLS=false;
1169 std::vector<number> currentPhi(elnoc);
1170 for (size_t j=0;j<elnoc;j++){
1171 m_phi->dof_indices(currentElem->vertex(j),0,ind);
1172 currentPhi[j]=DoFRef(*m_phi,ind[0]);
1173 }
1174 for (size_t i=0;i<numVertices;i++){
1175 if (currentPhi[i]==0){
1176 continue;
1177 };
1178 for (size_t j=i+1;j<numVertices;j++){
1179 if (currentPhi[i]*currentPhi[j]<0){
1180 currentElemOnLS = true;
1181 break;
1182 }
1183 }
1184 if (currentElemOnLS==true) break;
1185 }
1186 if (currentElemOnLS==false) continue;
1187 computeElemBarycenter<elem_type,position_accessor_type,dim>(bary,currentElem,aaPos);
1188 number localdist = VecDistance(bary,coarseElementBary);
1189 if (localdist<dist){
1190 dist = localdist;
1191 evaluationElem = childElems[ce];
1192 }
1193 }
1194 }
1195 m_phi->dof_indices(evaluationElem,1, ind);
1196 // evaluate curvature
1197 number element_curvature=DoFRef(*m_phi, ind[0]);
1198 // UG_LOG(element_curvature << "\n");
1199 // scale with surface tension factor
1200 element_curvature*=m_sigma;
1202 const size_t eeNumVertices = evaluationElem->num_vertices();
1203 for(size_t i = 0; i < eeNumVertices; ++i){
1204 vVrt[i] = evaluationElem->vertex(i);
1205 coCoord[i] = posAcc[vVrt[i]];
1206 // UG_LOG("co(" << i+1 << ",:)=[" << coCoord[i][0] << "," << coCoord[i][1] << "];\n");
1207 };
1208 // evaluate finite volume geometry
1209 geo.update(elem, &(coCoord[0]), domain.subset_handler().get());
1210 std::vector<number> phiSideValue(geo.num_sh());
1211 // compute interpolated lsf values in cr dofs
1212 for (size_t i=0;i<geo.num_scv();i++){
1213 // compute lsf value in ip (from Lagrange-1 shape function) and set value according to position (inside or outside)
1214 const LocalShapeFunctionSet<dim>& rTrialSpace =
1215 LocalFiniteElementProvider::get<dim>(roid, LFEID(LFEID::LAGRANGE, dim,1));
1216
1217 // evaluate shapes at ip
1218 rTrialSpace.shapes(vShape, geo.scv(i).local_ip());
1219
1220 // get multiindices of element
1221 std::vector<DoFIndex> ind;
1222 m_phi->dof_indices(elem, 0, ind);
1223
1224 // compute lsf at integration point
1225 phiSideValue[i] = 0.0;
1226 for(size_t sh = 0; sh < vShape.size(); ++sh)
1227 {
1228 phiSideValue[i] += phi[sh] * vShape[sh];
1229 }
1230 }
1231 //for (size_t i=0;i<geo.num_scv();i++){//debug
1232 //debug UG_LOG("phi(" << i << ")=" << phiSideValue[i] << "\n");//debug
1233 //}//debug
1234 size_t nscvf = geo.num_scvf();
1235 for (size_t ip=0;ip<nscvf;ip++){
1236 const typename DimCRFVGeometry<dim>::SCVF& scvf = geo.scvf(ip);
1237 number phiFrom = phiSideValue[scvf.from()];
1238 number phiTo = phiSideValue[scvf.to()];
1239 if (phiFrom<0) for (int d=0;d<dim;d++) surftensSource[scvf.from()][d] += scvf.normal()[d] * element_curvature;
1240 if (phiTo<0) for (int d=0;d<dim;d++) surftensSource[scvf.to()][d] -= scvf.normal()[d] * element_curvature;
1241 }
1242 for (size_t i=0;i<geo.num_scv();i++){
1243 surftensSource[i]/=geo.scv(i).volume();
1244 vValue[i] += surftensSource[i];
1245 }
1246 //for (size_t i=0;i<nip;i++){
1247 // UG_LOG("rhs(" << i << ")=" << vValue[i] << "\n");//debug
1248 //};
1249 //UG_LOG("##############\n");//debug
1250 }
1251 }; // evaluate
1252
1253 void update(){}
1254
1255 private:
1256 static const size_t max_number_of_ips = 20;
1257 };
1258
1259
1260}; // end namespace levelset
1261}; // end namespace ug
1262
1263#endif /* __LEVEL_SET__LEVEL_SET_USER_DATA__ */
parameterString s
Definition Biogas.lua:2
T * get()
TData * values(size_t s)
TData & value(size_t s, size_t ip)
size_t num_ip(size_t s) const
size_t num_series() const
const MathVector< worldDim > & normal() const
size_t num_scvf() const
size_t num_scv() const
const SCV & scv(size_t i) const
size_t num_sh() const
void update(GridObject *elem, const MathVector< worldDim > *vCornerCoords, const ISubsetHandler *ish=NULL)
const SCVF & scvf(size_t i) const
virtual ReferenceObjectID reference_object_id() const=0
int subset() const
number time() const
const MathVector< dim > * ips(size_t s) const
const MathVector< dim > & ip(size_t s, size_t ip) const
Definition level_set_user_data.h:890
static const int dim
world dimension
Definition level_set_user_data.h:901
void set_source(number f_x)
Definition level_set_user_data.h:946
CRTwoPhaseSource(SmartPtr< ApproximationSpace< domain_type > > approxSpace, SmartPtr< TGridFunction > spGridFct)
constructor
Definition level_set_user_data.h:1010
number m_sigma
Definition level_set_user_data.h:925
void evaluate(MathVector< dim > vValue[], const MathVector< dim > vGlobIP[], number time, int si, GridObject *elem, const MathVector< dim > vCornerCoords[], const MathVector< refDim > vLocIP[], const size_t nip, LocalVector *u, const MathMatrix< refDim, dim > *vJT=NULL) const
Definition level_set_user_data.h:1035
SmartPtr< CplUserData< MathVector< dim >, dim > > m_imSource
Data import for source.
Definition level_set_user_data.h:928
SmartPtr< ApproximationSpace< domain_type > > m_spApproxSpace
Definition level_set_user_data.h:914
TGridFunction::template dim_traits< dim >::grid_base_object elem_type
element type
Definition level_set_user_data.h:907
void update()
Definition level_set_user_data.h:1253
static const size_t max_number_of_ips
Definition level_set_user_data.h:1256
domain_type::position_accessor_type position_accessor_type
position accessor type
Definition level_set_user_data.h:898
void set_gravitation(number gravityconst)
Definition level_set_user_data.h:931
domain_type::grid_type grid_type
grid type
Definition level_set_user_data.h:904
void set_density(SmartPtr< CplUserData< number, dim > > user)
Definition level_set_user_data.h:992
void set_source(SmartPtr< CplUserData< MathVector< dim >, dim > > data)
Definition level_set_user_data.h:941
void set_source(number f_x, number f_y)
Definition level_set_user_data.h:955
number m_gravitational_constant
Definition level_set_user_data.h:922
SmartPtr< CplUserData< number, dim > > m_imDensity
density import for inside and outside density
Definition level_set_user_data.h:1006
grid_type * m_grid
Definition level_set_user_data.h:917
SmartPtr< TGridFunction > m_phi
Definition level_set_user_data.h:911
TGridFunction::domain_type domain_type
domain type
Definition level_set_user_data.h:892
TGridFunction::algebra_type algebra_type
algebra type
Definition level_set_user_data.h:895
virtual ~CRTwoPhaseSource()
Definition level_set_user_data.h:1032
void set_source(number f_x, number f_y, number f_z)
Definition level_set_user_data.h:968
void set_density(number val)
Definition level_set_user_data.h:995
void set_sigma(number sigma)
Definition level_set_user_data.h:935
Definition level_set_user_data.h:56
const TImpl & getImpl() const
const access to implementation
Definition level_set_user_data.h:119
virtual void compute(LocalVectorTimeSeries *u, GridObject *elem, const MathVector< dim > vCornerCoords[], bool bDeriv=false)
Definition level_set_user_data.h:98
void evaluate(TData vValue[], const MathVector< dim > vGlobIP[], number time, int si, GridObject *elem, const MathVector< dim > vCornerCoords[], const MathVector< refDim > vLocIP[], const size_t nip, LocalVector *u, const MathMatrix< refDim, dim > *vJT=NULL) const
Definition level_set_user_data.h:73
virtual void operator()(TData &value, const MathVector< dim > &globIP, number time, int si) const
Definition level_set_user_data.h:58
virtual bool continuous() const
returns if provided data is continuous over geometric object boundaries
Definition level_set_user_data.h:109
virtual void compute(LocalVector *u, GridObject *elem, const MathVector< dim > vCornerCoords[], bool bDeriv=false)
Definition level_set_user_data.h:87
TImpl & getImpl()
access to implementation
Definition level_set_user_data.h:116
virtual bool requires_grid_fct() const
returns if grid function is needed for evaluation
Definition level_set_user_data.h:112
Definition level_set_user_data.h:128
void update()
Definition level_set_user_data.h:445
SmartPtr< ApproximationSpace< domain_type > > m_spApproxSpace
Definition level_set_user_data.h:167
void set_outside_data(SmartPtr< CplUserData< number, dim > > user)
Definition level_set_user_data.h:190
TGridFunction::algebra_type algebra_type
algebra type
Definition level_set_user_data.h:133
domain_type::grid_type grid_type
grid type
Definition level_set_user_data.h:142
static const int dim
world dimension
Definition level_set_user_data.h:139
void set_inside_data(number val)
Definition level_set_user_data.h:182
static const size_t max_number_of_ips
Definition level_set_user_data.h:448
eval_type m_eval_type
Definition level_set_user_data.h:160
domain_type::position_accessor_type position_accessor_type
position accessor type
Definition level_set_user_data.h:136
void set_inside_data(SmartPtr< CplUserData< number, dim > > user)
Definition level_set_user_data.h:179
void evaluate(number vValue[], const MathVector< dim > vGlobIP[], number time, int si, GridObject *elem, const MathVector< dim > vCornerCoords[], const MathVector< refDim > vLocIP[], const size_t nip, LocalVector *u, const MathMatrix< refDim, dim > *vJT=NULL) const
Definition level_set_user_data.h:221
TGridFunction::template dim_traits< dim >::grid_base_object elem_type
element type
Definition level_set_user_data.h:145
SmartPtr< CplUserData< number, dim > > m_imInsideData
Data import for inside and outside data.
Definition level_set_user_data.h:204
TGridFunction::domain_type domain_type
domain type
Definition level_set_user_data.h:130
eval_type
Definition level_set_user_data.h:147
@ cr_ip_average
Definition level_set_user_data.h:147
@ sharp
Definition level_set_user_data.h:147
grid_type * m_grid
Definition level_set_user_data.h:170
LevelSetUserData(SmartPtr< ApproximationSpace< domain_type > > approxSpace, SmartPtr< TGridFunction > spGridFct)
constructor
Definition level_set_user_data.h:209
void set_eval_type(int type)
Definition level_set_user_data.h:155
SmartPtr< TGridFunction > m_phi
Definition level_set_user_data.h:164
SmartPtr< CplUserData< number, dim > > m_imOutsideData
Definition level_set_user_data.h:205
void set_outside_data(number val)
Definition level_set_user_data.h:193
virtual ~LevelSetUserData()
Definition level_set_user_data.h:218
Definition level_set_user_data.h:455
void set_eval_type(int type)
Definition level_set_user_data.h:482
SmartPtr< CplUserData< MathVector< dim >, dim > > m_imOutsideData
Definition level_set_user_data.h:609
void set_outside_data(number f_x, number f_y, number f_z)
Definition level_set_user_data.h:583
TGridFunction::algebra_type algebra_type
algebra type
Definition level_set_user_data.h:460
void update()
Definition level_set_user_data.h:851
void set_outside_data(number f_x, number f_y)
Definition level_set_user_data.h:570
SmartPtr< TGridFunction > m_phi
Definition level_set_user_data.h:491
TGridFunction::template dim_traits< dim >::grid_base_object elem_type
element type
Definition level_set_user_data.h:472
void set_inside_data(number f_x)
Definition level_set_user_data.h:511
void evaluate(MathVector< dim > vValue[], const MathVector< dim > vGlobIP[], number time, int si, GridObject *elem, const MathVector< dim > vCornerCoords[], const MathVector< refDim > vLocIP[], const size_t nip, LocalVector *u, const MathMatrix< refDim, dim > *vJT=NULL) const
Definition level_set_user_data.h:625
void set_inside_data(SmartPtr< CplUserData< MathVector< dim >, dim > > data)
Definition level_set_user_data.h:506
eval_type m_eval_type
Definition level_set_user_data.h:487
void set_outside_data(SmartPtr< CplUserData< MathVector< dim >, dim > > data)
Definition level_set_user_data.h:556
domain_type::position_accessor_type position_accessor_type
position accessor type
Definition level_set_user_data.h:463
SmartPtr< CplUserData< MathVector< dim >, dim > > m_imInsideData
Data import for inside and outside data.
Definition level_set_user_data.h:608
SmartPtr< ApproximationSpace< domain_type > > m_spApproxSpace
Definition level_set_user_data.h:494
LevelSetUserVectorData(SmartPtr< ApproximationSpace< domain_type > > approxSpace, SmartPtr< TGridFunction > spGridFct)
constructor
Definition level_set_user_data.h:613
domain_type::grid_type grid_type
grid type
Definition level_set_user_data.h:469
void set_inside_data(number f_x, number f_y)
Definition level_set_user_data.h:520
virtual ~LevelSetUserVectorData()
Definition level_set_user_data.h:622
eval_type
Definition level_set_user_data.h:474
@ sharp
Definition level_set_user_data.h:474
@ cr_ip_average
Definition level_set_user_data.h:474
static const int dim
world dimension
Definition level_set_user_data.h:466
void set_outside_data(number f_x)
Definition level_set_user_data.h:561
void set_inside_data(number f_x, number f_y, number f_z)
Definition level_set_user_data.h:533
static const size_t max_number_of_ips
Definition level_set_user_data.h:854
TGridFunction::domain_type domain_type
domain type
Definition level_set_user_data.h:457
grid_type * m_grid
Definition level_set_user_data.h:497
virtual void shapes(std::vector< std::vector< shape_type > > &vvShape, const std::vector< MathVector< dim > > &vLocPos) const=0
LocalVector & solution(size_t i)
std::string type() const
SmartPtr< TGrid > grid()
#define UG_ASSERT(expr, msg)
#define UG_THROW(msg)
double number
vector_t::value_type VecDistance(const vector_t &v1, const vector_t &v2)
void collect_finest_level_children(std::vector< TElem * > &childElemVector, TElem *elem, TGrid *grid)
Definition level_set_user_data.h:859
void computeElemBarycenter(MathVector< dim > &bary, TElem *elem, TPos posA)
Definition level_set_user_data.h:877
ReferenceObjectID
const number & DoFRef(const TMatrix &mat, const DoFIndex &iInd, const DoFIndex &jInd)
SmartPtr< T, FreePolicy > make_sp(T *inst)