~ubuntu-branches/ubuntu/raring/rheolef/raring-proposed

« back to all changes in this revision

Viewing changes to nfem/ptst/form_mass_bdr_tst.cc

  • Committer: Bazaar Package Importer
  • Author(s): Pierre Saramito
  • Date: 2011-03-23 11:14:26 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20110323111426-cjvhey7lxt6077ty
Tags: 5.93-1
* New upstream release (minor changes):
  - some extra warning message deleted in heap_allocator
  - graphic output with mayavi2 fixed
  - add doc refman in .info and .pdf format

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
///
 
2
/// This file is part of Rheolef.
 
3
///
 
4
/// Copyright (C) 2000-2009 Pierre Saramito <Pierre.Saramito@imag.fr>
 
5
///
 
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.
 
10
///
 
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.
 
15
///
 
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
 
19
///
 
20
/// =========================================================================
 
21
//
 
22
// check:
 
23
//  \int_\Gamma weight(x) dx = mes(\Gamma) with weight
 
24
//
 
25
// where Gamma is a boundary of the [0,1]^d cube
 
26
// 
 
27
// example:
 
28
//   form_mass_bdr_tst -app P1 -weight 0 -I../data carre-v2 left
 
29
//
 
30
#include "rheolef/rheolef.h"
 
31
using namespace rheolef;
 
32
using namespace std;
 
33
 
 
34
typedef Float (*function_type)(const point&);
 
35
 
 
36
Float weight_1  (const point& x) { return 1; }
 
37
Float weight_x  (const point& x) { return x[0]; }
 
38
Float weight_y  (const point& x) { return x[1]; }
 
39
Float weight_z  (const point& x) { return x[2]; }
 
40
Float weight_x2 (const point& x) { return x[0]*x[0]; }
 
41
Float weight_xy (const point& x) { return x[0]*x[1]; }
 
42
Float weight_y2 (const point& x) { return x[1]*x[1]; }
 
43
Float weight_xz (const point& x) { return x[0]*x[2]; }
 
44
Float weight_yz (const point& x) { return x[1]*x[2]; }
 
45
Float weight_z2 (const point& x) { return x[2]*x[2]; }
 
46
 
 
47
const char * domain_name [6] = {
 
48
        "left",         // y=0, xz varies
 
49
        "back",         // x=0, yz varies (3d)
 
50
        "bottom",       // z=0, xy varies
 
51
 
 
52
        "right",        // y=1, xz varies
 
53
        "front",        // x=1, yz varies (3d)
 
54
        "top",          // z=1, xy varies
 
55
};
 
56
size_t
 
57
domain_index (const string& name)
 
58
{
 
59
    for  (size_t i = 0; i < 6; i++)
 
60
        if (domain_name[i] == name) return i;
 
61
    error_macro ("unexpected domain name `" << name << "'");
 
62
    return 6;
 
63
}
 
64
struct list_type {
 
65
        string name;
 
66
        function_type function;
 
67
        Float  expect [6];
 
68
};
 
69
typedef Float T;
 
70
 
 
71
//
 
72
// 2d cartesian case
 
73
//
 
74
list_type weight_list_2d[]={
 
75
 
 
76
                // left      back    bottom  right      front       top
 
77
                // x=0        -      y=0     x=1         -          y=1
 
78
                // dy         -      dx      dy          -          dx 
 
79
 
 
80
 {"1", weight_1,  {1,        -1,     1,      1,         -1,         1     } },
 
81
 {"x", weight_x,  {0,        -1,     0.5,    1,         -1,         0.5   } },
 
82
 {"x2",weight_x2, {0,        -1,     T(1)/3, 1,         -1,         T(1)/3} },
 
83
 {"y", weight_y,  {0.5,      -1,     0,      0.5,       -1,         1     } },
 
84
 {"xy",weight_xy, {0,        -1,     0,      0.5,       -1,         0.5   } },
 
85
 {"y2",weight_y2, {T(1)/3,   -1,     0,      T(1)/3,    -1,         1     } }
 
86
};
 
87
const size_t max_weight_2d = sizeof(weight_list_2d)/sizeof(list_type);
 
88
//
 
89
// 3d cartesian case
 
90
//
 
