1
#include "dirichlet.icc"
2
#include "not_too_small.h"
3
p_laplacian::p_laplacian(Float p1, const geo& omega_h, string approx1)
4
: p(p1), Xh(), Kh(), fh(),
5
m(), inv_mt(), grad(), sm(), a1(), sa1() {
6
reset(omega_h, approx1);
8
void p_laplacian::reset(const geo& omega_h1, string approx1) {
9
if (approx1 == "previous") approx1 = Xh.get_approx();
10
Xh = space(omega_h1, approx1);
11
Xh.block ("boundary");
13
m = form (Xh, Xh, "mass");
15
string grad_approx = "P" + itos(Xh.degree()-1) + "d";
16
space Th (fh.get_geo(), grad_approx, "vector");
17
inv_mt = form (Th, Th, "inv_mass");
18
grad = form (Xh, Th, "grad");
19
Kh = space(fh.get_geo(), grad_approx, "tensor");
21
field p_laplacian::initial () const {
23
uh [Xh.get_geo()["boundary"]] = 0;
27
void p_laplacian::update_derivative (const field& uh) const {
28
field grad_uh = inv_mt*(grad*uh);
29
field norm2_grad_uh = norm2(grad_uh);
30
if (p/2 - 4 <= 0) norm2_grad_uh = compose (not_too_small(1e-10), norm2_grad_uh);
31
field w0h = pow(norm2_grad_uh, p/2)/norm2_grad_uh;
32
field w1h = pow(norm2_grad_uh, p/2)/sqr(norm2_grad_uh);
34
eta_h(0,0) = w0h + (p-2)*w1h*sqr(grad_uh[0]);
35
size_t d = uh.get_geo().dimension();
37
eta_h(1,1) = w0h + (p-2)*w1h*sqr(grad_uh[1]);
38
eta_h(0,1) = (p-2)*w1h*grad_uh[0]*grad_uh[1];
41
eta_h(2,2) = w0h + (p-2)*w1h*sqr(grad_uh[2]);
42
eta_h(1,2) = (p-2)*w1h*grad_uh[1]*grad_uh[2];
43
eta_h(0,2) = (p-2)*w1h*grad_uh[0]*grad_uh[2];
45
a1 = form (Xh, Xh, "grad_grad", eta_h);
46
sa1 = solver(a1.uu());
48
field p_laplacian::residue (const field& uh) const {
49
field grad_uh = inv_mt*(grad*uh);
50
field norm2_grad_uh = norm2(grad_uh);
51
field w0h = pow(norm2_grad_uh, p/2-1);
52
form a (Xh, Xh, "grad_grad", w0h);
53
field mrh = a*uh - m*fh;
57
field p_laplacian::derivative_solve (const field& mrh) const {
58
field delta_uh (Xh,0);
60
delta_uh.set_u() = sa1.solve(mrh.u());