00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <assert.h>
00039 #include <math.h>
00040 #include <stdlib.h>
00041
00042 #include "phelm.h"
00043 #include "ver.h"
00044 #include "util.h"
00045 #include "solver.h"
00046
00047 VERSION("$Id: phelm.cpp,v 26667047d007 2009/06/29 06:57:20 aozeritsky $");
00048
00049 using namespace std;
00050
00051 namespace phelm {
00052
00053 bool Mesh::load(FILE * f)
00054 {
00055 int size;
00056 int lineno = 1;
00057
00058 #define _BUF_SZ 32768
00059 char s[_BUF_SZ];
00060
00061 fprintf(stderr, "loading mesh ... \n");
00062
00063 fgets (s, _BUF_SZ - 1, f); lineno++;
00064
00065
00066 do
00067 {
00068 if (*s != '#') {
00069 break;
00070 }
00071 lineno ++;
00072 }
00073 while (fgets(s, _BUF_SZ - 1, f));
00074
00075
00076 do
00077 {
00078 double x, y;
00079 const char * sep = ";";
00080 char * str;
00081
00082 if (*s == '#')
00083 break;
00084
00085 MeshPoint p;
00086
00087 for (str = strtok(s, sep); str; str = strtok(0, sep))
00088 {
00089 x = 0; y = 0;
00090 sscanf (str, "%lf%lf", &x, &y);
00091 p.add(Point(x, y));
00092 }
00093
00094 ps.push_back (p); lineno++;
00095 }
00096 while (fgets (s, _BUF_SZ - 1, f));
00097
00098 size = (int) ps.size();
00099
00100 ps_flags.resize(size);
00101 if (!fgets (s, _BUF_SZ - 1, f)) {
00102 goto bad;
00103 }
00104 lineno++;
00105
00106
00107 do
00108 {
00109 int n1, n2, n3, tid, z = 1;
00110
00111 if (*s == '#')
00112 break;
00113
00114 if (sscanf (s, "%d%d%d ; %d", &n1, &n2, &n3, &z) < 3)
00115 {
00116 goto bad;
00117 }
00118
00119
00120 --n1;
00121 --n2;
00122 --n3;
00123 --z;
00124 if (n1 >= size || n2 >= size || n3 >= size)
00125 {
00126 goto bad;
00127 }
00128
00129 if (n1 < 0 || n1 < 0 || n3 < 0) {
00130 goto bad;
00131 }
00132
00133 Triangle t(n1, n2, n3, z);
00134 tid = (int)tr.size();
00135 tr.push_back (t);
00136 if ((int)adj.size() <= n1) adj.resize(n1 + 1);
00137 if ((int)adj.size() <= n2) adj.resize(n2 + 1);
00138 if ((int)adj.size() <= n3) adj.resize(n3 + 1);
00139 adj[n1].push_back(tid);
00140 adj[n2].push_back(tid);
00141 adj[n3].push_back(tid); lineno++;
00142 }
00143 while (fgets (s, _BUF_SZ - 1, f) );
00144
00145 if (!fgets (s, _BUF_SZ - 1, f)) {
00146 goto make_inner;
00147 }
00148 lineno++;
00149
00150
00151 do
00152 {
00153 int n;
00154 if (*s == '#')
00155 break;
00156
00157 if (sscanf(s, "%d", &n) != 1) {
00158 goto bad;
00159 }
00160
00161 --n;
00162
00163 if (n >= size || n < 0) {
00164 goto bad;
00165 }
00166
00167 ps_flags[n] = 1; lineno++;
00168 }
00169 while (fgets (s, _BUF_SZ - 1, f) );
00170
00171 make_inner:
00172 fprintf(stderr, "done ... \n");
00173 fprintf(stderr, "preparing mesh ... \n");
00174 inner.reserve(ps.size());
00175 outer.reserve(ps.size());
00176 p2io.resize(ps.size());
00177
00178 for (uint i = 0; i < ps.size(); ++i) {
00179 if (ps_flags[i] == 0) {
00180 p2io[i] = (int)inner.size();
00181 inner.push_back(i);
00182 } else if (ps_flags[i] == 1) {
00183 p2io[i] = (int)outer.size();
00184 outer.push_back(i);
00185 }
00186 }
00187
00188 prepare();
00189 fprintf(stderr, "done ... \n");
00190
00191 return true;
00192
00193 bad:
00194 {
00195 fprintf(stderr, "bad file format, line = %d\n", lineno);
00196 return false;
00197 }
00198 }
00199
00200 void Mesh::prepare()
00201 {
00202 triangles_t::iterator it, b = tr.begin(), e = tr.end();
00203 for (it = b; it != e; ++it) {
00204 it->prepare(ps);
00205 }
00206 }
00207
00208 void Mesh::info()
00209 {
00210 fprintf(stderr, "points: %lu\n", ps.size());
00211 fprintf(stderr, "inner points: %lu\n", inner.size());
00212 fprintf(stderr, "outer points: %lu\n", outer.size());
00213 fprintf(stderr, "triangles: %lu\n", tr.size());
00214 }
00215
00216 void print_inner_function(FILE * to, double * ans, const Mesh & m,
00217 x_t x, x_t y, x_t z)
00218 {
00219 fprintf(to, "# points %lu\n", m.inner.size());
00220 for (uint i = 0; i < m.inner.size(); ++i) {
00221 int p = m.inner[i];
00222 double u = m.ps[p].x();
00223 double v = m.ps[p].y();
00224 double f = ans[p];
00225
00226 if (x) {
00227 fprintf(to, "%.16lf ", x(u, v));
00228 } else {
00229 fprintf(to, "%.16lf ", u);
00230 }
00231
00232 if (y) {
00233 fprintf(to, "%.16lf ", y(u, v));
00234 } else {
00235 fprintf(to, "%.16lf ", v);
00236 }
00237
00238 if (z) {
00239 fprintf(to, "%.16lf ", z(u, v));
00240 } else {
00241 fprintf(to, "%.16lf ", 0.0);
00242 }
00243
00244 fprintf(to, "%.16lf %.16lf %.16lf \n", f, u, v);
00245 }
00246
00247 fprintf(to, "# triangles %lu\n", m.tr.size());
00248 for (uint i = 0; i < m.tr.size(); ++i) {
00249 int p1 = m.tr[i].p[0];
00250 int p2 = m.tr[i].p[1];
00251 int p3 = m.tr[i].p[2];
00252
00253 if (m.ps_flags[p1] == 0
00254 && m.ps_flags[p2] == 0
00255 && m.ps_flags[p3] == 0)
00256 {
00257 fprintf(to, "%d %d %d\n",
00258 m.p2io[p1] + 1,
00259 m.p2io[p2] + 1,
00260 m.p2io[p3] + 1);
00261 }
00262 }
00263 fprintf(to, "# end \n");
00264 }
00265
00266 void print_inner_function(const char * to, double * ans, const Mesh & m,
00267 x_t x, x_t y, x_t z)
00268 {
00269 FILE * f = fopen(to, "wb");
00270 if (f) {
00271 print_inner_function(f, ans, m, x, y, z);
00272 fclose(f);
00273 }
00274 }
00275
00276 void print_function(FILE * to, double * ans, const Mesh & m,
00277 x_t x, x_t y, x_t z)
00278 {
00279 fprintf(to, "# points %lu\n", m.ps.size());
00280 for (uint i = 0; i < m.ps.size(); ++i) {
00281 double u = m.ps[i].x();
00282 double v = m.ps[i].y();
00283 double f = ans[i];
00284
00285 if (x) {
00286 fprintf(to, "%.16lf ", x(u, v));
00287 } else {
00288 fprintf(to, "%.16lf ", u);
00289 }
00290
00291 if (y) {
00292 fprintf(to, "%.16lf ", y(u, v));
00293 } else {
00294 fprintf(to, "%.16lf ", v);
00295 }
00296
00297 if (z) {
00298 fprintf(to, "%.16lf ", z(u, v));
00299 } else {
00300 fprintf(to, "%.16lf ", 0.0);
00301 }
00302
00303 fprintf(to, "%.16lf %.16lf %.16lf \n", f, u, v);
00304 }
00305
00306 fprintf(to, "# triangles %lu\n", m.tr.size());
00307 for (uint i = 0; i < m.tr.size(); ++i) {
00308 fprintf(to, "%d %d %d\n",
00309 m.tr[i].p[0] + 1,
00310 m.tr[i].p[1] + 1,
00311 m.tr[i].p[2] + 1);
00312 }
00313 fprintf(to, "# end \n");
00314 }
00315
00316 void print_function(const char * fname, double * ans, const Mesh & m,
00317 x_t x, x_t y, x_t z)
00318 {
00319 FILE * f = fopen(fname, "wb");
00320 if (f) {
00321 print_function(f, ans, m, x, y, z);
00322 fclose(f);
00323 }
00324 }
00325
00326 void solve(double * Ans, const double * bnd, double * b, Matrix & A, const Mesh & m)
00327 {
00328 int rs = (int)m.inner.size();
00329 vector < double > x(rs);
00330
00331 solve2(&x[0], b, A, m);
00332 p2u(Ans, &x[0], bnd, m);
00333 }
00334
00335 void solve2(double * Ans, double * b, Matrix & A, const Mesh & m)
00336 {
00337 int sz = (int)m.ps.size();
00338 int rs = (int)m.inner.size();
00339 vector < double > x(rs);
00340
00341 #ifdef _DEBUG
00342 Timer t;
00343 fprintf(stderr, "solve %dx%d: \n", rs, rs);
00344 #endif
00345 A.solve(Ans, &b[0]);
00346 #ifdef _DEBUG
00347 fprintf(stderr, "solve: %lf \n", t.elapsed());
00348 #endif
00349 }
00350
00351
00352 void p2u(double * u, const double * p, const double * bnd, const Mesh & m)
00353 {
00354 int sz = (int)m.ps.size();
00355
00356 #pragma omp parallel for
00357 for (int i = 0; i < sz; ++i) {
00358 if (m.ps_flags[i] == 1) {
00359
00360 if (bnd) {
00361 u[i] = bnd[m.p2io[i]];
00362 } else {
00363 u[i] = 0;
00364 }
00365 } else {
00366
00367 u[i] = p[m.p2io[i]];
00368 }
00369 }
00370 }
00371
00372
00373 void u2p(double * p, const double * u, const Mesh & m)
00374 {
00375 int j = 0;
00376 int rs = (int)m.inner.size();
00377 for (int i = 0; i < rs; ++i) {
00378 p[j++] = u[m.inner[i]];
00379 }
00380 }
00381
00382 void set_bnd(double *u, const double * bnd, const Mesh & m)
00383 {
00384 int sz = (int)m.ps.size();
00385 for (int i = 0; i < sz; ++i) {
00386 if (m.ps_flags[i] == 1) {
00387 if (bnd) {
00388 u[i] = bnd[m.p2io[i]];
00389 } else {
00390 u[i] = 0;
00391 }
00392 }
00393 }
00394 }
00395
00396 double generic_scalar_cb(const Polynom & phi_i, const Polynom & phi_j, const Triangle & trk, const Mesh & m, int, int, int, int, void * )
00397 {
00398 return integrate(phi_i * phi_j, trk, m.ps);
00399 }
00400
00401 double sphere_scalar_cb(const Polynom & phi_i, const Polynom & phi_j, const Triangle & trk, const Mesh & m, int, int, int, int, void * user_data)
00402 {
00403 return integrate_cos(phi_i * phi_j, trk, m.ps);
00404 }
00405
00406 double fast_scalar(const double * u, const double * v, const Mesh & m, Matrix & A)
00407 {
00408 int sz = (int)m.ps.size();
00409 vector < double > tmp(sz);
00410 A.mult_vector(&tmp[0], v);
00411 return vec_scalar2(u, &tmp[0], sz);
00412 }
00413
00414 double fast_norm(const double * u, const Mesh & m, Matrix & A)
00415 {
00416 return sqrt(fast_scalar(u, u, m, A));
00417 }
00418
00419 double fast_dist(const double * u, const double * v, const Mesh & m, Matrix & A)
00420 {
00421 int sz = (int)m.ps.size();
00422 vector < double > diff(sz);
00423 vec_diff(&diff[0], u, v, sz);
00424 return fast_norm(&diff[0], m, A);
00425 }
00426
00427 void proj(double * F, const Mesh & mesh, f_xy_t f)
00428 {
00429 size_t sz = mesh.ps.size();
00430 for (size_t i = 0; i < sz; ++i)
00431 {
00432 const Point & p = mesh.ps[i].p[0];
00433 F[i] = f(p.x, p.y);
00434 }
00435 }
00436
00437 void proj_bnd(double * F, const Mesh & m, f_xy_t f)
00438 {
00439 for (size_t i = 0; i < m.outer.size(); ++i) {
00440 int p0 = m.outer[i];
00441 const Point & p = m.ps[p0].p[0];
00442 F[i] = f(p.x, p.y);
00443 }
00444 }
00445
00446 void proj_bnd(double * F, const double * F1, const Mesh & m)
00447 {
00448 #pragma omp parallel for
00449 for (int i = 0; i < (int)m.outer.size(); ++i) {
00450 int p0 = m.outer[i];
00451 F[i] = F1[p0];
00452 }
00453 }
00454
00455 void proj(double * F, const Mesh & mesh, f_xyt_t f, double t)
00456 {
00457 for (size_t i = 0; i < mesh.ps.size(); ++i)
00458 {
00459 F[i] = f(mesh.ps[i].x(), mesh.ps[i].y(), t);
00460 }
00461 }
00462
00463 void proj_bnd(double * F, const Mesh & m, f_xyt_t f, double t)
00464 {
00465 for (size_t i = 0; i < m.outer.size(); ++i) {
00466 int p0 = m.outer[i];
00467 const Point & p = m.ps[p0].p[0];
00468 F[i] = f(p.x, p.y, t);
00469 }
00470 }
00471
00472 }
00473