2
/// This file is part of Rheolef.
4
/// Copyright (C) 2000-2009 Pierre Saramito <Pierre.Saramito@imag.fr>
6
/// Rheolef is free software; you can redistribute it and/or modify
7
/// it under the terms of the GNU General Public License as published by
8
/// the Free Software Foundation; either version 2 of the License, or
9
/// (at your option) any later version.
11
/// Rheolef is distributed in the hope that it will be useful,
12
/// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
/// GNU General Public License for more details.
16
/// You should have received a copy of the GNU General Public License
17
/// along with Rheolef; if not, write to the Free Software
18
/// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
/// =========================================================================
23
// \int_\Omega weight(x) dx = mes(\Omega) with weight
25
// check value on the unit ball C(0,1) in IR^d
27
#include "rheolef/rheolef.h"
28
using namespace rheolef;
33
= int_Omega x^m y^n dx
34
= (int_{r=0}^1 r^{m+n+1} dr)*(int_0^{2*pi} cos(theta)^m sin(theta)^n d theta)
36
int_{r=0}^1 r^{m+n+1} dr = 1/(m+n+2)
37
=> I_{m,n} = J_{m,n}/(m+n+2)
38
J_{m,n} = int_0^{2*pi} cos(theta)^m sin(theta)^n d theta
39
cf Bro-1985, p. 557 & 561 : recurrence
40
J_{m,n} = 0 si m ou n impair
41
J_{2p,2q} = (2q-1)/(2p+2q)*J_{2p,2q-2}
42
J_{2p,0} = (2p-1)/(2p)*J_{2p-2,0}
45
=> J_{2p,0} = ------------ * (2*pi) pour q = 0
48
=> J_{2p,2q} = -------------------------- pour q >=1
49
4^(p+q-1) p! (q-1)! (p+q)!
51
Float factorial (size_t n)
54
for (size_t i = 1; i <= n; i++) res *= i;
58
integrate_2d_mass_xy (size_t nx, size_t ny, bool is_boundary)
60
static Float pi = acos(-1.0);
61
if ((nx % 2 == 1) || (ny % 2 == 1)) return 0;
66
value = 2*pi*factorial(2*p)/sqr(pow(2.0,p)*factorial(p));
68
value = pi*factorial(2*p)*factorial(2*q-1)/(pow(4.0,p+q-1)*factorial(p)*factorial(q-1)*factorial(p+q));
70
if (!is_boundary) value = value/(nx+ny+2); // integrate also in r : interior of the circle
73
// handle also grad_grad form:
75
integrate_xy (size_t d, string name, size_t nx, size_t ny, size_t mx, size_t my, bool is_boundary)
77
if (d == 2) { // circle
78
if (name == "mass") return integrate_2d_mass_xy (nx+mx, ny+my, is_boundary);
79
check_macro (name == "grad_grad", "unexpected form `"<<name<<"'");
80
if (is_boundary) return 0;
81
// here: form="grad_grad" on a filled circle
83
if (nx+mx >= 2) value += nx*mx*integrate_2d_mass_xy (nx+mx-2, ny+my, is_boundary);
84
if (ny+my >= 2) value += ny*my*integrate_2d_mass_xy (nx+mx, ny+my-2, is_boundary);
86
} else { // sphere: only mass and nx=ny=0 yet
87
check_macro (name == "mass", "form `"<<name<<"' not yet");
88
check_macro (nx + ny + mx + my == 0, "non null nx etc: not yet");
89
static Float pi = acos(-1.0);
96
derr << "usage: form_mass_circle_tst"
99
<< " [-form name=mass]"
109
<< "example:" << endl
110
<< " mkgeo_ball -order 3 -t 10 > ball.geo" << endl
111
<< " form_mass_circle_tst ball -app P3 -nx 3" << endl;
114
struct weight : std::unary_function<point,Float> {
115
Float operator() (const point& x) const {
116
if (nx == 0 && ny == 0) return 1;
118
if (nx % 2 == 0) factx = pow(fabs(x[0]),nx);
119
else factx = x[0]*pow(fabs(x[0]),nx-1);
120
if (ny % 2 == 0) facty = pow(fabs(x[1]),ny);
121
else facty = x[1]*pow(fabs(x[1]),ny-1);
124
weight(size_t nx1=0, size_t ny1=0) : nx(nx1), ny(ny1) {}
127
int main(int argc, char**argv)
130
// load geometry and options
132
environment rheolef (argc,argv);
134
string form_name = "mass";
135
string approx1 = "P1";
143
bool mesh_done = false;
146
if (argc <= 1) usage() ;
148
for (int i = 1; i < argc; i++ ) {
150
if (argv [i][0] == '-' && argv [i][1] == 'I') { append_dir_to_rheo_path (argv[i]+2) ; }
151
else if (strcmp(argv[i], "-form") == 0) { form_name = argv[++i]; }
152
else if (strcmp(argv[i], "-app") == 0) { approx1 = argv[++i]; }
153
else if (strcmp(argv[i], "-tol") == 0) { tol = atof(argv[++i]); }
154
else if (strcmp(argv[i], "-nx") == 0) { nx = atoi(argv[++i]); }
155
else if (strcmp(argv[i], "-ny") == 0) { ny = atoi(argv[++i]); }
156
else if (strcmp(argv[i], "-nz") == 0) { nz = atoi(argv[++i]); }
157
else if (strcmp(argv[i], "-mx") == 0) { mx = atoi(argv[++i]); }
158
else if (strcmp(argv[i], "-my") == 0) { my = atoi(argv[++i]); }
159
else if (strcmp(argv[i], "-mz") == 0) { mz = atoi(argv[++i]); }
160
else if (strcmp(argv[i], "-") == 0) {
161
// input geo on standard input
162
if (mesh_done) usage() ;
163
derr << "! load geo on stdin" << endl ;
168
if (mesh_done) usage() ;
169
//derr << "! load " << argv[i] << endl ;
170
omega = geo(argv[i]);
174
warning_macro ("form = " << form_name);
175
warning_macro ("nx = " << nx);
176
warning_macro ("ny = " << ny);
177
warning_macro ("mx = " << mx);
178
warning_macro ("my = " << my);
179
if (!mesh_done) usage() ;
183
space V1(omega, approx1);
184
space V2(omega, approx2);
185
field w1h = interpolate (V1, weight(nx,ny));
186
field w2h = interpolate (V2, weight(mx,my));
187
form a(V1,V2,form_name);
189
odiststream out; out.open("a","mm"); out << a.uu;
190
odiststream zzz; zzz.open("w1h","field"); zzz << w1h;
191
form mass(V1,V2,"mass");
194
aw1h.u = sm.solve ((a*w1h).u);
195
aw1h["boundary"] = -2;
196
odiststream yyy; yyy.open("aw1h","field"); yyy << aw1h;
198
Float mes_omega = a(w1h, w2h);
199
dout << setprecision(numeric_limits<Float>::digits10)
200
<< "mes(omega," << approx1 << "," << approx2 << ") = " << double(mes_omega) << endl;
203
bool is_boundary = (omega.dimension() > omega.map_dimension());
204
Float expect = integrate_xy (omega.dimension(),form_name,nx, ny, mx, my, is_boundary);
205
dout << "exact = " << expect << endl
206
<< "error = " << fabs(mes_omega - expect) << endl;