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
00048 #include "solver.h"
00049 #include "util.h"
00050
00051 namespace phelm {
00052
00065 struct Element {
00066 int i;
00067 int j;
00068 double a;
00069
00076 Element(int i1, int j1, double a1) : i(i1), j(j1), a(a1) {}
00077 };
00078
00085 typedef std::vector < Element > elements_t;
00086
00087 #include "phelm_private.h"
00088
00115 template < typename Functor, typename Data >
00116 void generate_matrix(Matrix & A, const Mesh & m,
00117 Functor integrate_cb,
00118 Data user_data,
00119 bool transpose = false)
00120 {
00121 using namespace phelm_private_;
00122 int rs = (int)m.inner.size();
00123
00124 Timer t;
00125 #pragma omp parallel for
00126 for (int i = 0; i < rs; ++i) {
00127
00128 int p = m.inner[i];
00129
00130 for (uint tk = 0; tk < m.adj[p].size(); ++tk)
00131 {
00132
00133 int trk_i = m.adj[p][tk];
00134 const Triangle & trk = m.tr[trk_i];
00135 const std::vector < Polynom > & phik = trk.elem1();
00136 const Polynom & phi_i = trk.elem1(p);
00137
00138 for (uint i0 = 0; i0 < phik.size(); ++i0) {
00139 int p2 = m.tr[trk_i].p[i0];
00140 int j = m.p2io[p2];
00141
00142 if (m.ps_flags[p2] == 1) {
00143 ;
00144 } else {
00145 mat_add(A, i, j,
00146 integrate_cb(phi_i, phik[i0], trk,
00147 m, p, p2, i, j, user_data), transpose);
00148 }
00149 }
00150 }
00151 }
00152 #ifdef _DEBUG
00153 fprintf(stderr, "generate_matrix: %lf \n", t.elapsed());
00154 #endif
00155 }
00156
00166 template < typename Functor, typename Data >
00167 void generate_full_matrix(Matrix & A, const Mesh & m,
00168 Functor integrate_cb,
00169 Data user_data,
00170 bool transpose = false)
00171 {
00172 using namespace phelm_private_;
00173 int sz = (int)m.ps.size();
00174
00175 Timer t;
00176
00177 for (int p = 0; p < sz; ++p) {
00178 for (uint tk = 0; tk < m.adj[p].size(); ++tk) {
00179
00180 int trk_i = m.adj[p][tk];
00181 const Triangle & trk = m.tr[trk_i];
00182 const std::vector < Polynom > & phik = trk.elem1();
00183 const Polynom & phi_i = trk.elem1(p);
00184
00185 for (uint i0 = 0; i0 < phik.size(); ++i0) {
00186 int p2 = m.tr[trk_i].p[i0];
00187 mat_add(A, p, p2,
00188 integrate_cb(phi_i, phik[i0], trk, m,
00189 p, p2, p, p2, user_data), transpose);
00190 }
00191 }
00192 }
00193 #ifdef _DEBUG
00194 fprintf(stderr, "generate_full_matrix: %lf \n", t.elapsed());
00195 #endif
00196 }
00197
00206 template < typename Functor, typename Data >
00207 void generate_right_part(double * b, const Mesh & m,
00208 Functor right_part_cb,
00209 Data user_data)
00210 {
00211 using namespace phelm_private_;
00212 int rs = (int)m.inner.size();
00213 Timer t;
00214
00215
00216
00217
00218
00219 #pragma omp parallel for
00220 for (int i = 0; i < rs; ++i)
00221 {
00222
00223 int p = m.inner[i];
00224 b[i] = 0.0;
00225
00226 for (uint tk = 0; tk < m.adj[p].size(); ++tk) {
00227
00228 int trk_i = m.adj[p][tk];
00229 const Triangle & trk = m.tr[trk_i];
00230 const std::vector < Polynom > & phik = trk.elem1();
00231 const Polynom & phi_i = trk.elem1(p);
00232
00233
00234
00235
00236 for (uint i0 = 0; i0 < phik.size(); ++i0) {
00237 int p2 = m.tr[trk_i].p[i0];
00238 vec_add(b, i,
00239 right_part_cb(phi_i, phik[i0],
00240 trk, m, p, p2, i, m.p2io[p2], user_data));
00241 }
00242 }
00243 }
00244 #ifdef _DEBUG
00245 fprintf(stderr, "generate_right_part: %lf \n", t.elapsed());
00246 #endif
00247 }
00248
00257 template < typename Functor, typename Data >
00258 void generate_full_right_part(double * b, const Mesh & m,
00259 Functor right_part_cb,
00260 Data user_data)
00261 {
00262 using namespace phelm_private_;
00263 int sz = (int)m.ps.size();
00264
00265 Timer t;
00266
00267
00268
00269
00270
00271 #pragma omp parallel for
00272 for (int p = 0; p < sz; ++p)
00273 {
00274 b[p] = 0.0;
00275
00276 for (uint tk = 0; tk < m.adj[p].size(); ++tk) {
00277
00278 int trk_i = m.adj[p][tk];
00279 const Triangle & trk = m.tr[trk_i];
00280 const std::vector < Polynom > & phik = trk.elem1();
00281 const Polynom & phi_i = trk.elem1(p);
00282
00283
00284
00285
00286 for (uint i0 = 0; i0 < phik.size(); ++i0) {
00287 int p2 = m.tr[trk_i].p[i0];
00288 vec_add(b, p,
00289 right_part_cb(phi_i, phik[i0],
00290 trk, m, p, p2, p, p2, user_data));
00291 }
00292 }
00293 }
00294 #ifdef _DEBUG
00295 fprintf(stderr, "generate_right_part: %lf \n", t.elapsed());
00296 #endif
00297 }
00298
00310 template < typename Functor, typename Data >
00311 void generate_boundary_matrix(Matrix & A, const Mesh & m,
00312 Functor right_part_cb,
00313 Data user_data,
00314 bool transpose = false)
00315 {
00316 using namespace phelm_private_;
00317 int os = (int)m.outer.size();
00318 for (int j = 0; j < os; ++j) {
00319
00320 int p2 = m.outer[j];
00321
00322 for (uint tk = 0; tk < m.adj[p2].size(); ++tk) {
00323
00324 int trk_j = m.adj[p2][tk];
00325 const Triangle & trk = m.tr[trk_j];
00326 const std::vector < Polynom > & phik = trk.elem1();
00327 const Polynom & phi_j = trk.elem1(p2);
00328
00329 for (uint i0 = 0; i0 < phik.size(); ++i0) {
00330 int p = m.tr[trk_j].p[i0];
00331
00332 if (m.ps_flags[p] == 1) {
00333 ;
00334 } else {
00335
00336 int i = m.p2io[p];
00337 mat_add(A, i, j,
00338 right_part_cb(phik[i0], phi_j,
00339 trk, m, p, p2, i, j, user_data), transpose);
00340 }
00341 }
00342 }
00343 }
00344 }
00345
00356 template < typename Functor, typename Data >
00357 void convolution(double * ans, const double * u, const double * v,
00358 const Mesh & m, Functor cb, Data user_data)
00359 {
00360 using namespace phelm_private_;
00361
00362 int sz = (int)m.ps.size();
00363
00364
00365 for (int i = 0; i < sz; ++i)
00366 {
00367
00368 int p = i;
00369 ans[i] = 0.0;
00370
00371 for (uint tk = 0; tk < m.adj[p].size(); ++tk) {
00372
00373 int trk_i = m.adj[p][tk];
00374 const Triangle & trk = m.tr[trk_i];
00375 const std::vector < Polynom > & phik = trk.elem1();
00376 const Polynom & phi_i = trk.elem1(p);
00377
00378 for (uint i0 = 0; i0 < phik.size(); ++i0) {
00379 int j = trk.p[i0];
00380 ans[i] += u[i] * v[j] *
00381 cb(phi_i, phik[i0], trk, m, i, j, i, j, user_data);
00382
00383 }
00384 }
00385 }
00386 }
00387
00389
00405 template < typename Functor, typename Data >
00406 double scalar(const double * u, const double * v, const Mesh & m,
00407 Functor cb, Data user_data)
00408 {
00409 int sz = (int)m.ps.size();
00410 double s = 0.0;
00411 std::vector < double > nr(sz);
00412 convolution(&nr[0], u, v, m, cb, user_data);
00413
00414 for (int i = 0; i < sz; ++i) {
00415 s = s + nr[i];
00416 }
00417 return s;
00418 }
00419
00428 template < typename Functor, typename Data >
00429 void generate_scalar_matrix(Matrix & mat, const Mesh & m,
00430 Functor cb, Data user_data)
00431 {
00432 generate_full_matrix(mat, m, cb, user_data);
00433 }
00434
00444 template < typename Functor, typename Data >
00445 double norm(const double * u, const Mesh & m,
00446 Functor cb, Data user_data)
00447 {
00448 return sqrt(scalar(u, u, m, cb, user_data));
00449 }
00450
00457 inline double norm(const double * u, const Mesh & m)
00458 {
00459 return norm(u, m, generic_scalar_cb, (void*)0);
00460 }
00461
00472 template < typename Functor, typename Data>
00473 double dist(const double * u, const double * v, const Mesh & m,
00474 Functor cb, Data user_data)
00475 {
00476 int sz = (int)m.ps.size();
00477 std::vector < double > diff(sz);
00478 vec_diff(&diff[0], u, v, sz);
00479 return norm(&diff[0], m, cb, user_data);
00480 }
00481
00489 inline double dist(const double * u, const double * v, const Mesh & m)
00490 {
00491 return dist(u, v, m, generic_scalar_cb, (void*)0);
00492 }
00493
00495 }
00496