jacobi.template
Loading...
Searching...
No Matches
getmatrix.cpp
Go to the documentation of this file.
1#include "getmatrix.h"
2#include "userset.h"
3
4#include "omp.h"
5#include <algorithm>
6#include <cassert>
7#include <cmath>
8#include <ctime> // contains clock()
9#include <iomanip>
10#include <iostream>
11#include <list>
12#include <vector>
13using namespace std;
14
15// ####################################################################
16
17Matrix::Matrix(int const nrows, int const ncols)
18 : _nrows(nrows), _ncols(ncols), _dd(0)
19{}
20
21//Matrix::Matrix()
22 //: Matrix(0,0)
23//{}
24
25
28
29//vector<double> const & Matrix::GetDiag() const
30//{
31 //if ( 0==_dd.size() )
32 //{
33 //_dd.resize(Nrows());
34 //this->GetDiag(_dd);
35 //}
36 //assert( Nrows()==static_cast<int>(_dd.size()) );
37 //return _dd;
38//}
39
40// ####################################################################
41
43 : Matrix(0,0), _nnz(0), _id(0), _ik(0), _sk(0)
44{}
45
48
49void CRS_Matrix::Mult(vector<double> &w, vector<double> const &u) const
50{
51 assert( _ncols==static_cast<int>(u.size()) ); // compatibility of inner dimensions
52 assert( _nrows==static_cast<int>(w.size()) ); // compatibility of outer dimensions
53
54 for (int row = 0; row < _nrows; ++row)
55 {
56 double wi = 0.0;
57 for (int ij = _id[row]; ij < _id[row + 1]; ++ij)
58 {
59 wi += _sk[ij] * u[ _ik[ij] ];
60 }
61 w[row] = wi;
62 }
63 return;
64}
65
66void CRS_Matrix::Defect(vector<double> &w,
67 vector<double> const &f, vector<double> const &u) const
68{
69 assert( _ncols==static_cast<int>(u.size()) ); // compatibility of inner dimensions
70 assert( _nrows==static_cast<int>(w.size()) ); // compatibility of outer dimensions
71 assert( w.size()==f.size() );
72
73#pragma omp parallel for
74 for (int row = 0; row < _nrows; ++row)
75 {
76 double wi = f[row];
77 for (int ij = _id[row]; ij < _id[row + 1]; ++ij)
78 {
79 wi -= _sk[ij] * u[ _ik[ij] ];
80 }
81 w[row] = wi;
82 }
83 return;
84}
85
86void CRS_Matrix::GetDiag(vector<double> &d) const
87{
88 // be carefull when using a rectangular matrix
89 int const nm = min(_nrows, _ncols);
90
91 assert( nm==static_cast<int>(d.size()) ); // instead of stopping we could resize d and warn the user
92
93 for (int row = 0; row < nm; ++row)
94 {
95 const int ia = fetch(row, row); // Find diagonal entry of row
96 assert(ia >= 0);
97 d[row] = _sk[ia];
98 }
99 return;
100}
101
102inline
103int CRS_Matrix::fetch(int const row, int const col) const
104{
105 int const id2 = _id[row + 1]; // end and
106 int ip = _id[row]; // start of recent row (global index)
107
108 while (ip < id2 && _ik[ip] != col) // find index col (global index)
109 {
110 ++ip;
111 }
112 if (ip >= id2)
113 {
114 ip = -1;
115#ifndef NDEBUG // compiler option -DNDEBUG switches off the check
116 cout << "No column " << col << " in row " << row << endl;
117 assert(ip >= id2);
118#endif
119 }
120 return ip;
121}
122
124{
125// ID points to first entry of row
126// no symmetry assumed
127 cout << "\nMatrix (" << _nrows << " x " << _ncols << " with nnz = " << _id[_nrows] << ")\n";
128
129 for (int row = 0; row < _nrows; ++row)
130 {
131 cout << "Row " << row << " : ";
132 int const id1 = _id[row];
133 int const id2 = _id[row + 1];
134 for (int j = id1; j < id2; ++j)
135 {
136 cout.setf(ios::right, ios::adjustfield);
137 cout << "[" << setw(2) << _ik[j] << "] " << setw(4) << _sk[j] << " ";
138 }
139 cout << endl;
140 }
141 return;
142}
143
144
145
146bool CRS_Matrix::Compare2Old(int nnode, int const id[], int const ik[], double const sk[]) const
147{
148 bool bn = (nnode==_nrows); // number of rows
149 if (!bn)
150 {
151 cout << "######### Error: " << "number of rows" << endl;
152 }
153
154 bool bz = (id[nnode]==_nnz); // number of non zero elements
155 if (!bz)
156 {
157 cout << "######### Error: " << "number of non zero elements" << endl;
158 }
159
160 bool bd = equal(id,id+nnode+1,_id.cbegin()); // row starts
161 if (!bd)
162 {
163 cout << "######### Error: " << "row starts" << endl;
164 }
165
166 bool bk = equal(ik,ik+id[nnode],_ik.cbegin()); // column indices
167 if (!bk)
168 {
169 cout << "######### Error: " << "column indices" << endl;
170 }
171
172 bool bv = equal(sk,sk+id[nnode],_sk.cbegin()); // values
173 if (!bv)
174 {
175 cout << "######### Error: " << "values" << endl;
176 }
177
178 return bn && bz && bd && bk && bv;
179}
180
181
182// ####################################################################
183
185 : CRS_Matrix(), _mesh(mesh)
186{
188 return;
189}
190
193
195{
196 cout << "\n############ FEM_Matrix::Derive_Matrix_Pattern ";
197 double tstart = clock();
198 int const nelem(_mesh.Nelems());
199 int const ndof_e(_mesh.NdofsElement());
200 auto const &ia(_mesh.GetConnectivity());
201// Determine the number of matrix rows
202 _nrows = *max_element(ia.cbegin(), ia.cbegin() + ndof_e * nelem);
203 ++_nrows; // node numberng: 0 ... nnode-1
204 assert(*min_element(ia.cbegin(), ia.cbegin() + ndof_e * nelem) == 0); // numbering starts with 0 ?
205
206// CSR data allocation
207 _id.resize(_nrows + 1); // Allocate memory for CSR row pointer
208//##########################################################################
209 auto const v2v=_mesh.Node2NodeGraph();
210 _nnz=0; // number of connections
211 _id[0] = 0; // start of matrix row zero
212 for (size_t v = 0; v<v2v.size(); ++v )
213 {
214 _id[v+1] = _id[v] + v2v[v].size();
215 _nnz += v2v[v].size();
216 }
217 assert(_nnz == _id[_nrows]);
218 _sk.resize(_nnz); // Allocate memory for CSR column index vector
219
220// CSR data allocation
221 _ik.resize(_nnz); // Allocate memory for CSR column index vector
222// Copy column indices
223 int kk = 0;
224 for (size_t v = 0; v<v2v.size(); ++v )
225 {
226 for (size_t vi=0; vi<v2v[v].size(); ++vi)
227 {
228 _ik[kk] = v2v[v][vi];
229 ++kk;
230 }
231 }
232 _ncols = *max_element(_ik.cbegin(), _ik.cend()); // maximal column number
233 ++_ncols; // node numbering: 0 ... nnode-1
234 //cout << _nrows << " " << _ncols << endl;
235 assert(_ncols==_nrows);
236
237 double duration = (clock() - tstart) / CLOCKS_PER_SEC;
238 cout << "finished in " << duration << " sec. ########\n";
239
240 return;
241}
242
243
245{
246 cout << "\n############ FEM_Matrix::Derive_Matrix_Pattern slow ";
247 double tstart = clock();
248 int const nelem(_mesh.Nelems());
249 int const ndof_e(_mesh.NdofsElement());
250 auto const &ia(_mesh.GetConnectivity());
251// Determine the number of matrix rows
252 _nrows = *max_element(ia.cbegin(), ia.cbegin() + ndof_e * nelem);
253 ++_nrows; // node numberng: 0 ... nnode-1
254 assert(*min_element(ia.cbegin(), ia.cbegin() + ndof_e * nelem) == 0); // numbering starts with 0 ?
255
256// Collect for each node those nodes it is connected to (multiple entries)
257// Detect the neighboring nodes
258 vector< list<int> > cc(_nrows); // cc[i] is the list of nodes a node i is connected to
259 for (int i = 0; i < nelem; ++i)
260 {
261 int const idx = ndof_e * i;
262 for (int k = 0; k < ndof_e; ++k)
263 {
264 list<int> &cck = cc[ia[idx + k]];
265 cck.insert( cck.end(), ia.cbegin() + idx, ia.cbegin() + idx + ndof_e );
266 }
267 }
268// Delete the multiple entries
269 _nnz = 0;
270 for (auto &it : cc)
271 {
272 it.sort();
273 it.unique();
274 _nnz += it.size();
275 // cout << it.size() << " :: "; copy(it->begin(),it->end(), ostream_iterator<int,char>(cout," ")); cout << endl;
276 }
277
278// CSR data allocation
279 _id.resize(_nrows + 1); // Allocate memory for CSR row pointer
280 _ik.resize(_nnz); // Allocate memory for CSR column index vector
281
282// copy CSR data
283 _id[0] = 0; // begin of first row
284 for (size_t i = 0; i < cc.size(); ++i)
285 {
286 //cout << i << " " << nid.at(i) << endl;;
287 const list<int> &ci = cc[i];
288 const auto nci = static_cast<int>(ci.size());
289 _id[i + 1] = _id[i] + nci; // begin of next line
290 copy(ci.begin(), ci.end(), _ik.begin() + _id[i] );
291 }
292
293 assert(_nnz == _id[_nrows]);
294 _sk.resize(_nnz); // Allocate memory for CSR column index vector
295
296 _ncols = *max_element(_ik.cbegin(), _ik.cend()); // maximal column number
297 ++_ncols; // node numbering: 0 ... nnode-1
298 //cout << _nrows << " " << _ncols << endl;
299 assert(_ncols==_nrows);
300
301 double duration = (clock() - tstart) / CLOCKS_PER_SEC;
302 cout << "finished in " << duration << " sec. ########\n";
303
304 return;
305}
306
307
308void FEM_Matrix::CalculateLaplace(vector<double> &f)
309{
310 cout << "\n############ FEM_Matrix::CalculateLaplace ";
311 //double tstart = clock();
312 double tstart = omp_get_wtime(); // OpenMP
313 assert(_mesh.NdofsElement() == 3); // only for triangular, linear elements
314 //cout << _nnz << " vs. " << _id[_nrows] << " " << _nrows<< endl;
315 assert(_nnz == _id[_nrows]);
316
317 for (int k = 0; k < _nrows; ++k)
318 {
319 _sk[k] = 0.0;
320 }
321 for (int k = 0; k < _nrows; ++k)
322 {
323 f[k] = 0.0;
324 }
325
326 double ske[3][3], fe[3];
327 // Loop over all elements
328 auto const nelem = _mesh.Nelems();
329 auto const &ia = _mesh.GetConnectivity();
330 auto const &xc = _mesh.GetCoords();
331
332#pragma omp parallel for private(ske,fe)
333 for (int i = 0; i < nelem; ++i)
334 {
335 CalcElem(ia.data()+3 * i, xc.data(), ske, fe);
336 //AddElem(ia.data()+3 * i, ske, fe, _id.data(), _ik.data(), _sk.data(), f.data()); // GH: deprecated
337 AddElem_3(ia.data()+3 * i, ske, fe, f);
338 }
339
340 //double duration = (clock() - tstart) / CLOCKS_PER_SEC;
341 double duration = omp_get_wtime() - tstart; // OpenMP
342 cout << "finished in " << duration << " sec. ########\n";
343 //Debug();
344
345 return;
346}
347
348//void FEM_Matrix::ApplyDirichletBC(std::vector<double> const &u, std::vector<double> &f)
349//{
350 //double const PENALTY = 1e6;
351 //auto const idx = _mesh.Index_DirichletNodes();
352 //int const nidx = idx.size();
353
354 //for (int i=0; i<nidx; ++i)
355 //{
356 //int const k = idx[i];
357 //int const id1 = fetch(k, k); // Find diagonal entry of k
358 //assert(id1 >= 0);
359 //_sk[id1] += PENALTY; // matrix weighted scaling feasible
360 //f[k] += PENALTY * u[k];
361 //}
362
363 //return;
364//}
365
366void FEM_Matrix::ApplyDirichletBC(std::vector<double> const &u, std::vector<double> &f)
367{
368 auto const idx = _mesh.Index_DirichletNodes();
369 int const nidx = idx.size();
370
371 for (int i=0; i<nidx; ++i)
372 {
373 int const row = idx[i];
374 for (int ij=_id[row]; ij<_id[row+1]; ++ij)
375 {
376 int const col=_ik[ij];
377 if (col==row)
378 {
379 _sk[ij] = 1.0;
380 f[row] = u[row];
381 }
382 else
383 {
384 int const id1 = fetch(col, row); // Find entry (col,row)
385 assert(id1 >= 0);
386 f[col] -= _sk[id1]*u[row];
387 _sk[id1] = 0.0;
388 _sk[ij] = 0.0;
389 }
390 }
391 }
392
393 return;
394}
395
396
397
398void FEM_Matrix::AddElem_3(int const ial[3], double const ske[3][3], double const fe[3], vector<double> & f)
399{
400 for (int i = 0; i < 3; ++i)
401 {
402 const int ii = ial[i]; // row ii (global index)
403 for (int j = 0; j < 3; ++j) // no symmetry assumed
404 {
405 const int jj = ial[j]; // column jj (global index)
406 const int ip = fetch(ii,jj); // find column entry jj in row ii
407#ifndef NDEBUG // compiler option -DNDEBUG switches off the check
408 if (ip<0) // no entry found !!
409 {
410 cout << "Error in AddElem: (" << ii << "," << jj << ") ["
411 << ial[0] << "," << ial[1] << "," << ial[2] << "]\n";
412 assert(ip>=0);
413 }
414#endif
415#pragma omp atomic
416 _sk[ip] += ske[i][j];
417 }
418#pragma omp atomic
419 f[ii] += fe[i];
420 }
421}
422
423// ####################################################################
424
425
426//Prolongation::Prolongation(Mesh const & cmesh, Mesh const & fmesh)
427 //: CRS_Matrix(), _cmesh(cmesh), _fmesh(fmesh)
428//{
429 //Derive_Matrix_Pattern();
430 //return;
431//}
432
433
434//void Prolongation::Derive_Matrix_Pattern()
435//{
436 //cout << "\n ***** Subject to ongoing imlementation. *****\n";
437//}
438
439// ####################################################################
440// *********************************************************************
441
442
443// general routine for lin. triangular elements
444
445void CalcElem(int const ial[3], double const xc[], double ske[3][3], double fe[3])
446//void CalcElem(const int* __restrict__ ial, const double* __restrict__ xc, double* __restrict__ ske[3], double* __restrict__ fe)
447{
448 const int i1 = 2 * ial[0], i2 = 2 * ial[1], i3 = 2 * ial[2];
449 const double x13 = xc[i3 + 0] - xc[i1 + 0], y13 = xc[i3 + 1] - xc[i1 + 1],
450 x21 = xc[i1 + 0] - xc[i2 + 0], y21 = xc[i1 + 1] - xc[i2 + 1],
451 x32 = xc[i2 + 0] - xc[i3 + 0], y32 = xc[i2 + 1] - xc[i3 + 1];
452 const double jac = fabs(x21 * y13 - x13 * y21);
453
454 ske[0][0] = 0.5 / jac * (y32 * y32 + x32 * x32);
455 ske[0][1] = 0.5 / jac * (y13 * y32 + x13 * x32);
456 ske[0][2] = 0.5 / jac * (y21 * y32 + x21 * x32);
457 ske[1][0] = ske[0][1];
458 ske[1][1] = 0.5 / jac * (y13 * y13 + x13 * x13);
459 ske[1][2] = 0.5 / jac * (y21 * y13 + x21 * x13);
460 ske[2][0] = ske[0][2];
461 ske[2][1] = ske[1][2];
462 ske[2][2] = 0.5 / jac * (y21 * y21 + x21 * x21);
463
464 const double xm = (xc[i1 + 0] + xc[i2 + 0] + xc[i3 + 0]) / 3.0,
465 ym = (xc[i1 + 1] + xc[i2 + 1] + xc[i3 + 1]) / 3.0;
466 //fe[0] = fe[1] = fe[2] = 0.5 * jac * FunctF(xm, ym) / 3.0;
467 fe[0] = fe[1] = fe[2] = 0.5 * jac * fNice(xm, ym) / 3.0;
468}
469
470void CalcElem_Masse(int const ial[3], double const xc[], double const cm, double ske[3][3])
471{
472 const int i1 = 2 * ial[0], i2 = 2 * ial[1], i3 = 2 * ial[2];
473 const double x13 = xc[i3 + 0] - xc[i1 + 0], y13 = xc[i3 + 1] - xc[i1 + 1],
474 x21 = xc[i1 + 0] - xc[i2 + 0], y21 = xc[i1 + 1] - xc[i2 + 1];
475 //x32 = xc[i2 + 0] - xc[i3 + 0], y32 = xc[i2 + 1] - xc[i3 + 1];
476 const double jac = fabs(x21 * y13 - x13 * y21);
477
478 ske[0][0] += jac/12.0;
479 ske[0][1] += jac/24.0;
480 ske[0][2] += jac/24.0;
481 ske[1][0] += jac/24.0;
482 ske[1][1] += jac/12.0;
483 ske[1][2] += jac/24.0;
484 ske[2][0] += jac/24.0;
485 ske[2][1] += jac/24.0;
486 ske[2][2] += jac/12.0;
487
488 return;
489}
490
491
492// general routine for lin. triangular elements,
493// non-symm. matrix
494// node numbering in element: a s c e n d i n g indices !!
495// GH: deprecated
496void AddElem(int const ial[3], double const ske[3][3], double const fe[3],
497 int const id[], int const ik[], double sk[], double f[])
498{
499 for (int i = 0; i < 3; ++i)
500 {
501 const int ii = ial[i], // row ii (global index)
502 id1 = id[ii], // start and
503 id2 = id[ii + 1]; // end of row ii in matrix
504 int ip = id1;
505 for (int j = 0; j < 3; ++j) // no symmetry assumed
506 {
507 const int jj = ial[j];
508 bool not_found = true;
509 do // find entry jj (global index) in row ii
510 {
511 not_found = (ik[ip] != jj);
512 ++ip;
513 }
514 while (not_found && ip < id2);
515
516#ifndef NDEBUG // compiler option -DNDEBUG switches off the check
517 if (not_found) // no entry found !!
518 {
519 cout << "Error in AddElem: (" << ii << "," << jj << ") ["
520 << ial[0] << "," << ial[1] << "," << ial[2] << "]\n";
521 assert(!not_found);
522 }
523#endif
524 sk[ip - 1] += ske[i][j];
525 }
526 f[ii] += fe[i];
527 }
528}
529
530
531// ----------------------------------------------------------------------------
532
533// #####################################################################
534
536: Matrix( 0, 0 ), _iv(), _vv()
537{
538}
539
540BisectInterpolation::BisectInterpolation(std::vector<int> const & fathers)
541: Matrix( static_cast<int>(fathers.size())/2, 1+*max_element(fathers.cbegin(),fathers.cend()) ),
542 _iv(fathers), _vv(fathers.size(),0.5)
543{
544}
545
548
549void BisectInterpolation::GetDiag(vector<double> &d) const
550{
551 assert( Nrows()==static_cast<int>(d.size()) );
552
553 for (int k=0; k<Nrows(); ++k)
554 {
555 if ( _iv[2*k]==_iv[2*k+1] )
556 {
557 d[k] = 1.0;
558 }
559 else
560 {
561 d[k] = 0.0;
562 }
563 }
564 return;
565}
566
567void BisectInterpolation::Mult(vector<double> &wf, vector<double> const &uc) const
568{
569 assert( Nrows()==static_cast<int>(wf.size()) );
570 assert( Ncols()==static_cast<int>(uc.size()) );
571
572#pragma omp parallel for
573 for (int k=0; k<Nrows(); ++k)
574 {
575 wf[k] = _vv[2*k]*uc[_iv[2*k]] + _vv[2*k+1]*uc[_iv[2*k+1]];
576 }
577 return;
578}
579
580//void BisectInterpolation::MultT(vector<double> const &wf, vector<double> &uc) const
581//{
582 //assert( Nrows()==static_cast<int>(wf.size()) );
583 //assert( Ncols()==static_cast<int>(uc.size()) );
586 //for (int k=0; k<Ncols(); ++k) uc[k] = 0.0;
587//#pragma omp parallel for
588 //for (int k=0; k<Nrows(); ++k)
589 //{
590//#pragma omp atomic
591 //uc[_iv[2*k] ] += _vv[2*k ]*wf[k];
592//#pragma omp atomic
593 //uc[_iv[2*k+1]] += _vv[2*k+1]*wf[k];
594 //}
595 //return;
596//}
597
598void BisectInterpolation::MultT(vector<double> const &wf, vector<double> &uc) const
599{
600 assert( Nrows()==static_cast<int>(wf.size()) );
601 assert( Ncols()==static_cast<int>(uc.size()) );
602// GH: atomic slows down the code ==> use different storage for MultT operation (CRS-matrix?)
603//#pragma omp parallel for
604 for (int k=0; k<Ncols(); ++k) uc[k] = 0.0;
605#pragma omp parallel for
606 for (int k=0; k<Nrows(); ++k)
607 {
608 if (_iv[2*k]!=_iv[2*k+1])
609 {
610#pragma omp atomic
611 uc[_iv[2*k] ] += _vv[2*k ]*wf[k];
612#pragma omp atomic
613 uc[_iv[2*k+1]] += _vv[2*k+1]*wf[k];
614 }
615 else
616 {
617#pragma omp atomic
618 uc[_iv[2*k] ] += 2.0*_vv[2*k ]*wf[k]; // uses a property of class BisectInterpolation
619 }
620 }
621 return;
622}
623
624void BisectInterpolation::Defect(vector<double> &w,
625 vector<double> const &f, vector<double> const &u) const
626{
627 assert( Nrows()==static_cast<int>(w.size()) );
628 assert( Ncols()==static_cast<int>(u.size()) );
629 assert( w.size()==f.size() );
630
631 for (int k=0; k<Nrows(); ++k)
632 {
633 w[k] = f[k] - _vv[2*k]*u[_iv[2*k]] + _vv[2*k+1]*u[_iv[2*k+1]];
634 }
635 return;
636}
637
639{
640 for (int k=0; k<Nrows(); ++k)
641 {
642 cout << k << " : fathers(" << _iv[2*k] << "," << _iv[2*k+1] << ") ";
643 cout << "weights(" << _vv[2*k] << "," << _vv[2*k+1] << endl;
644 }
645 cout << endl;
646 return;
647}
648
649int BisectInterpolation::fetch(int row, int col) const
650{
651 int idx(-1);
652 if (_iv[2*row ] == col) idx = 2*row;
653 if (_iv[2*row+1] == col) idx = 2*row+1;
654 assert(idx>=0);
655 return idx;
656}
657
658// #####################################################################
659
660BisectIntDirichlet::BisectIntDirichlet(std::vector<int> const & fathers, std::vector<int> const & idxc_dir)
661 : BisectInterpolation(fathers)
662{
663 vector<bool> bdir(Ncols(), false); // Indicator for Dirichlet coarse nodes
664 for (size_t kc=0; kc<idxc_dir.size(); ++kc)
665 {
666 bdir.at(idxc_dir[kc]) = true; // Mark Dirichlet node from coarse mesh
667 }
668
669 for (size_t j=0; j<_iv.size(); ++j)
670 {
671 if ( bdir.at(_iv[j]) ) _vv[j] = 0.0; // set weight to zero iff (at least) one father is Dirichlet node
672 }
673 return;
674}
675
676
679
680
681// #####################################################################
682
684 vector<double> &fc, vector<double> &ff, vector<double> &uf)
685{
686 assert( P.Nrows()==static_cast<int>(ff.size()) );
687 assert( P.Ncols()==static_cast<int>(fc.size()) );
688 assert( ff.size()==uf.size() );
689 assert( P.Nrows()==SK.Nrows() );
690
691//#pragma omp parallel for
692 for (int k=0; k<P.Ncols(); ++k) fc[k] = 0.0;
693
694// GH: atomic slows down the code ==> use different storage for MultT operation (CRS-matrix?)
695#pragma omp parallel for
696 for (int row = 0; row < SK._nrows; ++row)
697 {
698 double wi = ff[row];
699 for (int ij = SK._id[row]; ij < SK._id[row + 1]; ++ij)
700 {
701 wi -= SK._sk[ij] * uf[ SK._ik[ij] ];
702 }
703
704 const int i1=P._iv[2*row];
705 const int i2=P._iv[2*row+1];
706 if (i1!=i2)
707 {
708#pragma omp atomic
709 fc[i1] += P._vv[2*row ]*wi;
710#pragma omp atomic
711 fc[i2] += P._vv[2*row +1]*wi;
712 }
713 else
714 {
715#pragma omp atomic
716 fc[i1] += 2.0*P._vv[2*row ]*wi; // uses a property of class BisectInterpolation
717 }
718 }
719 return;
720}
e, 2 size()
function vertex minimal boundary edge info in an ASCII file Matlab indexing is stored(starts with 1). % % The output file format is compatible with Mesh_2d_3_matlab nnode
~BisectIntDirichlet() override
std::vector< int > _iv
fathers[nnode][2] of fine grid nodes, double entries denote injection points
Definition getmatrix.h:465
void Debug() const override
std::vector< double > _vv
weights[nnode][2] of fathers for grid nodes
Definition getmatrix.h:466
void Mult(std::vector< double > &wf, std::vector< double > const &uc) const override
‍**
~BisectInterpolation() override
void MultT(std::vector< double > const &wf, std::vector< double > &uc) const
int fetch(int row, int col) const override
void Defect(std::vector< double > &w, std::vector< double > const &f, std::vector< double > const &u) const override
std::vector< int > _id
start indices of matrix rows
Definition getmatrix.h:225
void Mult(std::vector< double > &w, std::vector< double > const &u) const override
‍**
Definition getmatrix.cpp:49
std::vector< double > _sk
non-zero values
Definition getmatrix.h:227
int fetch(int row, int col) const override
virtual ~CRS_Matrix() override
Definition getmatrix.cpp:46
void Defect(std::vector< double > &w, std::vector< double > const &f, std::vector< double > const &u) const override
Definition getmatrix.cpp:66
std::vector< int > _ik
column indices
Definition getmatrix.h:226
int _nnz
number of non-zero entries
Definition getmatrix.h:224
void Debug() const override
bool Compare2Old(int nnode, int const id[], int const ik[], double const sk[]) const
void CalculateLaplace(std::vector< double > &f)
FEM_Matrix(Mesh const &mesh)
void ApplyDirichletBC(std::vector< double > const &u, std::vector< double > &f)
Mesh const & _mesh
reference to discretization
Definition getmatrix.h:316
~FEM_Matrix() override
void Derive_Matrix_Pattern_fast()
void Derive_Matrix_Pattern_slow()
void Derive_Matrix_Pattern()
Definition getmatrix.h:265
void AddElem_3(int const ial[3], double const ske[3][3], double const fe[3], std::vector< double > &f)
‍**
int Ncols() const
Definition getmatrix.h:56
std::vector< double > const & GetDiag() const
Definition getmatrix.h:78
virtual ~Matrix()
Definition getmatrix.cpp:26
Matrix(int nrows, int ncols)
Definition getmatrix.cpp:17
int _nrows
number of rows in matrix
Definition getmatrix.h:120
int _ncols
number of columns in matrix
Definition getmatrix.h:121
int Nrows() const
Definition getmatrix.h:47
Definition geom.h:14
const std::vector< double > & GetCoords() const
Definition geom.h:151
virtual std::vector< int > Index_DirichletNodes() const
Definition geom.cpp:260
int Nelems() const
Definition geom.h:62
std::vector< std::vector< int > > Node2NodeGraph() const
Definition geom.h:282
int NdofsElement() const
Definition geom.h:80
const std::vector< int > & GetConnectivity() const
Definition geom.h:120
void AddElem(int const ial[3], double const ske[3][3], double const fe[3], int const id[], int const ik[], double sk[], double f[])
void CalcElem_Masse(int const ial[3], double const xc[], double const cm, double ske[3][3])
void CalcElem(int const ial[3], double const xc[], double ske[3][3], double fe[3])
void DefectRestrict(CRS_Matrix const &SK, BisectInterpolation const &P, vector< double > &fc, vector< double > &ff, vector< double > &uf)
void CalcElem(int const ial[3], double const xc[], double ske[3][3], double fe[3])
u
Definition laplacian.m:3
double fNice(double const x, double const y)
Definition userset.h:28