91
list_type weight_list_3d[]={
 
92
 
 
93
                // left      back    bottom     right     front     top
 
94
                // y=0       x=0     z=0        y=1       x=1       z=1
 
95
                // dx.dz     dy.dz   dx.dy      dx.dz     dy.dz     dx.dy
 
96
 
 
97
 {"1", weight_1,  {1,        1,      1,         1,        1,        1     } },
 
98
 {"x", weight_x,  {0.5,      0,      0.5,       0.5,      1,        0.5   } },
 
99
 {"x2",weight_x2, {T(1)/3,   0,      T(1)/3,    T(1)/3,   1,        T(1)/3} },
 
100
 {"y", weight_y,  {0,        0.5,    0.5,       1,        0.5,      0.5   } },
 
101
 {"xy",weight_xy, {0,        0,      0.25,      0.5,      0.5,      0.25  } },
 
102
 {"y2",weight_y2, {0,        T(1)/3, T(1)/3,    1,        T(1)/3,   T(1)/3} },
 
103
 {"z", weight_z,  {0.5,      0.5,    0,         0.5,      0.5,      1     } },
 
104
 {"xz",weight_xz, {0.25,     0,      0,         0.25,     0.5,      0.5   } },
 
105
 {"yz",weight_yz, {0,        0.25,   0,         0.5,      0.25,     0.5   } },  
 
106
 {"z2",weight_z2, {T(1)/3,   T(1)/3, 0,         T(1)/3,   T(1)/3,   1     } }
 
107
};
 
108
const size_t max_weight_3d = sizeof(weight_list_3d)/sizeof(list_type);
 
109
//
 
110
// axisymmetric case: TODO recompute the good values because of swap columns
 
111
//
 
112
list_type weight_list_rz []={
 
113
 
 
114
                // left     back     bottom     right     front     top
 
115
                // y=0      x=0      z=0        y=1       x=1       z=1
 
116
                // x.dx     0        -          x.dx      dy        -
 
117
 
 
118
 {"1", weight_1,  {0.5,      0,      -1,        0.5,      1,        -1     } },
 
119
 {"x", weight_x,  {T(1)/3,   0,      -1,        T(1)/3,   1,        -1     } },
 
120
 {"x2",weight_x2, {0.25,     0,      -1,        0.25,     1,        -1     } },
 
121
 {"y", weight_y,  {0,        0,      -1,        0.5,      0.5,      -1     } },
 
122
 {"xy",weight_xy, {0,        0,      -1,        T(1)/3,   0.5,      -1     } },
 
123
 {"y2",weight_y2, {0,        0,      -1,        0.5,      T(1)/3,   -1     } }
 
124
};
 
125
const size_t max_weight_rz = sizeof(weight_list_rz)/sizeof(list_type);
 
126
 
 
127
size_t
 
128
weight_index (size_t dim, const string& name, const string& coord_sys)
 
129
{
 
130
  if (coord_sys == "cartesian" && dim == 3) {
 
131
 
 
132
    for  (size_t i = 0; i < max_weight_3d; i++)
 
133
        if (weight_list_3d[i].name == name) return i;
 
134
    error_macro ("unexpected 3d weight `" << name << "'");
 
135
    return max_weight_3d;
 
136
 
 
137
  } else if (coord_sys == "cartesian" && dim == 2) {
 
138
 
 
139
    for  (size_t i = 0; i < max_weight_2d; i++)
 
140
        if (weight_list_2d[i].name == name) return i;
 
141
    error_macro ("unexpected 2d weight `" << name << "'");
 
142
    return max_weight_2d;
 
143
 
 
144
  } else { // axisymmetric rz
 
145
 
 
146
    for  (size_t i = 0; i < max_weight_rz; i++)
 
147
        if (weight_list_rz[i].name == name) return i;
 
148
    error_macro ("unexpected weight `" << name << "' in axisymmetric system");
 
149
    return max_weight_rz;
 
150
  }
 
151
}
 
152
function_type
 
153
get_function (size_t dim, string weight, string coord_sys)
 
154
{
 
155
  size_t weight_idx = weight_index (dim, weight, coord_sys);
 
156
  if (coord_sys == "cartesian" && dim == 3) {
 
157
    return weight_list_3d [weight_idx].function;
 
158
  } else if (coord_sys == "cartesian" && dim == 2) {
 
159
    return weight_list_2d [weight_idx].function;
 
160
  } else {
 
161
    return weight_list_rz [weight_idx].function;
 
162
  }
 
163
}
 
164
Float
 
165
get_expected_value (size_t dim, string weight, string domain_name, string coord_sys)
 
