PRAgMaTIc  master
fit_ellipsoid_3d.py
Go to the documentation of this file.
1 from __future__ import print_function
2 from sympy import *
3 import sys
4 
5 # Lets work this out symbolically first and perform python unit test.
6 
7 # Equation for the ellipsoid can be written sxx*x^2 + syy*y^2 + szz*z^2 + syz*y*z + sxz*x*z + sxy*x*y = 1,
8 
9 sxx,syy,szz,syz,sxz,sxy=symbols("sxx,syy,szz,syz,sxz,sxy")
10 S=Matrix([[sxx],[syy],[szz],[syz],[sxz],[sxy]])
11 
12 x,y,z=symbols('x,y,z')
13 
14 P=Matrix([[x**2, y**2, z**2, y*z, x*z, x*y]])
15 
16 A = P.transpose()*P
17 b = P.transpose()*Matrix([[1]])
18 
19 # Sphere of radius sqrt(3). Sxx=1/h^2, therefore Sxx=1/3
20 sphere = {x:1, y:1, z:1,
21  sxx:Rational(1,3),syy:Rational(1, 3),szz:Rational(1, 3),syz:0,sxz:0,sxy:0}
22 
23 if (A*S).evalf(subs=sphere)==b.evalf(subs=sphere):
24  print("pass")
25 else:
26  print("fail")
27  sys.exit(-1)
28 
29 # Move onto code generation.
30 
31 pyname=sys.argv[0].split('/')[-1]
32 
33 # Write source file
34 cxxname=pyname[:-3]+".cpp"
35 
36 src="""
37 /* Start of code generated by %s. Warning - be careful about modifying
38  any of the generated code directly. Any changes/fixes should be done
39  in the code generation script generation.
40  */
41 """%(pyname)
42 
43 src += """
44 void fit_ellipsoid(int i, real_t *sm){
45  Eigen::Matrix<double, 6, 6> A = Eigen::Matrix<real_t, 6, 6>::Zero(6,6);
46  Eigen::Matrix<double, 6, 1> b = Eigen::Matrix<real_t, 6, 1>::Zero(6);
47 
48  std::vector<index_t> nodes = _mesh->NNList[i];
49  nodes.push_back(i);
50 
51  for(typename std::vector<index_t>::const_iterator it=nodes.begin();it!=nodes.end();++it){
52  const real_t *X0=_mesh->get_coords(*it);
53  real_t x0=X0[0], y0=X0[1], z0=X0[2];
54  assert(std::isfinite(x0));
55  assert(std::isfinite(y0));
56  assert(std::isfinite(z0));
57 
58  for(typename std::vector<index_t>::const_iterator n=_mesh->NNList[*it].begin();n!=_mesh->NNList[*it].end();++n){
59  if(*n<=*it)
60  continue;
61 
62  const real_t *X=_mesh->get_coords(*n);
63  real_t x=X[0]-x0, y=X[1]-y0, z=X[2]-z0;
64 
65  assert(std::isfinite(x));
66  assert(std::isfinite(y));
67  assert(std::isfinite(z));
68  if(x<0){
69  x*=-1;
70  y*=-1;
71  z*=-1;
72  }
73  """
74 
75 for i in range(6):
76  src+=" "
77  for j in range(6):
78  src+="A[%d]+="%(i*6+j)+ccode(A[i,j], contract=False)+"; "
79  src+="\n"
80 
81 for i in range(6):
82  src+="b[%d]+="%(i)+ccode(b[i], contract=False)+";\n"
83 
84 src+="""
85  }
86  }
87 
88  Eigen::Matrix<double, 6, 1> S = Eigen::Matrix<real_t, 6, 1>::Zero(6);
89 
90  A.svd().solve(b, &S);
91 
92  if(_mesh->NNList[i].size()>=6){
93  sm[0] = S[0]; sm[1] = S[5]; sm[2] = S[4];
94  sm[3] = S[1]; sm[4] = S[3];
95  sm[5] = S[2];
96  }else{
97  sm[0] = S[0]; sm[1] = 0; sm[2] = 0;
98  sm[3] = S[1]; sm[4] = 0;
99  sm[5] = S[2];
100  }
101 
102  return;
103 }
104 
105 /* End of code generated by %s. Warning - be careful about
106  modifying any of the generated code directly. Any changes/fixes
107  should be done in the code generation script generation.*/\n"""%pyname
108 
109 cxxfile = open(cxxname, "w")
110 cxxfile.write(src)
111 cxxfile.close()