proteus  1.8.1
C/C++/Fortran libraries
equivalent_polynomials.h
Go to the documentation of this file.
1 #ifndef EQUIVALENT_POLYNOMIALS_H
2 #define EQUIVALENT_POLYNOMIALS_H
3 #include <cmath>
4 #include <cassert>
5 #include <iostream>
6 #include <iomanip>
10 
12 {
13  template<int nSpace, int nP, int nQ, int nEBQ>
15  {
16  public:
17  Regularized(bool useExact=false)
18  {}
19  inline int calculate(const double* phi_dof, const double* phi_nodes, const double* xi_r, double ma, double mb, bool isBoundary, bool scale)
20  {}
21  inline int calculate(const double* phi_dof, const double* phi_nodes, const double* xi_r, bool isBoundary)
22  {
23  return calculate(phi_dof, phi_nodes, xi_r, 1.0,1.0, isBoundary, false);
24  }
25  inline double* get_normal()
26  {
27  return NULL;
28  }
29  inline void set_quad(unsigned int q)
30  {}
31  inline void set_boundary_quad(unsigned int ebq)
32  {}
33  inline double H(double eps, double phi)
34  {
35  double h;
36  if (phi > eps)
37  h=1.0;
38  else if (phi < -eps)
39  h=0.0;
40  else if (phi==0.0)
41  h=0.5;
42  else
43  h = 0.5*(1.0 + phi/eps + sin(M_PI*phi/eps)/M_PI);
44  return h;
45  }
46  inline double ImH(double eps, double phi)
47  {
48  return 1.0-H(eps,phi);
49  }
50  inline double D(double eps, double phi)
51  {
52  double d;
53  if (phi > eps)
54  d=0.0;
55  else if (phi < -eps)
56  d=0.0;
57  else
58  d = 0.5*(1.0 + cos(M_PI*phi/eps))/eps;
59  return d;
60  }
61  inline double VA(int i){return -1.0;};
62  inline double VA_x(int i){return -1.0;};
63  inline double VA_y(int i){return -1.0;};
64  inline double VA_z(int i){return -1.0;};
65  inline double VB(int i){return -1.0;};
66  inline double VB_x(int i){return -1.0;};
67  inline double VB_y(int i){return -1.0;};
68  inline double VB_z(int i){return -1.0;};
69  };
70 
71  template<int nSpace, int nP, int nQ, int nEBQ>
72  class Simplex
73  {
74  public:
75  Simplex(bool useExact=true)
76  {
77  if (nSpace == 1)
78  assert(nDOF == nP+1);
79  else if (nSpace == 2)
80  assert(nDOF == (nP+1)*(nP+2)/2);
81  else if (nSpace == 3)
82  assert(nDOF == (nP+1)*(nP+2)*(nP+3)/6);
83  else
84  assert(false);
85  _set_Ainv<nSpace,nP>(Ainv);
86  for (int i=0;i<nSpace;i++)
87  level_set_normal[i]=0.0;
88  level_set_normal[0]=1.0;
89  }
90 
91  inline int calculate(const double* phi_dof, const double* phi_nodes, const double* xi_r, double ma, double mb, bool isBoundary, bool scale);
92 
93  inline int calculate(const double* phi_dof, const double* phi_nodes, const double* xi_r, bool isBoundary)
94  {
95  return calculate(phi_dof, phi_nodes, xi_r, 1.0,1.0, isBoundary, false);
96  }
97 
98  inline void set_quad(unsigned int q)
99  {
100  assert(q >= 0);
101  assert(q < nQ);
102  if(inside_out)
103  {
104  _H_q = _ImH[q];
105  _ImH_q = _H[q];
106  _D_q = _D[q];
107  }
108  else
109  {
110  _H_q = _H[q];
111  _ImH_q = _ImH[q];
112  _D_q = _D[q];
113  }
114  //basis functions already adjusted for inside_out
115  for(int i=0;i<nN;i++)
116  {
117  _va_q[i] = _va[q*nN+i];
118  _vb_q[i] = _vb[q*nN+i];
119  }
120  }
121 
122  inline void set_boundary_quad(unsigned int ebq)
123  {
124  assert(ebq >= 0);
125  assert(ebq < nEBQ);
126  if(inside_out)
127  {
128  _H_q = _ImH_ebq[ebq];
129  _ImH_q = _H_ebq[ebq];
130  _D_q = _D_ebq[ebq];
131  }
132  else
133  {
134  _H_q = _H_ebq[ebq];
135  _ImH_q = _ImH_ebq[ebq];
136  _D_q = _D_ebq[ebq];
137  }
138  //basis functions already adjusted for inside_out
139  for(int i=0;i<nN;i++)
140  {
141  _va_q[i] = _va_ebq[ebq*nN+i];
142  _vb_q[i] = _vb_ebq[ebq*nN+i];
143  }
144  }
145 
146  inline double* get_H(){return _H;};
147  inline double* get_ImH(){return _ImH;};
148  inline double* get_D(){return _D;};
149  inline double H(double eps, double phi){return _H_q;};
150  inline double ImH(double eps, double phi){return _ImH_q;};
151  inline double D(double eps, double phi){return _D_q;};
152  inline double VA(int i){return _va_q[i];};
153  inline double VA_x(int i){return _va_x[i];};
154  inline double VA_y(int i){return _va_y[i];};
155  inline double VA_z(int i){return _va_z[i];};
156  inline double VB(int i){return _vb_q[i];};
157  inline double VB_x(int i){return _vb_x[i];};
158  inline double VB_y(int i){return _vb_y[i];};
159  inline double VB_z(int i){return _vb_z[i];};
160  inline double* get_normal()
161  {
162  return level_set_normal;
163  }
165  static const unsigned int nN=nSpace+1;
167  private:
168  double _H_q, _ImH_q, _D_q, _va_q[nN], _vb_q[nN],
169  _va_x[nN],_va_y[nN],_va_z[nN],_vb_x[nN],_vb_y[nN],_vb_z[nN];
170  unsigned int root_node, permutation[nN];
171  double phi[nN], nodes[nN*3];
172  double _a1[nN],_a2[nN],_a3[nN],
173  _b1[nN],_b2[nN],_b3[nN];
174  double Jac[nSpace*nSpace], inv_Jac[nSpace*nSpace], det_Jac;
175  double level_set_normal[nSpace], X_0[nSpace], phys_nodes_cut[(nN-1)*3], THETA_01, THETA_02, THETA_31, THETA_32, phys_nodes_cut_quad_01[3],phys_nodes_cut_quad_02[3],phys_nodes_cut_quad_31[3],phys_nodes_cut_quad_32[3];
176  static const unsigned int nDOF=((nSpace-1)/2)*(nSpace-2)*(nP+1)*(nP+2)*(nP+3)/6 + (nSpace-1)*(3-nSpace)*(nP+1)*(nP+2)/2 + (2-nSpace)*((3-nSpace)/2)*(nP+1);
177  double Ainv[nDOF*nDOF];
178  double C_H[nDOF], C_ImH[nDOF], C_D[nDOF];
179  inline int _calculate_permutation(const double* phi_dof, const double* phi_nodes);
180  inline void _calculate_cuts();
181  inline void _calculate_cuts_quad();
182  inline void _calculate_C();
183  inline void _correct_phi(const double* phi_dof, const double* phi_nodes);
184  double _H[nQ], _ImH[nQ], _D[nQ], _va[nQ*nN], _vb[nQ*nN];
185  double _H_ebq[nEBQ], _ImH_ebq[nEBQ], _D_ebq[nEBQ], _va_ebq[nEBQ*nN], _vb_ebq[nEBQ*nN];//cek hack: this is confusing because we use no suffice for the q arrays and _ebq for the ebq arrays, then use _q above for generic quad point
186  inline void _calculate_basis_coefficients(const double ma, const double mb);
187  inline void _calculate_basis(const double* xi,double* va, double* vb)
188  {
189  //2D specific but won't break in 3D
190  for (int i=0;i<nN;i++)
191  {
192  va[i] = _a1[i] + _a2[i]*xi[0] + _a3[i]*xi[1];
193  vb[i] = _b1[i] + _b2[i]*xi[0] + _b3[i]*xi[1];
194  }
195  }
196  };
197 
198  template<int nSpace, int nP, int nQ, int nEBQ>
199  inline void Simplex<nSpace,nP,nQ,nEBQ>::_calculate_C()
200  {
201  register double b_H[nDOF], b_ImH[nDOF], b_dH[nDOF*nSpace], b_D[nDOF*nSpace];
202  if (quad_cut)
203  {
204  _calculate_b<nP>(THETA_01,THETA_02,THETA_31,THETA_32,
205  phi_dof_corrected[permutation[0]],
206  phi_dof_corrected[permutation[1]],
207  phi_dof_corrected[permutation[2]],
208  phi_dof_corrected[permutation[3]],
209  b_H, b_ImH, b_D);
210  if (inside_out)//todo handle insdie out for H/ImH/D in a simplified/unified way
211  {
212  for (unsigned int i=0; i < nDOF; i++)
213  {
214  b_D[i] = -b_D[i];
215  }
216  }
217  for (unsigned int i=0; i < nDOF; i++)
218  {
219  C_H[i] = 0.0;
220  C_ImH[i] = 0.0;
221  C_D[i] = 0.0;
222  for (unsigned int j=0; j < nDOF; j++)
223  {
224  assert(!isnan(Ainv[i*nDOF + j]));
225  assert(!isnan(b_H[j]));
226  assert(!isnan(b_ImH[j]));
227  assert(!isnan(b_D[j]));
228  C_H[i] += Ainv[i*nDOF + j]*b_H[j];
229  C_ImH[i] += Ainv[i*nDOF + j]*b_ImH[j];
230  C_D[i] += Ainv[i*nDOF + j]*b_D[j];
231  }
232  //only if direct boundary integral is used
233  //C_D[i] /= det_Jac;
234  }
235  }
236  else
237  {
238  _calculate_b<nSpace,nP>(X_0, b_H, b_ImH, b_dH);
239 
240  register double Jt_dphi_dx[nSpace];
241  for (unsigned int I=0; I < nSpace; I++)
242  {
243  Jt_dphi_dx[I] = 0.0;
244  for(unsigned int J=0; J < nSpace; J++)
245  Jt_dphi_dx[I] += Jac[J*nSpace + I]*level_set_normal[J];
246  }
247  for (unsigned int i=0; i < nDOF; i++)
248  {
249  C_H[i] = 0.0;
250  C_ImH[i] = 0.0;
251  C_D[i] = 0.0;
252  for (unsigned int j=0; j < nDOF; j++)
253  {
254  C_H[i] += Ainv[i*nDOF + j]*b_H[j];
255  C_ImH[i] += Ainv[i*nDOF + j]*b_ImH[j];
256  for (unsigned int I=0; I < nSpace; I++)
257  {
258  if (fabs(Jt_dphi_dx[I]) > 0.0)
259  C_D[i] -= Ainv[i*nDOF + j]*b_dH[j*nSpace+I]/(Jt_dphi_dx[I]);
260  }
261  }
262  }
263  }
264  }
265 
266  template<int nSpace, int nP, int nQ, int nEBQ>
267  inline int Simplex<nSpace,nP,nQ,nEBQ>::_calculate_permutation(const double* phi_dof, const double* phi_nodes)
268  {
269  int p_i, pcount=0, n_i, ncount=0, z_i, zcount=0;
270  root_node=0;
271  inside_out=false;
272  quad_cut=false;
273  const double eps=1.0e-8;
274  for (unsigned int i=0; i < nN; i++)
275  {
276  if(phi_dof[i] > eps)
277  {
278  if (pcount == 0)
279  p_i = i;
280  pcount += 1;
281  }
282  else if(phi_dof[i] < -eps)
283  {
284  if (ncount == 0)
285  n_i = i;
286  ncount += 1;
287  }
288  else
289  {
290  z_i = i;
291  zcount += 1;
292  }
293  }
294  if(pcount == nN)
295  {
296  return 1;
297  }
298  else if(ncount == nN)
299  {
300  return -1;
301  }
302  else if(ncount == 1)
303  {
304  if (zcount == nN-1)//interface is on an element boundary, don't integrate this orientation
305  {
306  if (nSpace > 1)
307  {
308  //note: see comment below about these two cases
309  return -1;
310  }
311  else
312  {
313  root_node = n_i;
314  }
315  }
316  else
317  {
318  root_node = n_i;
319  }
320  }
321  else if(pcount == 1)
322  {
323  if (zcount == nN-1)//interface is on an element boundary, integrate this orientation
324  {
325  //note: we are marking the element to the positive sdf side as cut,
326  //which means the other element is fully in the -1 domain
327  //for single-phase/cut cell methods, that means the fictitious domain
328  //is excluded. This affects how ghost penalties and inactive nodes are set.
329  //This choice is more robust.
330  if (nSpace > 1)
331  {
332  root_node = p_i;
333  inside_out = true;
334  }
335  else
336  return 1;
337  }
338  else
339  {
340  if (nSpace > 1)
341  {
342  root_node = p_i;
343  inside_out = true;
344  }
345  else
346  {
347  root_node = n_i;
348  }
349  }
350  }
351  else if (nSpace == 3 && pcount == 2 && ncount == 2)
352  {
353  //special case only in 3D
354  quad_cut = true;
355  root_node = n_i;
356  }
357  else
358  {
359  if (zcount >= nN-1)
360  std::cout<<"zcount "<<zcount<<" >= "<<nN-1<<std::endl;
361  assert(zcount < nN-1);
362  if(pcount)
363  return 1;
364  else if (ncount)
365  return -1;
366  else
367  assert(false);
368  }
369  for(unsigned int i=0; i < nN; i++)
370  {
371  permutation[i] = (root_node+i)%nN;
372  }
373  if(quad_cut)
374  {
375  if(phi_dof[permutation[nN-1]] > 0.0)
376  {
377  int tmp=permutation[nN-1];
378  if (phi_dof[permutation[nN-2]] < 0.0)
379  {
380  permutation[nN-1] = permutation[nN-2];
381  permutation[nN-2] = tmp;
382  }
383  else if (phi_dof[permutation[nN-3]] < 0.0)
384  {
385  permutation[nN-1] = permutation[nN-3];
386  permutation[nN-3] = tmp;
387  }
388  else
389  assert(false);
390  }
391  assert(phi_dof[permutation[0]] < 0.0);
392  assert(phi_dof[permutation[3]] < 0.0);
393  assert(phi_dof[permutation[1]] > 0.0);
394  assert(phi_dof[permutation[2]] > 0.0);
395  }
396  for(unsigned int i=0; i < nN; i++)
397  {
398  phi[i] = phi_dof[permutation[i]];
399  for(unsigned int I=0; I < 3; I++)
400  {
401  nodes[i*3 + I] = phi_nodes[permutation[i]*3 + I];//nodes always 3D
402  }
403  }
404  double JacTest[nSpace*nSpace];
405  for(unsigned int I=0; I < nSpace; I++)
406  {
407  for(unsigned int i=0; i < nN - 1; i++)
408  {
409  Jac[I*nSpace+i] = nodes[(1+i)*3 + I] - nodes[I];
410  JacTest[I*nSpace+i] = phi_nodes[(1+i)*3 + I] - phi_nodes[I];
411  }
412  }
413  det_Jac = det<nSpace>(Jac);
414  double det_JacTest = det<nSpace>(JacTest);
415  /* assert(det_JacTest >= 0.0); */
416  /* assert(det_Jac >= 0.0); */
417  if(det_Jac < 0.0)
418  {
419  if (quad_cut)//flip the two internal positive nodes
420  {
421  double tmp = permutation[2];
422  permutation[2] = permutation[1];
423  permutation[1] = tmp;
424  }
425  else//flip the last two nodes
426  {
427  double tmp = permutation[nN-1];
428  permutation[nN-1] = permutation[nN-2];
429  permutation[nN-2] = tmp;
430  }
431  for(unsigned int i=0; i < nN; i++)
432  {
433  phi[i] = phi_dof[permutation[i]];
434  for(unsigned int I=0; I < 3; I++)
435  {
436  nodes[i*3 + I] = phi_nodes[permutation[i]*3 + I];//nodes always 3D
437  }
438  }
439  for(unsigned int i=0; i < nN-1; i++)
440  for(unsigned int I=0; I < nSpace; I++)
441  Jac[I*nSpace+i] = nodes[(1+i)*3 + I] - nodes[I];
442  det_Jac = det<nSpace>(Jac);
443  assert(det_Jac > 0);
444  if (nSpace == 1)
445  inside_out = true;
446  }
447  inv<nSpace>(Jac, inv_Jac);
448  return 0;
449  }
450 
451  template<int nSpace, int nP, int nQ, int nEBQ>
452  inline void Simplex<nSpace,nP,nQ,nEBQ>::_calculate_cuts()
453  {
454  const double eps=1.0e-8;
455  for (unsigned int i=0; i < nN-1;i++)
456  {
457  if(phi[i+1]*phi[0] < 0.0)
458  {
459  X_0[i] = 0.5 - 0.5*(phi[i+1] + phi[0])/(phi[i+1]-phi[0]);
460  assert(X_0[i] <=1.0);
461  assert(X_0[i] >=0.0);
462  for (unsigned int I=0; I < 3; I++)
463  {
464  phys_nodes_cut[i*3 + I] = (1-X_0[i])*nodes[I] + X_0[i]*nodes[(1+i)*3 + I];
465  }
466  }
467  else
468  {
469  assert(phi[i+1] < eps);
470  X_0[i] = 1.0;
471  for (unsigned int I=0; I < 3; I++)
472  {
473  phys_nodes_cut[i*3 + I] = nodes[(1+i)*3 + I];
474  }
475  }
476  }
477  }
478 
479  template<int nSpace, int nP, int nQ, int nEBQ>
480  inline void Simplex<nSpace,nP,nQ,nEBQ>::_calculate_cuts_quad()
481  {
482  const double eps=1.0e-8,Imeps=1.0-eps;
483  THETA_01 = 0.5 - 0.5*(phi[1] + phi[0])/(phi[1] - phi[0]);
484  THETA_02 = 0.5 - 0.5*(phi[2] + phi[0])/(phi[2] - phi[0]);
485  THETA_31 = 0.5 - 0.5*(phi[1] + phi[3])/(phi[1] - phi[3]);
486  THETA_32 = 0.5 - 0.5*(phi[2] + phi[3])/(phi[2] - phi[3]);
487  if ( (THETA_01 < eps || THETA_01 > Imeps) || (THETA_02 < eps || THETA_02 > Imeps) || (THETA_31 < eps || THETA_31 > Imeps) || (THETA_32 < eps || THETA_32 > Imeps))
488  {
489  THETA_01 = fmin(Imeps,fmax(eps,0.5 - 0.5*(phi[1] + phi[0])/(phi[1] - phi[0])));
490  THETA_02 = fmin(Imeps,fmax(eps,0.5 - 0.5*(phi[2] + phi[0])/(phi[2] - phi[0])));
491  THETA_31 = fmin(Imeps,fmax(eps,0.5 - 0.5*(phi[1] + phi[3])/(phi[1] - phi[3])));
492  THETA_32 = fmin(Imeps,fmax(eps,0.5 - 0.5*(phi[2] + phi[3])/(phi[2] - phi[3])));
493  }
494  for (unsigned int I=0; I < 3; I++)
495  {
496  phys_nodes_cut_quad_01[I] = (1-THETA_01)*nodes[I] + THETA_01*nodes[1*3 + I];
497  phys_nodes_cut_quad_02[I] = (1-THETA_02)*nodes[I] + THETA_02*nodes[2*3 + I];
498  phys_nodes_cut_quad_31[I] = (1-THETA_31)*nodes[3*3 + I] + THETA_31*nodes[1*3 + I];
499  phys_nodes_cut_quad_32[I] = (1-THETA_32)*nodes[3*3 + I] + THETA_32*nodes[2*3 + I];
500  }
501  }
502 
503  template<int nSpace, int nP, int nQ, int nEBQ>
504  inline void Simplex<nSpace,nP,nQ,nEBQ>::_correct_phi(const double* phi_dof, const double* phi_nodes)
505  {
506  register double cut_barycenter[3] ={0.,0.,0.};
507  const double one_by_nNm1 = 1.0/(nN-1.0);
508  if (quad_cut)
509  {
510  for (unsigned int I=0; I < nSpace; I++)
511  cut_barycenter[I] += 0.25*(phys_nodes_cut_quad_01[I] +
512  phys_nodes_cut_quad_02[I] +
513  phys_nodes_cut_quad_31[I] +
514  phys_nodes_cut_quad_32[I]);
515  }
516  else
517  {
518  for (unsigned int i=0; i < nN-1;i++)
519  {
520  for (unsigned int I=0; I < nSpace; I++)
521  cut_barycenter[I] += phys_nodes_cut[i*3+I]*one_by_nNm1;
522  }
523  }
524  for (unsigned int i=0; i < nN;i++)
525  {
526  phi_dof_corrected[i]=0.0;
527  for (unsigned int I=0; I < nSpace; I++)
528  {
529  phi_dof_corrected[i] += level_set_normal[I]*(phi_nodes[i*3+I] - cut_barycenter[I]);
530  }
531  //ensure sdf sign convention consistent with input phi
532  if (phi_dof_corrected[i]*phi_dof[i] < 0.0)
533  {
534  phi_dof_corrected[i]*=-1.0;
535  }
536  }
537  }
538 
539  template<int nSpace, int nP, int nQ, int nEBQ>
540  inline void Simplex<nSpace,nP,nQ,nEBQ>::_calculate_basis_coefficients(const double ma, const double mb)
541  {
542  assert(nSpace == 2);
543  assert(nN==3);
544  double nx=0.0,ny=0.0;
545  for (int J=0;J<2;J++)
546  {
547  nx += inv_Jac[0*2+J]*level_set_normal[J];
548  ny += inv_Jac[1*2+J]*level_set_normal[J];
549  }
550  double x0=X_0[0],
551  y0=X_0[1];
552  double vall[9]={1.,0.,0.,
553  0.,0.,1.,
554  0.,1.,0.};
555  for (int j=0; j < 3; j++)
556  {
557  int i = permutation[j];
558  double v[3]={0.0,0.0,0.0},grad_va[2]={0.0,0.0},grad_vb[2]={0.0,0.0},grad_va_ref[2],grad_vb_ref[2];
559  v[0] = vall[j*3+0];
560  v[1] = vall[j*3+1];
561  v[2] = vall[j*3+2];
562  _a1[i] = v[0];
563  _a2[i] = (ny*v[1]*y0*(ma*x0 - ma - mb*x0 + mb) - v[0]*(ma*ny*x0 - ma*ny*y0 + mb*nx*y0 + mb*ny*y0) + v[2]*(-ma*ny*x0*y0 + ma*ny*x0 + mb*nx*y0 + mb*ny*x0*y0))/(-ma*nx*x0*y0 + ma*nx*y0 - ma*ny*x0*y0 + ma*ny*x0 + mb*nx*x0*y0 + mb*ny*x0*y0);
564  _a3[i] = (nx*v[2]*x0*(ma*y0 - ma - mb*y0 + mb) - v[0]*(-ma*nx*x0 + ma*nx*y0 + mb*nx*x0 + mb*ny*x0) + v[1]*(-ma*nx*x0*y0 + ma*nx*y0 + mb*nx*x0*y0 + mb*ny*x0))/(-ma*nx*x0*y0 + ma*nx*y0 - ma*ny*x0*y0 + ma*ny*x0 + mb*nx*x0*y0 + mb*ny*x0*y0);
565  _b1[i] = (ma*v[0]*(nx*y0 + ny*x0) - nx*v[2]*x0*y0*(ma - mb) - ny*v[1]*x0*y0*(ma - mb))/(-ma*nx*x0*y0 + ma*nx*y0 - ma*ny*x0*y0 + ma*ny*x0 + mb*nx*x0*y0 + mb*ny*x0*y0);
566  _b2[i] = (-ma*v[0]*(nx*y0 + ny*x0) + ny*v[1]*x0*y0*(ma - mb) + v[2]*(ma*nx*y0 - ma*ny*x0*y0 + ma*ny*x0 + mb*ny*x0*y0))/(-ma*nx*x0*y0 + ma*nx*y0 - ma*ny*x0*y0 + ma*ny*x0 + mb*nx*x0*y0 + mb*ny*x0*y0);
567  _b3[i] = (-ma*v[0]*(nx*y0 + ny*x0) + nx*v[2]*x0*y0*(ma - mb) + v[1]*(-ma*nx*x0*y0 + ma*nx*y0 + ma*ny*x0 + mb*nx*x0*y0))/(-ma*nx*x0*y0 + ma*nx*y0 - ma*ny*x0*y0 + ma*ny*x0 + mb*nx*x0*y0 + mb*ny*x0*y0);
568  grad_va_ref[0] = _a2[i];
569  grad_va_ref[1] = _a3[i];
570  grad_vb_ref[0] = _b2[i];
571  grad_vb_ref[1] = _b3[i];
572  for (int I=0;I<nSpace;I++)
573  for (int J=0; J<nSpace;J++)
574  {
575  grad_va[I] += inv_Jac[J*nSpace + I]*grad_va_ref[J];
576  grad_vb[I] += inv_Jac[J*nSpace + I]*grad_vb_ref[J];
577  }
578  _va_x[i] = grad_va[0];
579  _va_y[i] = grad_va[1];
580  _vb_x[i] = grad_vb[0];
581  _vb_y[i] = grad_vb[1];
582  }
583  }
584 
585  template<int nSpace, int nP, int nQ, int nEBQ>
586  inline int Simplex<nSpace,nP,nQ,nEBQ>::calculate(const double* phi_dof, const double* phi_nodes, const double* xi_r, double ma, double mb, bool isBoundary, bool scale)
587  {
588  //initialize phi_dof_corrected -- correction can only be actually computed on cut cells
589  for (unsigned int i=0; i < nN;i++)
590  phi_dof_corrected[i] = phi_dof[i];
591  int icase = _calculate_permutation(phi_dof, phi_nodes);//permuation, Jac,inv_Jac...
592  if(icase == 1)
593  {
594  for (unsigned int q=0; q < nQ; q++)
595  {
596  _H[q] = 1.0;
597  _ImH[q] = 0.0;
598  _D[q] = 0.0;
599  }
600  for (unsigned int ebq=0; ebq < nEBQ; ebq++)
601  {
602  _H_ebq[ebq] = 1.0;
603  _ImH_ebq[ebq] = 0.0;
604  _D_ebq[ebq] = 0.0;
605  }
606  return icase;
607  }
608  else if(icase == -1)
609  {
610  for (unsigned int q=0; q < nQ; q++)
611  {
612  _H[q] = 0.0;
613  _ImH[q] = 1.0;
614  _D[q] = 0.0;
615  }
616  for (unsigned int ebq=0; ebq < nEBQ; ebq++)
617  {
618  _H_ebq[ebq] = 0.0;
619  _ImH_ebq[ebq] = 1.0;
620  _D_ebq[ebq] = 0.0;
621  }
622  return icase;
623  }
624  if (quad_cut)
625  {
626  _calculate_cuts_quad();//THETA_* for quad cut in 3D
627  _calculate_normal_quad(phys_nodes_cut_quad_01,
628  phys_nodes_cut_quad_02,
629  phys_nodes_cut_quad_31,
630  phys_nodes_cut_quad_32,
631  level_set_normal);//normal to interface
632  }
633  else
634  {
635  _calculate_cuts();//X_0, array of interface cuts on reference simplex
636  _calculate_normal<nSpace>(phys_nodes_cut, level_set_normal);//normal to interface
637  }
638  double ma_scale,mb_scale;
639  if (scale)
640  {
641  //cek hack - 2D, pressure basis for discontinuous density
642  double jump_scale = level_set_normal[1],
643  m_average = 0.5*(ma + mb),
644  m_jump = 0.5*(mb - ma);
645  mb_scale = m_average + jump_scale*m_jump;//mb when jump_scale=1
646  ma_scale = m_average - jump_scale*m_jump;//ma when jump_scale=1
647  // double mb_scale=mb, ma_scale=ma;
648  //cek hack end
649  }
650  else
651  {
652  ma_scale = ma;
653  mb_scale = mb;
654  }
655  if (inside_out)
656  {
657  if (nN==3)
658  {
659  _calculate_basis_coefficients(mb_scale, ma_scale);
660  for (int i=0; i < 3; i++)
661  {
662  double tmp;
663  tmp = _va_x[i];
664  _va_x[i] = _vb_x[i];
665  _vb_x[i] = tmp;
666  tmp = _va_y[i];
667  _va_y[i] = _vb_y[i];
668  _vb_y[i] = tmp;
669  }
670  }
671  }
672  else
673  {
674  if (nN==3)
675  _calculate_basis_coefficients(ma_scale, mb_scale);
676  }
677  _correct_phi(phi_dof, phi_nodes);
678  _calculate_C();//coefficients of equiv poly
679  //compute the default affine map based on phi_nodes[0]
680  double Jac_0[nSpace*nSpace];
681  for(unsigned int i=0; i < nN - 1; i++)
682  for(unsigned int I=0; I < nSpace; I++)
683  Jac_0[I*nSpace+i] = phi_nodes[(1+i)*3 + I] - phi_nodes[I];
684 
685  if (not isBoundary)
686  {
687  for(unsigned int q=0; q < nQ; q++)
688  {
689  //Due to the permutation, the quadrature points on the reference may be rotated
690  //map reference to physical simplex, then back to permuted reference
691  register double x[nSpace], xi[nSpace];
692  //to physical coordinates
693  for (unsigned int I=0; I < nSpace; I++)
694  {
695  x[I]=phi_nodes[I];
696  for (unsigned int J=0; J < nSpace;J++)
697  {
698  x[I] += Jac_0[I*nSpace + J]*xi_r[q*3 + J];
699  }
700  }
701  //back to reference coordinates on possibly permuted
702  for (unsigned int I=0; I < nSpace; I++)
703  {
704  xi[I] = 0.0;
705  for (unsigned int J=0; J < nSpace; J++)
706  {
707  xi[I] += inv_Jac[I*nSpace + J]*(x[J] - nodes[J]);
708  }
709  }
710  if (nSpace == 1)
711  _calculate_polynomial_1D<nP>(xi,C_H,C_ImH,C_D,_H[q],_ImH[q],_D[q]);
712  else if (nSpace == 2)
713  {
714  _calculate_polynomial_2D<nP>(xi,C_H,C_ImH,C_D,_H[q],_ImH[q],_D[q]);
715  _calculate_basis(xi,&_va[q*nN],&_vb[q*nN]);
716  }
717  else if (nSpace == 3)
718  _calculate_polynomial_3D<nP>(xi,C_H,C_ImH,C_D,_H[q],_ImH[q],_D[q]);
719  }
720  set_quad(0);
721  }
722  else
723  {
724  for(unsigned int ebq=0; ebq < nEBQ; ebq++)
725  {
726  //Due to the permutation, the quadrature points on the reference may be rotated
727  //map reference to physical simplex, then back to permuted reference
728  register double x[nSpace], xi[nSpace];
729  //to physical coordinates
730  for (unsigned int I=0; I < nSpace; I++)
731  {
732  x[I]=phi_nodes[I];
733  for (unsigned int J=0; J < nSpace;J++)
734  {
735  x[I] += Jac_0[I*nSpace + J]*xi_r[ebq*3 + J];
736  }
737  }
738  //back to reference coordinates on possibly permuted
739  for (unsigned int I=0; I < nSpace; I++)
740  {
741  xi[I] = 0.0;
742  for (unsigned int J=0; J < nSpace; J++)
743  {
744  xi[I] += inv_Jac[I*nSpace + J]*(x[J] - nodes[J]);
745  }
746  }
747  if (nSpace == 1)
748  _calculate_polynomial_1D<nP>(xi,C_H,C_ImH,C_D,_H_ebq[ebq],_ImH_ebq[ebq],_D_ebq[ebq]);
749  else if (nSpace == 2)
750  {
751  _calculate_polynomial_2D<nP>(xi,C_H,C_ImH,C_D,_H_ebq[ebq],_ImH_ebq[ebq],_D_ebq[ebq]);
752  _calculate_basis(xi,&_va_ebq[ebq*nN],&_vb_ebq[ebq*nN]);
753  }
754  else if (nSpace == 3)
755  _calculate_polynomial_3D<nP>(xi,C_H,C_ImH,C_D,_H_ebq[ebq],_ImH_ebq[ebq],_D_ebq[ebq]);
756  }
757  set_boundary_quad(0);
758  }
759  if (inside_out)
760  for (unsigned int I=0; I<nSpace;I++)
761  level_set_normal[I]*=-1.0;
762  return icase;
763  }
764 
765  template<int nSpace, int nP, int nQ, int nEBQ>
767  {
768  public:
771  bool useExact;
774  {}
775 
776  inline int calculate(const double* phi_dof, const double* phi_nodes, const double* xi_r, double ma, double mb, bool isBoundary, bool scale)
777  {
778  //hack for testing
779  //return exact.calculate(phi_dof, phi_nodes, xi_r, ma, mb);
780  //
781  if(useExact)
782  return exact.calculate(phi_dof, phi_nodes, xi_r, ma, mb,isBoundary,scale);
783  else//for inexact just copy over local phi_dof
784  {
785  for (int i=0; i<exact.nN;i++)
786  exact.phi_dof_corrected[i] = phi_dof[i];
787  return 1;
788  }
789  }
790 
791  inline int calculate(const double* phi_dof, const double* phi_nodes, const double* xi_r, bool isBoundary)
792  {
793  return calculate(phi_dof, phi_nodes, xi_r, 1.0,1.0,isBoundary, false);
794  }
795 
796  inline double* get_normal()
797  {
798  if(useExact)
799  return exact.get_normal();
800  else
801  return regularized.get_normal();
802  }
803 
804  inline void set_quad(unsigned int q)
805  {
806  if(useExact)
807  exact.set_quad(q);
808  }
809 
810  inline void set_boundary_quad(unsigned int ebq)
811  {
812  if(useExact)
813  exact.set_boundary_quad(ebq);
814  }
815 
816  inline double H(double eps, double phi)
817  {
818  if(useExact)
819  return exact.H(eps, phi);
820  else
821  return regularized.H(eps, phi);
822  }
823 
824  inline double ImH(double eps, double phi)
825  {
826  if(useExact)
827  return exact.ImH(eps, phi);
828  else
829  return regularized.ImH(eps, phi);
830  }
831 
832  inline double D(double eps, double phi)
833  {
834  if(useExact)
835  return exact.D(eps, phi);
836  else
837  return regularized.D(eps, phi);
838  }
839  inline double VA(int i)
840  {
841  if(useExact)
842  return exact.VA(i);
843  else
844  return regularized.VA(i);
845  }
846  inline double VA_x(int i)
847  {
848  if(useExact)
849  return exact.VA_x(i);
850  else
851  return regularized.VA_x(i);
852  }
853  inline double VA_y(int i)
854  {
855  if(useExact)
856  return exact.VA_y(i);
857  else
858  return regularized.VA_y(i);
859  }
860  inline double VA_z(int i)
861  {
862  if(useExact)
863  return exact.VA_z(i);
864  else
865  return regularized.VA_z(i);
866  }
867  inline double VB(int i)
868  {
869  if(useExact)
870  return exact.VB(i);
871  else
872  return regularized.VB(i);
873  }
874  inline double VB_x(int i)
875  {
876  if(useExact)
877  return exact.VB_x(i);
878  else
879  return regularized.VB_x(i);
880  }
881  inline double VB_y(int i)
882  {
883  if(useExact)
884  return exact.VB_y(i);
885  else
886  return regularized.VB_y(i);
887  }
888  inline double VB_z(int i)
889  {
890  if(useExact)
891  return exact.VB_z(i);
892  else
893  return regularized.VB_z(i);
894  }
895  };
896 }//equivalent_polynomials
897 
898 #endif
equivalent_polynomials::GeneralizedFunctions_mix::ImH
double ImH(double eps, double phi)
Definition: equivalent_polynomials.h:824
equivalent_polynomials::GeneralizedFunctions_mix::get_normal
double * get_normal()
Definition: equivalent_polynomials.h:796
equivalent_polynomials::Regularized::D
double D(double eps, double phi)
Definition: equivalent_polynomials.h:50
equivalent_polynomials::Simplex::D
double D(double eps, double phi)
Definition: equivalent_polynomials.h:151
equivalent_polynomials::GeneralizedFunctions_mix::GeneralizedFunctions_mix
GeneralizedFunctions_mix(bool useExact=true)
Definition: equivalent_polynomials.h:772
equivalent_polynomials::GeneralizedFunctions_mix::VB_x
double VB_x(int i)
Definition: equivalent_polynomials.h:874
equivalent_polynomials::GeneralizedFunctions_mix::VB_y
double VB_y(int i)
Definition: equivalent_polynomials.h:881
equivalent_polynomials::Simplex::get_H
double * get_H()
Definition: equivalent_polynomials.h:146
equivalent_polynomials::Regularized::VA_y
double VA_y(int i)
Definition: equivalent_polynomials.h:63
equivalent_polynomials::Simplex::set_boundary_quad
void set_boundary_quad(unsigned int ebq)
Definition: equivalent_polynomials.h:122
equivalent_polynomials::Regularized
Definition: equivalent_polynomials.h:15
equivalent_polynomials::Regularized::get_normal
double * get_normal()
Definition: equivalent_polynomials.h:25
equivalent_polynomials::Simplex::VA_y
double VA_y(int i)
Definition: equivalent_polynomials.h:154
equivalent_polynomials::Regularized::VB_y
double VB_y(int i)
Definition: equivalent_polynomials.h:67
equivalent_polynomials::Simplex::H
double H(double eps, double phi)
Definition: equivalent_polynomials.h:149
equivalent_polynomials::GeneralizedFunctions_mix::VA_z
double VA_z(int i)
Definition: equivalent_polynomials.h:860
equivalent_polynomials::Regularized::VA
double VA(int i)
Definition: equivalent_polynomials.h:61
equivalent_polynomials::Regularized::set_quad
void set_quad(unsigned int q)
Definition: equivalent_polynomials.h:29
equivalent_polynomials::Simplex::inside_out
bool inside_out
Definition: equivalent_polynomials.h:164
q
Double q
Definition: Headers.h:81
equivalent_polynomials::Simplex::VB
double VB(int i)
Definition: equivalent_polynomials.h:156
equivalent_polynomials::Simplex::VA_z
double VA_z(int i)
Definition: equivalent_polynomials.h:155
equivalent_polynomials::Simplex::ImH
double ImH(double eps, double phi)
Definition: equivalent_polynomials.h:150
phi
Double phi
Definition: Headers.h:76
equivalent_polynomials::GeneralizedFunctions_mix::calculate
int calculate(const double *phi_dof, const double *phi_nodes, const double *xi_r, bool isBoundary)
Definition: equivalent_polynomials.h:791
equivalent_polynomials::Simplex::get_normal
double * get_normal()
Definition: equivalent_polynomials.h:160
equivalent_polynomials::Regularized::Regularized
Regularized(bool useExact=false)
Definition: equivalent_polynomials.h:17
equivalent_polynomials::Simplex::VB_z
double VB_z(int i)
Definition: equivalent_polynomials.h:159
equivalent_polynomials::GeneralizedFunctions_mix::VA_y
double VA_y(int i)
Definition: equivalent_polynomials.h:853
equivalent_polynomials::Regularized::VA_z
double VA_z(int i)
Definition: equivalent_polynomials.h:64
equivalent_polynomials::Simplex::set_quad
void set_quad(unsigned int q)
Definition: equivalent_polynomials.h:98
equivalent_polynomials::Regularized::VA_x
double VA_x(int i)
Definition: equivalent_polynomials.h:62
equivalent_polynomials::Regularized::VB_z
double VB_z(int i)
Definition: equivalent_polynomials.h:68
equivalent_polynomials::Regularized::VB_x
double VB_x(int i)
Definition: equivalent_polynomials.h:66
v
Double v
Definition: Headers.h:95
equivalent_polynomials::Simplex
Definition: equivalent_polynomials.h:73
equivalent_polynomials::GeneralizedFunctions_mix::set_quad
void set_quad(unsigned int q)
Definition: equivalent_polynomials.h:804
equivalent_polynomials::Regularized::VB
double VB(int i)
Definition: equivalent_polynomials.h:65
equivalent_polynomials::GeneralizedFunctions_mix::calculate
int calculate(const double *phi_dof, const double *phi_nodes, const double *xi_r, double ma, double mb, bool isBoundary, bool scale)
Definition: equivalent_polynomials.h:776
equivalent_polynomials::_calculate_normal_quad
void _calculate_normal_quad(double *phys_nodes_cut_quad_01, double *phys_nodes_cut_quad_02, double *phys_nodes_cut_quad_31, double *phys_nodes_cut_quad_32, double *level_set_normal)
Definition: equivalent_polynomials_utils.h:70
equivalent_polynomials::Simplex::VB_x
double VB_x(int i)
Definition: equivalent_polynomials.h:157
equivalent_polynomials
Definition: equivalent_polynomials.h:12
equivalent_polynomials::Regularized::set_boundary_quad
void set_boundary_quad(unsigned int ebq)
Definition: equivalent_polynomials.h:31
equivalent_polynomials::GeneralizedFunctions_mix::exact
Simplex< nSpace, nP, nQ, nEBQ > exact
Definition: equivalent_polynomials.h:770
equivalent_polynomials::Simplex::nN
static const unsigned int nN
Definition: equivalent_polynomials.h:165
equivalent_polynomials::Regularized::calculate
int calculate(const double *phi_dof, const double *phi_nodes, const double *xi_r, double ma, double mb, bool isBoundary, bool scale)
Definition: equivalent_polynomials.h:19
equivalent_polynomials::GeneralizedFunctions_mix::regularized
Regularized< nSpace, nP, nQ, nEBQ > regularized
Definition: equivalent_polynomials.h:769
equivalent_polynomials::GeneralizedFunctions_mix::set_boundary_quad
void set_boundary_quad(unsigned int ebq)
Definition: equivalent_polynomials.h:810
equivalent_polynomials::Regularized::calculate
int calculate(const double *phi_dof, const double *phi_nodes, const double *xi_r, bool isBoundary)
Definition: equivalent_polynomials.h:21
equivalent_polynomials::Simplex::quad_cut
bool quad_cut
Definition: equivalent_polynomials.h:164
equivalent_polynomials::GeneralizedFunctions_mix
Definition: equivalent_polynomials.h:767
equivalent_polynomials::Regularized::ImH
double ImH(double eps, double phi)
Definition: equivalent_polynomials.h:46
equivalent_polynomials::Simplex::get_D
double * get_D()
Definition: equivalent_polynomials.h:148
equivalent_polynomials::GeneralizedFunctions_mix::VA_x
double VA_x(int i)
Definition: equivalent_polynomials.h:846
equivalent_polynomials::Simplex::VA
double VA(int i)
Definition: equivalent_polynomials.h:152
equivalent_polynomials::Simplex::VA_x
double VA_x(int i)
Definition: equivalent_polynomials.h:153
equivalent_polynomials_utils.h
equivalent_polynomials::Simplex::VB_y
double VB_y(int i)
Definition: equivalent_polynomials.h:158
equivalent_polynomials::Simplex::phi_dof_corrected
double phi_dof_corrected[nN]
Definition: equivalent_polynomials.h:166
equivalent_polynomials::Simplex::calculate
int calculate(const double *phi_dof, const double *phi_nodes, const double *xi_r, double ma, double mb, bool isBoundary, bool scale)
Definition: equivalent_polynomials.h:586
equivalent_polynomials::Simplex::calculate
int calculate(const double *phi_dof, const double *phi_nodes, const double *xi_r, bool isBoundary)
Definition: equivalent_polynomials.h:93
equivalent_polynomials::GeneralizedFunctions_mix::VA
double VA(int i)
Definition: equivalent_polynomials.h:839
equivalent_polynomials::Simplex::Simplex
Simplex(bool useExact=true)
Definition: equivalent_polynomials.h:75
equivalent_polynomials::GeneralizedFunctions_mix::useExact
bool useExact
Definition: equivalent_polynomials.h:771
equivalent_polynomials::GeneralizedFunctions_mix::VB
double VB(int i)
Definition: equivalent_polynomials.h:867
equivalent_polynomials::Regularized::H
double H(double eps, double phi)
Definition: equivalent_polynomials.h:33
equivalent_polynomials_coefficients.h
equivalent_polynomials::GeneralizedFunctions_mix::H
double H(double eps, double phi)
Definition: equivalent_polynomials.h:816
equivalent_polynomials::Simplex::get_ImH
double * get_ImH()
Definition: equivalent_polynomials.h:147
equivalent_polynomials::GeneralizedFunctions_mix::D
double D(double eps, double phi)
Definition: equivalent_polynomials.h:832
equivalent_polynomials::GeneralizedFunctions_mix::VB_z
double VB_z(int i)
Definition: equivalent_polynomials.h:888
equivalent_polynomials_coefficients_quad.h