166
{
 
167
  size_t weight_idx = weight_index (dim, weight, coord_sys);
 
168
  size_t domain_idx = domain_index (domain_name);
 
169
  if (coord_sys == "cartesian" && dim == 3) {
 
170
    return weight_list_3d [weight_idx].expect [domain_idx];
 
171
  } else if (coord_sys == "cartesian" && dim == 2) {
 
172
    return weight_list_2d [weight_idx].expect [domain_idx];
 
173
  } else {
 
174
    return weight_list_rz [weight_idx].expect [domain_idx];
 
175
  }
 
176
}
 
177
#ifdef TODO
 
178
bool
 
179
is_on_axis (const space& W)
 
180
{
 
181
    const point& xmin = W.get_geo().xmin();
 
182
    const point& xmax = W.get_geo().xmax();
 
183
    return (xmin[0] == Float(0) && xmax[0] == Float(0));
 
184
}
 
185
#endif // TODO
 
186
 
 
187
void usage()
 
188
{
 
189
      dcerr << "form_mass_bdr_tst: usage: form_mass_bdr_tst"
 
190
            << " -app string"
 
191
            << " {-Igeodir}*"
 
192
            << " -|mesh[.geo]"
 
193
            << " {domain}+"
 
194
            << " [-weight string]"
 
195
            << " [-rz]"
 
196
            << endl
 
197
            << "example:" << endl
 
198
            << "  form_mass_bdr_tst -app P1 -I../data carre top -weight x" << endl;
 
199
      exit (1);
 
200
}
 
201
int main(int argc, char**argv)
 
