jacobi_C-Style
getmatrix.cpp
Go to the documentation of this file.
1 #include "getmatrix.h"
2 #include "userset.h"
3 
4 #include <algorithm>
5 #include <cassert>
6 #include <cmath>
7 #include <iomanip>
8 #include <iostream>
9 #include <list>
10 #include <vector>
11 using namespace std;
12 
13 
14 void Get_Matrix_Pattern(int const nelem, int const ndof_e, int const *const ia,
15  int &nnz, int* &id, int* &ik, double* &sk)
16 {
17 // Determine the number of nodes
18  int nnode = *max_element(ia, ia + ndof_e * nelem);
19  ++nnode; // node numberng: 0 ... nnode-1
20  assert(*min_element(ia, ia + ndof_e * nelem) == 0); // numbering starts with 0 ?
21 
22 // Collect for each node those nodes it is connected to (multiple entries)
23  vector< list<int> > cc(nnode); // cc[i] is the list of nodes a node i is connected to
24  for (int i = 0; i < nelem; ++i)
25  {
26  //auto &l2g = new_elem[i].Get_l2g();
27  const int idx = ndof_e * i;
28  for (int k = 0; k < ndof_e; ++k)
29  {
30  list<int> &cck = cc.at(ia[idx + k]);
31  cck.insert( cck.end(), ia + idx, ia + idx + ndof_e );
32  }
33  }
34 // Delete the multiple entries
35  nnz = 0;
36  for (auto &it : cc)
37  {
38  it.sort();
39  it.unique();
40  nnz += it.size();
41  // cout << it.size() << " :: "; copy(it->begin(),it->end(), ostream_iterator<int,char>(cout," ")); cout << endl;
42  }
43 
44 // CSR data allocation
45  id = new int [nnode + 1]; // Allocate memory for CSR row pointer
46  ik = new int [nnz]; // Allocate memory for CSR column index vector
47 
48 // copy CSR data
49  id[0] = 0; // begin of first row
50  for (size_t i = 0; i < cc.size(); ++i)
51  {
52  //cout << i << " " << nid.at(i) << endl;;
53  const list<int> &ci = cc.at(i);
54  const auto nci = static_cast<int>(ci.size());
55  id[i + 1] = id[i] + nci; // begin of next line
56  copy(ci.begin(), ci.end(), ik + id[i] );
57  }
58 
59  assert(nnz == id[nnode]);
60  sk = new double [nnz]; // Allocate memory for CSR column index vector
61  return;
62 }
63 
64 
65 
66 // general routine for lin. triangular elements
67 
68 void CalcElem(int const ial[3], double const xc[], double ske[3][3], double fe[3])
69 //void CalcElem(const int* __restrict__ ial, const double* __restrict__ xc, double* __restrict__ ske[3], double* __restrict__ fe)
70 {
71  const int i1 = 2 * ial[0], i2 = 2 * ial[1], i3 = 2 * ial[2];
72  const double x13 = xc[i3 + 0] - xc[i1 + 0], y13 = xc[i3 + 1] - xc[i1 + 1],
73  x21 = xc[i1 + 0] - xc[i2 + 0], y21 = xc[i1 + 1] - xc[i2 + 1],
74  x32 = xc[i2 + 0] - xc[i3 + 0], y32 = xc[i2 + 1] - xc[i3 + 1];
75  const double jac = fabs(x21 * y13 - x13 * y21);
76 
77  ske[0][0] = 0.5 / jac * (y32 * y32 + x32 * x32);
78  ske[0][1] = 0.5 / jac * (y13 * y32 + x13 * x32);
79  ske[0][2] = 0.5 / jac * (y21 * y32 + x21 * x32);
80  ske[1][0] = ske[0][1];
81  ske[1][1] = 0.5 / jac * (y13 * y13 + x13 * x13);
82  ske[1][2] = 0.5 / jac * (y21 * y13 + x21 * x13);
83  ske[2][0] = ske[0][2];
84  ske[2][1] = ske[1][2];
85  ske[2][2] = 0.5 / jac * (y21 * y21 + x21 * x21);
86 
87  const double xm = (xc[i1 + 0] + xc[i2 + 0] + xc[i3 + 0]) / 3.0,
88  ym = (xc[i1 + 1] + xc[i2 + 1] + xc[i3 + 1]) / 3.0;
89  fe[0] = fe[1] = fe[2] = 0.5 * jac * FunctF(xm, ym) / 3.0;
90 }
91 
92 
93 // general routine for lin. triangular elements,
94 // non-symm. matrix
95 // node numbering in element: lex. forward
96 
97 void AddElem(int const ial[3], double const ske[3][3], double const fe[3],
98  int const id[], int const ik[], double sk[], double f[])
99 {
100  for (int i = 0; i < 3; ++i)
101  {
102  const int ii = ial[i], // row ii (global index)
103  id1 = id[ii], // start and
104  id2 = id[ii + 1]; // end of row ii in matrix
105  int ip = id1;
106  for (int j = 0; j < 3; ++j) // no symmetry assumed
107  {
108  const int jj = ial[j];
109  bool not_found = true;
110  do // find entry jj (global index) in row ii
111  {
112  not_found = (ik[ip] != jj);
113  ++ip;
114  }
115  while (not_found && ip < id2);
116 
117 #ifndef NDEBUG // compiler option -DNDEBUG switches off the check
118  if (not_found) // no entry found !!
119  {
120  cout << "Error in AddElem: (" << ii << "," << jj << ") ["
121  << ial[0] << "," << ial[1] << "," << ial[2] << "]\n";
122  assert(!not_found);
123  }
124 #endif
125  sk[ip - 1] += ske[i][j];
126  }
127  f[ii] += fe[i];
128  }
129 }
130 
131 
132 void DebugMatrix(int const nnode, int const id[], int const ik[], double const sk[])
133 {
134 // ID points to first entry of row
135 // no symmetry assumed
136  cout << "\nMatrix (nnz = " << id[nnode] << ")\n";
137  int id1, id2 = -1;
138  for (int row = 0; row < nnode; ++row)
139  {
140  cout << "Row " << row << " : ";
141  id1 = id[row];
142  id2 = id[row + 1];
143  for (int j = id1; j < id2; ++j)
144  {
145  cout.setf(ios::right, ios::adjustfield);
146  cout << "[" << setw(2) << ik[j] << "] " << setw(4) << sk[j] << " ";
147  }
148  cout << endl;
149  }
150  return;
151 }
152 
153 
154 void DebugVector(int const nnode, double const v[])
155 {
156  cout << "\nVector (nnode = " << nnode << ")\n";
157  for (int j = 0; j < nnode; ++j)
158  {
159  cout.setf(ios::right, ios::adjustfield);
160  cout << v[j] << " ";
161  }
162  cout << endl;
163 
164  return;
165 }
166 
167 // ----------------------------------------------------------------------------
168 
169 
170 int fetch(int const row, int const col, int const id[], int const ik[])
171 {
172  int const id2 = id[row + 1]; // end and
173  int ip = id[row]; // start of recent row (global index)
174 
175  while (ip < id2 && ik[ip] != col) // find index col (global index)
176  {
177  ++ip;
178  }
179 #ifndef NDEBUG // compiler option -DNDEBUG switches off the check
180  if (ip >= id2)
181  {
182  cout << "No column " << col << " in row " << row << endl;
183  ip = -1;
184  assert(ip >= id2);
185  }
186 #endif
187  return ip;
188 }
189 
190 // w := f - K*u
191 void Defect(double w[], double const f[], double const u[],
192  int const nnode, int const id[], int const ik[], double const sk[])
193 {
194  for (int row = 0; row < nnode; ++row)
195  {
196  double wi = f[row];
197  for (int ij = id[row]; ij < id[row + 1]; ++ij)
198  {
199  wi -= sk[ij] * u[ ik[ij] ];
200  }
201  w[row] = wi;
202  }
203  return;
204 }
205 
206 void CrsMult(double w[], double const u[], int const nnode,
207  int const id[], int const ik[], double const sk[])
208 {
209  for (int row = 0; row < nnode; ++row)
210  {
211  double wi = 0.0;
212  for (int ij = id[row]; ij < id[row + 1]; ++ij)
213  {
214  wi += sk[ij] * u[ ik[ij] ];
215  }
216  w[row] = wi;
217  }
218  return;
219 }
220 
221 //----------------------------------------------------------------------
222 
223 void GetDiag(int const nnode, int const id[], int const ik[], double const sk[], double d[])
224 {
225  for (int row = 0; row < nnode; ++row)
226  {
227  const int ia = fetch(row, row, id, ik);
228  assert(ia >= 0);
229  d[row] = sk[ia];
230  }
231  return;
232 }
233 
234 
235 
236 /*
237  void GetMatrix(...)
238 
239  Computes matrix for Poisson eqution.
240  We use a general code to calculate element matrices and
241  local stiffness matrix K, no symmetry assumed
242 */
243 void GetMatrix (int const nelem, int const ndof_e, int const ia[], int const nnode, double const xc[],
244  int const nnz, int const id[], int const ik[], double sk[], double f[])
245 {
246  assert(ndof_e == 3);
247  assert(nnz == id[nnode]);
248 
249  for (int k = 0; k < id[nnode]; ++k)
250  {
251  sk[k] = 0.0;
252  }
253  for (int k = 0; k < nnode; ++k)
254  {
255  f[k] = 0.0;
256  }
257 
258  double ske[3][3], fe[3];
259  // Loop over all elements
260  for (int i = 0; i < nelem; ++i)
261  {
262  CalcElem(ia + 3 * i, xc, ske, fe);
263  AddElem(ia + 3 * i, ske, fe, id, ik, sk, f);
264  }
265 
266  //DebugMatrix(nnode, id, ik, sk);
267 
268  return;
269 }
270 
271 /* Apply b.c. defined in u on matrix and right hand side */
272 /* via penalty method. */
273 // no symmetry of matrix
274 
275 void ApplyDirichletBC(int const nx, int const ny, int const neigh[],
276  double const u[], int const id[], int const ik[] , double sk[], double f[])
277 {
278  const double PENALTY = 1e6;
279  const int dx = 1,
280  dy = nx + 1,
281  bl = 0,
282  br = nx,
283  tl = ny * (nx + 1),
284  tr = (ny + 1) * (nx + 1) - 1;
285  const int start[4] = { bl, br, tl, bl},
286  end[4] = { br, tr, tr, tl},
287  step[4] = { dx, dy, dx, dy};
288 
289  for (int j = 0; j < 4; j++)
290  {
291  if (neigh[j] < 0)
292  {
293  for (int i = start[j]; i <= end[j]; i += step[j])
294  {
295  const int id1 = fetch(i, i, id, ik);
296  assert(id1 >= 0);
297 // if ( j!=1 )
298  {
299  sk[id1] += PENALTY; /* matrix weighted scaling feasible */
300  f[i] += PENALTY * u[i];
301  }
302 // else
303 // {
304 // const double alfa = 1e-0; // Robin B.C. with g=1e-2
305 // sk[id1] += alfa;
306 // f[i] += alfa*1e-2;
307 // }
308  }
309  }
310  }
311  return;
312 }
313 
ApplyDirichletBC
void ApplyDirichletBC(int const nx, int const ny, int const neigh[], double const u[], int const id[], int const ik[], double sk[], double f[])
Definition: getmatrix.cpp:275
GetDiag
void GetDiag(int const nnode, int const id[], int const ik[], double const sk[], double d[])
Definition: getmatrix.cpp:223
DebugMatrix
void DebugMatrix(int const nnode, int const id[], int const ik[], double const sk[])
Definition: getmatrix.cpp:132
AddElem
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[])
Definition: getmatrix.cpp:97
Get_Matrix_Pattern
void Get_Matrix_Pattern(int const nelem, int const ndof_e, int const *const ia, int &nnz, int *&id, int *&ik, double *&sk)
Definition: getmatrix.cpp:14
CrsMult
void CrsMult(double w[], double const u[], int const nnode, int const id[], int const ik[], double const sk[])
Definition: getmatrix.cpp:206
userset.h
DebugVector
void DebugVector(int const nnode, double const v[])
Definition: getmatrix.cpp:154
GetMatrix
void GetMatrix(int const nelem, int const ndof_e, int const ia[], int const nnode, double const xc[], int const nnz, int const id[], int const ik[], double sk[], double f[])
Definition: getmatrix.cpp:243
CalcElem
void CalcElem(int const ial[3], double const xc[], double ske[3][3], double fe[3])
Definition: getmatrix.cpp:68
FunctF
double FunctF(double const x, double const y)
Definition: userset.cpp:31
getmatrix.h
Defect
void Defect(double w[], double const f[], double const u[], int const nnode, int const id[], int const ik[], double const sk[])
Definition: getmatrix.cpp:191
fetch
int fetch(int const row, int const col, int const id[], int const ik[])
Definition: getmatrix.cpp:170