This source file includes following definitions.
- evaluate
- evaluate
- jac_ran_to_jac_ran_lhs
- jac_ran_to_jac_ran_rhs
- ran_to_ran
- ran_u_normal_rhs
- Brusselator_model
- ran_to_ran
- ran_to_ran_ones
- ran_to_ran_lhs
- jac_ran_to_jac_ran_lhs
- tri_ran_to_ran_lhs
- generate_rhs
- generate_rhs_old_surface
- generate_rhs_new_surface
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 #ifndef TUMOR_GROWTH_OPERATOR_H
57 #define TUMOR_GROWTH_OPERATOR_H
58
59 #include <cmath>
60 #include <random>
61 #include <functional>
62
63 #include <dune/fem/function/common/function.hh>
64 #include <dune/fem/solver/timeprovider.hh>
65 #include <dune/fem/quadrature/quadrature.hh>
66
67 #include <dune/common/fmatrix.hh>
68
69 #include <dune/fem/quadrature/cachingquadrature.hh>
70 #include <dune/fem/operator/common/operator.hh>
71
72 #include <heat.hh>
73
74 namespace Tumor_growth{
75
76
77
78 template<typename Function_space>
79 struct Initial_data_u :
80 Dune::Fem::Function<Function_space, Initial_data_u<Function_space> >{
81
82 explicit Initial_data_u(const double mean_value, const double variance)
83 : random_fun (std::bind(Random_dist {mean_value, variance},
84 Random_engine {}))
85 {}
86
87 using Domain = typename Function_space::DomainType;
88 using Range = typename Function_space::RangeType;
89
90 void evaluate(const Domain& p, Range& q) const{
91 q = random_fun();
92 }
93 private:
94 using Random_dist = std::normal_distribution<>;
95 using Random_engine = std::default_random_engine;
96 std::function<double()> random_fun;
97 };
98
99 template<typename Function_space>
100 struct Initial_data_w :
101 Dune::Fem::Function<Function_space, Initial_data_w<Function_space> >{
102
103 explicit Initial_data_w(const double mean_value, const double variance)
104 : base {mean_value}, pertubation {variance}
105 {}
106
107 using Domain = typename Function_space::DomainType;
108 using Range = typename Function_space::RangeType;
109
110 void evaluate(const Domain& p, Range& q) const{
111
112 q = Range {base};
113 }
114 private:
115 double base;
116 double pertubation;
117 };
118
119
120
121
122 template <typename Vector_function_space, typename Scalar_function_space>
123 struct Surface_evolution_model{
124 using Vector = Vector_function_space;
125 using Scalar = Scalar_function_space;
126
127 template<typename T>
128 using Domain = typename T::DomainType;
129 template<typename T>
130 using Range = typename T::RangeType;
131 template<typename T>
132 using JacobianRange = typename T::JacobianRangeType;
133 template<typename T>
134 using DomainField = typename T::DomainFieldType;
135 template<typename T>
136 using RangeField = typename T::RangeFieldType;
137 static const int dim_vec_domain = Domain<Vector>::dimension;
138 static const int dim_vec_range = Range<Vector>::dimension;
139 static const int dim_scalar_domain = Domain<Scalar>::dimension;
140 static const int dim_scalar_range = Range<Scalar>::dimension;
141
142 explicit
143 Surface_evolution_model (const Dune::Fem::TimeProviderBase& time_provider,
144 const double alpha_regularization_parameter,
145 const double epsilon_regularization_parameter,
146 const double delta_parameter) :
147 tp {time_provider}, reg_alpha {alpha_regularization_parameter},
148 reg_epsilon {epsilon_regularization_parameter}, delta {delta_parameter}
149 {}
150
151
152
153
154
155
156
157
158 template <typename Entity, typename Point>
159 void jac_ran_to_jac_ran_lhs(const Entity& entity, const Point& xx,
160 const JacobianRange<Vector>& dX_p,
161 JacobianRange<Vector>& a_dX_p) const;
162
163 template <typename Entity, typename Point>
164 void jac_ran_to_jac_ran_rhs(const Entity& entity, const Point& xx,
165 const JacobianRange<Vector>& dX_p,
166 JacobianRange<Vector>& a_dX_p) const;
167
168 template <typename Entity, typename Point>
169 void ran_to_ran(const Entity& entity, const Point& xx,
170 const Range<Vector>& X_p, Range<Vector>& X_p_chi) const;
171
172 template <typename Entity, typename Point>
173 void ran_u_normal_rhs(const Entity& entity, const Point& xx,
174 const Range<Scalar>& u_p,
175 Range<Vector>& n_p_chi) const;
176
177 private:
178 const Dune::Fem::TimeProviderBase& tp;
179 const double reg_alpha;
180 const double reg_epsilon;
181 const double delta;
182 };
183
184 enum class Growth {promoting, inhibiting};
185
186 template <typename Scalar_function_space>
187 class Brusselator_model{
188 public:
189 using Scalar = Scalar_function_space;
190 using Range = typename Scalar::RangeType;
191 using JacobianRange = typename Scalar::JacobianRangeType;
192
193 explicit
194 Brusselator_model(const double uniform_time_step,
195 const double gamma,
196 const double a_or_b,
197 const Growth scalar_type,
198 const double diffusion = 1.);
199
200
201
202
203
204
205 template <typename Entity, typename Point>
206 void ran_to_ran(const Entity& entity, const Point& xx,
207 const Range& u_p, Range& u_p_chi) const;
208
209
210 template <typename Entity, typename Point>
211 void ran_to_ran_ones(const Entity& entity, const Point& xx,
212 Range& ones_chi) const;
213
214
215 template <typename Entity, typename Point>
216 void ran_to_ran_lhs(const Entity& entity, const Point& xx,
217 const Range& u_p, Range& u_p_chi) const;
218
219
220 template <typename Entity, typename Point>
221 void jac_ran_to_jac_ran_lhs(const Entity& entity, const Point& xx,
222 const JacobianRange& du_p,
223 JacobianRange& du_p_dchi) const;
224
225
226 template <typename Entity, typename Point>
227 void tri_ran_to_ran_lhs(const Entity& entity, const Point& xx,
228 const Range& first, const Range& second,
229 const Range& u_p, Range& uwu_p_chi) const;
230
231
232 private:
233 using Domain = typename Scalar::DomainType;
234
235
236
237 double mass_matrix_lhs {0.};
238 double stiffness_matrix_lhs {0.};
239 double quadrilinear_mass_matrix_lhs {0.};
240 double mass_matrix_rhs {0.};
241 };
242
243
244
245
246 template <typename Vec_discrete_function, typename Scalar_discrete_function,
247 typename Model>
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265 struct Surface_parabolic_operator
266 : Dune::Fem::Operator<Vec_discrete_function>{
267 using Vector = Vec_discrete_function;
268 using Scalar = Scalar_discrete_function;
269 protected:
270 using Discrete_function_space = typename Vector::DiscreteFunctionSpaceType;
271 using Iterator = typename Discrete_function_space::IteratorType;
272 using Entity = typename Iterator::Entity;
273 using Geometry = typename Entity::Geometry;
274 using GridPart = typename Discrete_function_space::GridPartType;
275 using QuadratureType = Dune::Fem::CachingQuadrature<GridPart, 0>;
276
277 template<typename T>
278 using Local_function = typename T::LocalFunctionType;
279 template<typename T>
280 using Range = typename Local_function<T>::RangeType;
281 template<typename T>
282 using Jacobian_range = typename Local_function<T>::JacobianRangeType;
283
284 public:
285 explicit
286 Surface_parabolic_operator(const Model& model_input,
287 const Scalar_discrete_function& u_previous,
288 const double bdf_alpha_lead_coeff = 1.)
289 : model (model_input), u_approx (u_previous), bdf_factor {bdf_alpha_lead_coeff}
290 {}
291
292 virtual void operator() (const Vec_discrete_function& u,
293 Vec_discrete_function& w) const;
294
295
296
297 void generate_rhs(const Vec_discrete_function& u, Vec_discrete_function& w) const;
298
299
300
301 private:
302 const Model model;
303 const Scalar_discrete_function& u_approx;
304 const double bdf_factor;
305 };
306
307 template <typename Scalar_discrete_function, typename Model>
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327 struct Scalar_parabolic_operator
328 : Dune::Fem::Operator<Scalar_discrete_function>{
329 public:
330 using FE_function = Scalar_discrete_function;
331
332 explicit
333 Scalar_parabolic_operator(const Model& model_input,
334 const FE_function& u_previous,
335 const FE_function& u_or_w_previous,
336 const double bdf_alpha_lead_coeff = 1.)
337 : model (model_input), u_approx (u_previous), u_or_w_approx (u_or_w_previous),
338 bdf_factor {bdf_alpha_lead_coeff}
339 {}
340
341 virtual void operator() (const FE_function& u, FE_function& w) const;
342
343
344
345
346 void generate_rhs_old_surface(const FE_function& u, FE_function& w) const;
347
348
349 void generate_rhs_new_surface(FE_function& w) const;
350
351 private:
352 using Discrete_function_space = typename FE_function::DiscreteFunctionSpaceType;
353 using Iterator = typename Discrete_function_space::IteratorType;
354 using Entity = typename Iterator::Entity;
355 using Geometry = typename Entity::Geometry;
356 using GridPart = typename Discrete_function_space::GridPartType;
357 using QuadratureType = Dune::Fem::CachingQuadrature<GridPart, 0>;
358
359 using Local_function = typename FE_function::LocalFunctionType;
360 using Range = typename Local_function::RangeType;
361 using Jacobian_range = typename Local_function::JacobianRangeType;
362
363
364
365 const Model model;
366 const FE_function& u_approx;
367 const FE_function& u_or_w_approx;
368 const double bdf_factor;
369 };
370
371
372
373
374
375
376 template <typename Vector_function_space, typename Scalar_function_space>
377 template <typename Entity, typename Point>
378 inline void Surface_evolution_model<Vector_function_space, Scalar_function_space>::
379 jac_ran_to_jac_ran_lhs(const Entity& entity, const Point& xx,
380 const JacobianRange<Vector>& dX_p,
381 JacobianRange<Vector>& a_dX_p) const{
382
383
384
385
386
387 a_dX_p = dX_p;
388 a_dX_p *= (reg_alpha + reg_epsilon * tp.deltaT());
389 }
390 template <typename Vector_function_space, typename Scalar_function_space>
391 template <typename Entity, typename Point>
392 inline void Surface_evolution_model<Vector_function_space, Scalar_function_space>::
393 jac_ran_to_jac_ran_rhs(const Entity& entity, const Point& xx,
394 const JacobianRange<Vector>& dX_p,
395 JacobianRange<Vector>& a_dX_p) const{
396
397
398
399
400
401 a_dX_p = dX_p;
402 a_dX_p *= reg_alpha;
403 }
404 template <typename Vector_function_space, typename Scalar_function_space>
405 template <typename Entity, typename Point>
406 inline void Surface_evolution_model<Vector_function_space, Scalar_function_space>::
407 ran_to_ran(const Entity& entity, const Point& xx,
408 const Range<Vector>& X_p, Range<Vector>& X_p_chi) const{
409
410
411
412
413 X_p_chi = X_p;
414 }
415 template <typename Vector_function_space, typename Scalar_function_space>
416 template <typename Entity, typename Point>
417 void Surface_evolution_model<Vector_function_space, Scalar_function_space>::
418 ran_u_normal_rhs(const Entity& entity, const Point& xx, const Range<Scalar>& u_p,
419 Range<Vector>& n_p_chi) const{
420
421
422
423
424
425
426
427
428
429 Domain<Vector> p0 = entity.geometry().corner(0);
430 Domain<Vector> p1 = entity.geometry().corner(1);
431 Domain<Vector> p2 = entity.geometry().corner(2);
432
433
434
435
436 Domain<Vector> v = p2 - p0;
437 Domain<Vector> w = p1 - p0;
438
439 auto eucl_norm = [](const Range<Vector>& vv){
440 return std::sqrt(vv[0] * vv[0] + vv[1] * vv[1] + vv[2] * vv[2]);
441 };
442
443
444
445 n_p_chi[0] = v[1] * w[2] - v[2] * w[1];
446 n_p_chi[1] = - v[0] * w[2] + v[2] * w[0];
447 n_p_chi[2] = v[0] * w[1] - v[1] * w[0];
448 n_p_chi /= eucl_norm(n_p_chi);
449
450
451 n_p_chi *= u_p * tp.deltaT() * delta;
452 }
453
454
455
456
457 template <typename Scalar_function_space>
458 Brusselator_model<Scalar_function_space>::
459 Brusselator_model(const double uniform_time_step,
460 const double gamma, const double a_or_b, const Growth scalar_type,
461 const double diffusion)
462 {
463 switch(scalar_type){
464 case Growth::promoting:
465 mass_matrix_lhs = 1. + uniform_time_step * gamma;
466 stiffness_matrix_lhs = uniform_time_step;
467 quadrilinear_mass_matrix_lhs = (-1.) * uniform_time_step * gamma;
468 break;
469 case Growth::inhibiting:
470 mass_matrix_lhs = 1.;
471 stiffness_matrix_lhs = uniform_time_step * diffusion;
472 quadrilinear_mass_matrix_lhs = uniform_time_step * gamma;
473 break;
474 default:
475 throw std::runtime_error {"Error in constructor of Brusselator_model.\n"
476 "Your scalar_type is not implemented."};
477 break;
478 };
479 mass_matrix_rhs = uniform_time_step * gamma * a_or_b;
480 }
481
482 template <typename Scalar_function_space>
483 template <typename Entity, typename Point>
484 inline void Brusselator_model<Scalar_function_space>::
485 ran_to_ran(const Entity& entity, const Point& xx,
486 const Range& u_p, Range& u_p_chi) const{
487 u_p_chi = u_p;
488 }
489 template <typename Scalar_function_space>
490 template <typename Entity, typename Point>
491 inline void Brusselator_model<Scalar_function_space>::
492 ran_to_ran_ones(const Entity& entity, const Point& xx,
493 Range& ones_chi) const{
494
495 ones_chi = Range {mass_matrix_rhs};
496 }
497 template <typename Scalar_function_space>
498 template <typename Entity, typename Point>
499 inline void Brusselator_model<Scalar_function_space>::
500 ran_to_ran_lhs(const Entity& entity, const Point& xx,
501 const Range& u_p, Range& u_p_chi) const{
502
503 u_p_chi = u_p;
504 u_p_chi *= mass_matrix_lhs;
505 }
506 template <typename Scalar_function_space>
507 template <typename Entity, typename Point>
508 inline void Brusselator_model<Scalar_function_space>::
509 jac_ran_to_jac_ran_lhs(const Entity& entity, const Point& xx,
510 const JacobianRange& du_p,
511 JacobianRange& du_p_dchi) const{
512
513 du_p_dchi = du_p;
514 du_p_dchi *= stiffness_matrix_lhs;
515 }
516 template <typename Scalar_function_space>
517 template <typename Entity, typename Point>
518 inline void Brusselator_model<Scalar_function_space>::
519 tri_ran_to_ran_lhs(const Entity& entity, const Point& xx,
520 const Range& first, const Range& second,
521 const Range& u_p, Range& uwu_p_chi) const{
522
523 uwu_p_chi = u_p;
524 uwu_p_chi *= first * second * quadrilinear_mass_matrix_lhs;
525 }
526
527
528
529
530 template <typename Vec_discrete_function, typename Scalar_discrete_function,
531 typename Model>
532 void Surface_parabolic_operator<Vec_discrete_function,
533 Scalar_discrete_function, Model>::
534 operator() (const Vec_discrete_function& u, Vec_discrete_function& w) const{
535 w.clear();
536
537 const Discrete_function_space& dfSpace = w.space();
538 for(const Entity& entity : dfSpace){
539
540
541
542
543
544 const Geometry& geometry = entity.geometry();
545
546 const Local_function<Vector> uLocal = u.localFunction(entity);
547 Local_function<Vector> wLocal = w.localFunction(entity);
548
549 QuadratureType quadrature(entity, uLocal.order() + wLocal.order() + 1);
550
551 for(size_t pt = 0; pt < quadrature.nop(); ++pt){
552
553 Range<Vector> u_x;
554 uLocal.evaluate(quadrature[pt], u_x);
555
556 Jacobian_range<Vector> du_x;
557 uLocal.jacobian(quadrature[pt], du_x);
558
559 Range<Vector> u_x_psi;
560
561 model.ran_to_ran(entity, quadrature[pt], u_x, u_x_psi);
562
563
564
565 Jacobian_range<Vector> du_x_dpsi;
566
567 model.jac_ran_to_jac_ran_lhs(entity, quadrature[pt], du_x, du_x_dpsi);
568
569
570 const typename QuadratureType::CoordinateType& x = quadrature.point(pt);
571 const double weight = quadrature.weight(pt) * geometry.integrationElement(x);
572
573
574 u_x_psi *= weight;
575 du_x_dpsi *= weight;
576 wLocal.axpy(quadrature[pt], u_x_psi, du_x_dpsi);
577
578 }
579 }
580 w.communicate();
581 }
582 template <typename Vec_discrete_function, typename Scalar_discrete_function,
583 typename Model>
584 void Surface_parabolic_operator<Vec_discrete_function,
585 Scalar_discrete_function, Model>::
586 generate_rhs(const Vec_discrete_function& u, Vec_discrete_function& w) const{
587 w.clear();
588
589 const Discrete_function_space& dfSpace = w.space();
590 for(const Entity& entity : dfSpace){
591
592
593
594 const Geometry& geometry = entity.geometry();
595
596 const Local_function<Vector> uLocal = u.localFunction(entity);
597 const Local_function<Scalar> u_approx_local
598 = u_approx.localFunction(entity);
599 Local_function<Vector> wLocal = w.localFunction(entity);
600
601 QuadratureType quadrature(entity, uLocal.order() + wLocal.order() + 1);
602
603 for(size_t pt = 0; pt < quadrature.nop(); ++pt){
604 Range<Vector> u_x;
605 uLocal.evaluate(quadrature[pt], u_x);
606
607 Range<Scalar> u_approx_x;
608 u_approx_local.evaluate(quadrature[pt], u_approx_x);
609
610 Jacobian_range<Vector> du_x;
611 uLocal.jacobian(quadrature[pt], du_x);
612
613 Range<Vector> u_x_psi;
614
615 model.ran_to_ran(entity, quadrature[pt], u_x, u_x_psi);
616
617
618 Jacobian_range<Vector> du_x_dpsi;
619
620 model.jac_ran_to_jac_ran_rhs(entity, quadrature[pt], du_x, du_x_dpsi);
621
622
623 Range<Vector> un_x_psi;
624
625 model.ran_u_normal_rhs(entity, quadrature[pt], u_approx_x, un_x_psi);
626
627 const typename QuadratureType::CoordinateType& x = quadrature.point(pt);
628 const double weight = quadrature.weight(pt) * geometry.integrationElement(x);
629
630
631 u_x_psi *= weight;
632 un_x_psi *= weight;
633 du_x_dpsi *= weight;
634
635 wLocal.axpy(quadrature[pt], u_x_psi, du_x_dpsi);
636 wLocal.axpy(quadrature[pt], un_x_psi, 0);
637
638 }
639 }
640 w.communicate();
641 }
642
643
644
645
646 template <typename Scalar_discrete_function, typename Model>
647 void Scalar_parabolic_operator<Scalar_discrete_function, Model>::
648 operator() (const FE_function& u, FE_function& w) const{
649 w.clear();
650
651 const Discrete_function_space& dfSpace = w.space();
652 for(const Entity& entity : dfSpace){
653 const Geometry& geometry = entity.geometry();
654
655 const Local_function uLocal = u.localFunction(entity);
656 const auto u_approx_local = u_approx.localFunction(entity);
657 const auto u_or_w_approx_local = u_or_w_approx.localFunction(entity);
658 Local_function wLocal = w.localFunction(entity);
659
660 QuadratureType quadrature(entity, uLocal.order() + wLocal.order() + 1);
661 for(size_t pt = 0; pt < quadrature.nop(); ++pt){
662 Range u_x;
663 uLocal.evaluate(quadrature[pt], u_x);
664
665 Jacobian_range du_x;
666 uLocal.jacobian(quadrature[pt], du_x);
667
668 Range u_x_chi;
669
670 model.ran_to_ran_lhs(entity, quadrature[pt], u_x, u_x_chi);
671
672
673
674 Jacobian_range du_x_dchi;
675
676
677 model.jac_ran_to_jac_ran_lhs(entity, quadrature[pt], du_x, du_x_dchi);
678
679
680 const typename QuadratureType::CoordinateType& x = quadrature.point(pt);
681 const double weight = quadrature.weight(pt) * geometry.integrationElement(x);
682
683
684 u_x_chi *= weight;
685 du_x_dchi *= weight;
686 wLocal.axpy(quadrature[pt], u_x_chi, du_x_dchi);
687
688 }
689
690 QuadratureType
691 bigger_quadrature(entity, uLocal.order() + u_approx_local.order()
692 + u_or_w_approx_local.order() + wLocal.order() + 1);
693 for(size_t pt = 0; pt < bigger_quadrature.nop(); ++pt){
694 Range u_x;
695 uLocal.evaluate(bigger_quadrature[pt], u_x);
696 Range u_app;
697 u_approx_local.evaluate(bigger_quadrature[pt], u_app);
698 Range u_or_w_app;
699 u_or_w_approx_local.evaluate(bigger_quadrature[pt], u_or_w_app);
700
701
702 Range uwu_x_chi;
703
704 model.tri_ran_to_ran_lhs(entity, bigger_quadrature[pt],
705 u_app, u_or_w_app, u_x, uwu_x_chi);
706
707 const typename QuadratureType::CoordinateType& x = bigger_quadrature.point(pt);
708 const double weight
709 = bigger_quadrature.weight(pt) * geometry.integrationElement(x);
710
711
712 wLocal.axpy(bigger_quadrature[pt], uwu_x_chi, 0);
713 }
714 }
715 w.communicate();
716 }
717 template <typename Scalar_discrete_function, typename Model>
718 void Scalar_parabolic_operator<Scalar_discrete_function, Model>::
719 generate_rhs_old_surface (const FE_function& u, FE_function& w) const{
720 w.clear();
721
722 const Discrete_function_space& dfSpace = w.space();
723 for(const Entity& entity : dfSpace){
724
725 const Geometry& geometry = entity.geometry();
726
727 const Local_function uLocal = u.localFunction(entity);
728 Local_function wLocal = w.localFunction(entity);
729
730 QuadratureType quadrature(entity, uLocal.order() + wLocal.order() + 1);
731
732 for(size_t pt = 0; pt < quadrature.nop(); ++pt){
733
734 Range u_x;
735 uLocal.evaluate(quadrature[pt], u_x);
736
737 Range u_x_chi;
738
739 model.ran_to_ran(entity, quadrature[pt], u_x, u_x_chi);
740
741
742 const typename QuadratureType::CoordinateType& x = quadrature.point(pt);
743 const double weight = quadrature.weight(pt) * geometry.integrationElement(x);
744
745
746 u_x_chi *= weight;
747 wLocal.axpy(quadrature[pt], u_x_chi, 0);
748
749 }
750 }
751 w.communicate();
752 }
753 template <typename Scalar_discrete_function, typename Model>
754 void Scalar_parabolic_operator<Scalar_discrete_function, Model>::
755 generate_rhs_new_surface (FE_function& w) const{
756 w.clear();
757
758 const Discrete_function_space& dfSpace = w.space();
759 for(const Entity& entity : dfSpace){
760 const Geometry& geometry = entity.geometry();
761
762 Local_function wLocal = w.localFunction(entity);
763
764 QuadratureType quadrature(entity, wLocal.order() + 1);
765
766 for(size_t pt = 0; pt < quadrature.nop(); ++pt){
767
768 Range ones_chi;
769
770 model.ran_to_ran_ones(entity, quadrature[pt], ones_chi);
771
772
773 const typename QuadratureType::CoordinateType& x = quadrature.point(pt);
774 const double weight = quadrature.weight(pt) * geometry.integrationElement(x);
775
776
777 ones_chi *= weight;
778 wLocal.axpy(quadrature[pt], ones_chi, 0);
779
780 }
781 }
782 w.communicate();
783 }
784 }
785
786 #endif
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805