202
{
 
203
    environment distributed (argc, argv);
 
204
    typedef geo::size_type size_type;
 
205
    Float epsilon = 1e-15;
 
206
    //
 
207
    // load geometry and options
 
208
    //
 
209
    geo omega;
 
210
    string approx = "P1";
 
211
    string weight = "1";
 
212
    bool mesh_done = false;
 
213
    geo::size_type n_dom = 0;
 
214
    string dom_name;
 
215
    string coord_sys = "cartesian";
 
216
    int status = 0;
 
217
 
 
218
    if (argc <= 1) usage() ;
 
219
    dcerr << noverbose;
 
220
 
 
221
    for (int i=1 ; i < argc ; i++) {
 
222
 
 
223
      if (argv [i][0] == '-' && argv [i][1] == 'I')
 
224
        append_dir_to_rheo_path (argv[i]+2) ;
 
225
      else if (strcmp(argv[i], "-app") == 0)    approx = argv[++i];
 
226
      else if (strcmp(argv[i], "-weight") == 0) weight = argv[++i];
 
227
      else if (strcmp(argv[i], "-rz") == 0)     coord_sys = "rz";
 
228
      else if (strcmp(argv[i], "-") == 0) {
 
229
 
 
230
          // input geo on standard input
 
231
          if (mesh_done) usage() ;
 
232
          dcerr << " ! mass: read geo on stdin" << endl ;
 
233
          dcin >> omega ;
 
234
          mesh_done = true ;
 
235
 
 
236
      } else if (!mesh_done) {
 
237
 
 
238
          // input geo on file
 
239
          omega = geo(argv[i]);
 
240
          mesh_done = true ;
 
241
 
 
242
      } else {
 
243
 
 
244
          // a domain
 
245
          dom_name = argv[i];
 
246
      }
 
247
    }
 
248
warning_macro ("main [1]");
 
249
    if (!mesh_done) {
 
250
      warning_macro("no mesh specified.");
 
251
      usage();
 
252
    }
 
253
    if (weight == "") {
 
254
      warning_macro("no weight specified");
 
255
      usage();
 
256
    }
 
257
    if (dom_name == "") {
 
258
      warning_macro("no boundary domain specified");
 
259
      usage();
 
260
    }
 
261
    size_t dim = omega.dimension();
 
262
warning_macro ("main [2]");
 
263
#ifdef TODO
 
264
    omega.set_coordinate_system(coord_sys);
 
265
#endif // TODO
 
266
    //
 
267
    // build boundary domain
 
268
    //
 
269
warning_macro ("main [3]");
 
270
    domain gamma(omega[dom_name]) ;
 
271
    //
 
272
    // build space
 
273
    //
 
274
warning_macro ("main [4]");
 
275
    space V(omega, approx);
 
276
    space W(gamma, approx);
 
277
    //
 
278
    // build field on V
 
279
    //
 
280
warning_macro ("main [5]");
 
281
    field one(V,1);
 
282
#ifdef TODO   
 
283
    string sys_coord = omega.coordinate_system();
 
284
#endif // TODO   
 
285
    string sys_coord = "cartesian";
 
286
    function_type weight_fct = get_function(dim,weight, sys_coord);
 
287
    field weight_h = interpolate(V,weight_fct);
 
288
    //
 
289
    // build forms
 
290
    //
 
291
warning_macro ("main [6]");
 
292
    form  m_h (V, V, "mass", gamma) ;
 
293
    // ---------------------------------------------------
 
294
    // first check : compute boundary area with i-th weight
 
295
    // ---------------------------------------------------
 
296
warning_macro ("main [7]");
 
297
    Float mes_gamma_1 = dot(one, m_h*weight_h);
 
298
    cout << "mes1(gamma) = " << double(mes_gamma_1) << endl;
 
299
    // ---------------------------------------------------
 
300
    // 2nd check : use trace
 
301
    // ---------------------------------------------------
 
302
#ifdef TODO
 
303
    bool axi_and_on_axis = (coord_sys == "rz" && is_on_axis(W));
 
304
#endif // TODO
 
305
    bool axi_and_on_axis = false;
 
306
    if (!axi_and_on_axis) {
 
307
        //
 
308
        // build field on W
 
309
        // 
 
310
warning_macro ("main [8]");
 
311
        field weight_bdr_bug = interpolate(W,weight_fct);
 
312
        //
 
313
        // build form on W
 
314
        //
 
315
warning_macro ("main [9]");
 
316
        form  m_gamma_h (W, W, "mass") ;
 
317
warning_macro ("main [9a]");
 
318
        form  m_trace_h (V, W, "mass") ;
 
319
        //
 
320
        // deduce field on W by solving
 
321
        //   m_gamma_h*weight_bdr = m_trace_h*weight_h
 
322
        //
 
323
warning_macro ("main [10]");
 
324
        field one_bdr (W, 1.);
 
325
        field weight_bdr(W);
 
326
        solver sa (m_gamma_h.uu);
 
327
        weight_bdr.b = 0;
 
328
        weight_bdr.u = sa.solve(m_trace_h.uu*weight_h.u 
 
329
            + m_trace_h.ub*weight_h.b - m_gamma_h.ub*weight_bdr.b);
 
330
        //
 
331
        // compute boundary area with i-th weight
 
332
        //
 
333
warning_macro ("main [11]");
 
334
        Float mes_gamma_2 = dot(one_bdr, m_gamma_h*weight_bdr);
 
335
        cout << "mes2(gamma) = " << double(mes_gamma_2) << endl;
 
336
        // ---------------------------------------------------
 
337
        // 3nd check : compare two results
 
338
        // ---------------------------------------------------
 
339
warning_macro ("main [12]");
 
340
        if (fabs(mes_gamma_1-mes_gamma_2) > sqrt(epsilon)) {
 
341
          dcerr << "boundary mass problem detected." << endl;
 
342
          status = 1;
 
343
        }
 
344
    }
 
345
    // ---------------------------------------------------
 
346
    // 4th check : compare with exact data
 
347
    // ---------------------------------------------------
 
348
warning_macro ("main [13]");
 
349
    Float expect = get_expected_value (dim, weight, dom_name, coord_sys);
 
350
    cout << "exact       = " << expect << endl;
 
351
    if (fabs(mes_gamma_1-expect) <= sqrt(epsilon)) {
 
352
        dcerr << "ok" << endl;
 
353
    } else {
 
354
        dcerr << "error = " << mes_gamma_1-expect << endl;
 
355
        status = 1;
 
356
    }
 
357
warning_macro ("main [14]");
 
358
 
 
359
#ifdef TO_CLEAN
 
360
    cout << ml
 
361
         << "weight   = " << weight_h.u << ";" << endl
 
362
         << "one_bdr  = " << one_bdr.u << ";" << endl
 
363
         << "m_bdr    = " << m_gamma_h.uu << ";" << endl
 
364
         << "m_trace  = " << m_trace_h.uu << ";" << endl
 
365
         << "weight_bdr  = " << weight_bdr.u << ";" << endl
 
366
        ;
 
367
#endif // TO_CLEAN
 
368
 
 
369
    return status;
 
370
}