1 #ifndef EQUIVALENT_POLYNOMIALS_H
2 #define EQUIVALENT_POLYNOMIALS_H
13 template<
int nSpace,
int nP,
int nQ,
int nEBQ>
19 inline int calculate(
const double* phi_dof,
const double* phi_nodes,
const double* xi_r,
double ma,
double mb,
bool isBoundary,
bool scale)
21 inline int calculate(
const double* phi_dof,
const double* phi_nodes,
const double* xi_r,
bool isBoundary)
23 return calculate(phi_dof, phi_nodes, xi_r, 1.0,1.0, isBoundary,
false);
33 inline double H(
double eps,
double phi)
43 h = 0.5*(1.0 +
phi/eps + sin(M_PI*
phi/eps)/M_PI);
46 inline double ImH(
double eps,
double phi)
48 return 1.0-
H(eps,
phi);
50 inline double D(
double eps,
double phi)
58 d = 0.5*(1.0 + cos(M_PI*
phi/eps))/eps;
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;};
71 template<
int nSpace,
int nP,
int nQ,
int nEBQ>
80 assert(nDOF == (nP+1)*(nP+2)/2);
82 assert(nDOF == (nP+1)*(nP+2)*(nP+3)/6);
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;
91 inline int calculate(
const double* phi_dof,
const double* phi_nodes,
const double* xi_r,
double ma,
double mb,
bool isBoundary,
bool scale);
93 inline int calculate(
const double* phi_dof,
const double* phi_nodes,
const double* xi_r,
bool isBoundary)
95 return calculate(phi_dof, phi_nodes, xi_r, 1.0,1.0, isBoundary,
false);
115 for(
int i=0;i<
nN;i++)
117 _va_q[i] = _va[
q*
nN+i];
118 _vb_q[i] = _vb[
q*
nN+i];
128 _H_q = _ImH_ebq[ebq];
129 _ImH_q = _H_ebq[ebq];
135 _ImH_q = _ImH_ebq[ebq];
139 for(
int i=0;i<
nN;i++)
141 _va_q[i] = _va_ebq[ebq*
nN+i];
142 _vb_q[i] = _vb_ebq[ebq*
nN+i];
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];};
162 return level_set_normal;
165 static const unsigned int nN=nSpace+1;
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],
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];
186 inline void _calculate_basis_coefficients(
const double ma,
const double mb);
187 inline void _calculate_basis(
const double* xi,
double* va,
double* vb)
190 for (
int i=0;i<
nN;i++)
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];
198 template<
int nSpace,
int nP,
int nQ,
int nEBQ>
199 inline void Simplex<nSpace,nP,nQ,nEBQ>::_calculate_C()
201 register double b_H[nDOF], b_ImH[nDOF], b_dH[nDOF*nSpace], b_D[nDOF*nSpace];
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]],
212 for (
unsigned int i=0; i < nDOF; i++)
217 for (
unsigned int i=0; i < nDOF; i++)
222 for (
unsigned int j=0; j < nDOF; j++)
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];
238 _calculate_b<nSpace,nP>(X_0, b_H, b_ImH, b_dH);
240 register double Jt_dphi_dx[nSpace];
241 for (
unsigned int I=0; I < nSpace; I++)
244 for(
unsigned int J=0; J < nSpace; J++)
245 Jt_dphi_dx[I] += Jac[J*nSpace + I]*level_set_normal[J];
247 for (
unsigned int i=0; i < nDOF; i++)
252 for (
unsigned int j=0; j < nDOF; j++)
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++)
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]);
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)
269 int p_i, pcount=0, n_i, ncount=0, z_i, zcount=0;
273 const double eps=1.0e-8;
274 for (
unsigned int i=0; i < nN; i++)
282 else if(phi_dof[i] < -eps)
298 else if(ncount == nN)
351 else if (nSpace == 3 && pcount == 2 && ncount == 2)
360 std::cout<<
"zcount "<<zcount<<
" >= "<<nN-1<<std::endl;
361 assert(zcount < nN-1);
369 for(
unsigned int i=0; i < nN; i++)
371 permutation[i] = (root_node+i)%nN;
375 if(phi_dof[permutation[nN-1]] > 0.0)
377 int tmp=permutation[nN-1];
378 if (phi_dof[permutation[nN-2]] < 0.0)
380 permutation[nN-1] = permutation[nN-2];
381 permutation[nN-2] = tmp;
383 else if (phi_dof[permutation[nN-3]] < 0.0)
385 permutation[nN-1] = permutation[nN-3];
386 permutation[nN-3] = tmp;
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);
396 for(
unsigned int i=0; i < nN; i++)
398 phi[i] = phi_dof[permutation[i]];
399 for(
unsigned int I=0; I < 3; I++)
401 nodes[i*3 + I] = phi_nodes[permutation[i]*3 + I];
404 double JacTest[nSpace*nSpace];
405 for(
unsigned int I=0; I < nSpace; I++)
407 for(
unsigned int i=0; i < nN - 1; i++)
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];
413 det_Jac = det<nSpace>(Jac);
414 double det_JacTest = det<nSpace>(JacTest);
421 double tmp = permutation[2];
422 permutation[2] = permutation[1];
423 permutation[1] = tmp;
427 double tmp = permutation[nN-1];
428 permutation[nN-1] = permutation[nN-2];
429 permutation[nN-2] = tmp;
431 for(
unsigned int i=0; i < nN; i++)
433 phi[i] = phi_dof[permutation[i]];
434 for(
unsigned int I=0; I < 3; I++)
436 nodes[i*3 + I] = phi_nodes[permutation[i]*3 + I];
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);
447 inv<nSpace>(Jac, inv_Jac);
451 template<
int nSpace,
int nP,
int nQ,
int nEBQ>
452 inline void Simplex<nSpace,nP,nQ,nEBQ>::_calculate_cuts()
454 const double eps=1.0e-8;
455 for (
unsigned int i=0; i < nN-1;i++)
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++)
464 phys_nodes_cut[i*3 + I] = (1-X_0[i])*nodes[I] + X_0[i]*nodes[(1+i)*3 + I];
469 assert(
phi[i+1] < eps);
471 for (
unsigned int I=0; I < 3; I++)
473 phys_nodes_cut[i*3 + I] = nodes[(1+i)*3 + I];
479 template<
int nSpace,
int nP,
int nQ,
int nEBQ>
480 inline void Simplex<nSpace,nP,nQ,nEBQ>::_calculate_cuts_quad()
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))
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])));
494 for (
unsigned int I=0; I < 3; I++)
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];
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)
506 register double cut_barycenter[3] ={0.,0.,0.};
507 const double one_by_nNm1 = 1.0/(nN-1.0);
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]);
518 for (
unsigned int i=0; i < nN-1;i++)
520 for (
unsigned int I=0; I < nSpace; I++)
521 cut_barycenter[I] += phys_nodes_cut[i*3+I]*one_by_nNm1;
524 for (
unsigned int i=0; i < nN;i++)
526 phi_dof_corrected[i]=0.0;
527 for (
unsigned int I=0; I < nSpace; I++)
529 phi_dof_corrected[i] += level_set_normal[I]*(phi_nodes[i*3+I] - cut_barycenter[I]);
532 if (phi_dof_corrected[i]*phi_dof[i] < 0.0)
534 phi_dof_corrected[i]*=-1.0;
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)
544 double nx=0.0,ny=0.0;
545 for (
int J=0;J<2;J++)
547 nx += inv_Jac[0*2+J]*level_set_normal[J];
548 ny += inv_Jac[1*2+J]*level_set_normal[J];
552 double vall[9]={1.,0.,0.,
555 for (
int j=0; j < 3; j++)
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];
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++)
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];
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];
585 template<
int nSpace,
int nP,
int nQ,
int nEBQ>
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);
594 for (
unsigned int q=0;
q < nQ;
q++)
600 for (
unsigned int ebq=0; ebq < nEBQ; ebq++)
610 for (
unsigned int q=0;
q < nQ;
q++)
616 for (
unsigned int ebq=0; ebq < nEBQ; ebq++)
626 _calculate_cuts_quad();
628 phys_nodes_cut_quad_02,
629 phys_nodes_cut_quad_31,
630 phys_nodes_cut_quad_32,
636 _calculate_normal<nSpace>(phys_nodes_cut, level_set_normal);
638 double ma_scale,mb_scale;
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;
646 ma_scale = m_average - jump_scale*m_jump;
659 _calculate_basis_coefficients(mb_scale, ma_scale);
660 for (
int i=0; i < 3; i++)
675 _calculate_basis_coefficients(ma_scale, mb_scale);
677 _correct_phi(phi_dof, phi_nodes);
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];
687 for(
unsigned int q=0;
q < nQ;
q++)
691 register double x[nSpace], xi[nSpace];
693 for (
unsigned int I=0; I < nSpace; I++)
696 for (
unsigned int J=0; J < nSpace;J++)
698 x[I] += Jac_0[I*nSpace + J]*xi_r[
q*3 + J];
702 for (
unsigned int I=0; I < nSpace; I++)
705 for (
unsigned int J=0; J < nSpace; J++)
707 xi[I] += inv_Jac[I*nSpace + J]*(x[J] - nodes[J]);
711 _calculate_polynomial_1D<nP>(xi,C_H,C_ImH,C_D,_H[
q],_ImH[
q],_D[
q]);
712 else if (nSpace == 2)
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]);
717 else if (nSpace == 3)
718 _calculate_polynomial_3D<nP>(xi,C_H,C_ImH,C_D,_H[
q],_ImH[
q],_D[
q]);
724 for(
unsigned int ebq=0; ebq < nEBQ; ebq++)
728 register double x[nSpace], xi[nSpace];
730 for (
unsigned int I=0; I < nSpace; I++)
733 for (
unsigned int J=0; J < nSpace;J++)
735 x[I] += Jac_0[I*nSpace + J]*xi_r[ebq*3 + J];
739 for (
unsigned int I=0; I < nSpace; I++)
742 for (
unsigned int J=0; J < nSpace; J++)
744 xi[I] += inv_Jac[I*nSpace + J]*(x[J] - nodes[J]);
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)
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]);
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]);
757 set_boundary_quad(0);
760 for (
unsigned int I=0; I<nSpace;I++)
761 level_set_normal[I]*=-1.0;
765 template<
int nSpace,
int nP,
int nQ,
int nEBQ>
776 inline int calculate(
const double* phi_dof,
const double* phi_nodes,
const double* xi_r,
double ma,
double mb,
bool isBoundary,
bool scale)
782 return exact.calculate(phi_dof, phi_nodes, xi_r, ma, mb,isBoundary,scale);
785 for (
int i=0; i<
exact.nN;i++)
786 exact.phi_dof_corrected[i] = phi_dof[i];
791 inline int calculate(
const double* phi_dof,
const double* phi_nodes,
const double* xi_r,
bool isBoundary)
793 return calculate(phi_dof, phi_nodes, xi_r, 1.0,1.0,isBoundary,
false);
799 return exact.get_normal();
813 exact.set_boundary_quad(ebq);
816 inline double H(
double eps,
double phi)
824 inline double ImH(
double eps,
double phi)
832 inline double D(
double eps,
double phi)
839 inline double VA(
int i)
849 return exact.VA_x(i);
856 return exact.VA_y(i);
863 return exact.VA_z(i);
867 inline double VB(
int i)
877 return exact.VB_x(i);
884 return exact.VB_y(i);
891 return exact.VB_z(i);