muMECH  1.0
esei_ProlateSpheroid.cpp
Go to the documentation of this file.
1 //********************************************************************************************************
2 // code: ### ### ##### #### ## ##
3 // ## ## ######## ## ## ## ## ##
4 // ## ## ## ## ## ### ## ######
5 // ## ## ## ## ## ## ## ## ##
6 // ##### ## ## ##### #### ## ##
7 // ##
8 //
9 // name: eshelbySoluEllipticIntegralsProlateSpheroid.cpp
10 // author(s): Jan Novak, Tomas Janda
11 // language: C, C++
12 // license: This program is free software; you can redistribute it and/or modify
13 // it under the terms of the GNU Lesser General Public License as published by
14 // the Free Software Foundation; either version 2 of the License, or
15 // (at your option) any later version.
16 //
17 // This program is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 // GNU Lesser General Public License for more details.
21 //
22 // You should have received a copy of the GNU Lesser General Public License
23 // along with this program; if not, write to the Free Software
24 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 //********************************************************************************************************
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <math.h>
30 #include <cmath>
31 #include <iostream>
32 
33 #include "macros.h"
34 #include "esei_ProlateSpheroid.h"
35 #include "eshelbySoluLambda.h"
36 #include "legendreIntegrals.h"
37 #include "elementaryFunctions.h"
38 #include "inclusion.h"
39 
40 
41 namespace mumech {
42 
43 // Function gives the values of Ferers-Dysons integrals
44 // Last edit: 11-Sep-2013
45 void eshelbySoluEllipticIntegralsProlateSpheroid::giveEllipticIntegrals(double J[13], double lambda, bool intpoint)
46 {
47 #ifdef DEBUG
48  if (! (I->a[0] > I->a [1] && I->a[1] == I->a[2] && I->a[2] > 0.0)) _errorr("Semiaxes are not OK.");
49 #endif
50 
51  double a1 = I->a[0];
52  double a3 = I->a[2];
53 
54  J[0] = 0.0;
55 
56  J[2] = this->I2(a1, a3, lambda, intpoint); // I2
57  J[1] = this->I1(a1, a3, J[2], lambda, intpoint); // I1
58  J[3] = this->I3(J[2]); // I3
59 
60  // (Order changed due to sequential evaluation I13 -> I12 -> I11)
61  J[6] = this->I13(a1, a3, J[1], J[3]); // I13
62  J[5] = this->I12(J[6]); // I12
63  J[4] = this->I11(a1, a3, J[6], lambda, intpoint); // I11
64 
65  double I33 = this->I33(a1, a3, J[6], lambda, intpoint);
66 
67  J[7] = J[5]; // I21
68  J[8] = this->I22(I33); // I22
69  J[9] = this->I23(I33); // I23
70 
71  J[10] = J[6]; // I31
72  J[11] = J[9]; // I32
73  J[12] = I33; // I33
74 }
75 
76 // Function gives the derivatives of Ferers-Dysons integrals
77 // Last edit: 11-Sep-2013
79 {
80  if (intpoint) _errorr("derivatives are 0, this function should not be called");
81 
82  double ndiff = I->ndiff_1;
83 
84  // NUMERICAL DERIVATIVES (using REAL ARGUMENTS)
85 
86  // Get perturbated points and their lambdas
87  double lambdas[NUM_PERTURB];
88  this->getPerturbatedLambdas(lambdas, point->loc_x);
89 
90  // Create and fill a two dimensional array containing values of J-integrals at perturbated points.
91  const int NUM_ELLIP_INT = 13;
92  double J_pert[NUM_PERTURB][NUM_ELLIP_INT]; // All perturbations of all elliptical integrals.
93  for (int i = 0; i < NUM_PERTURB; i++) // For each perturbated point
94  this->giveEllipticIntegrals(J_pert[i], lambdas[i], intpoint); // Get elliptical integrals for lambda of perturbated point.
95 
96  // Compute numerial derivatives of first and second order of J_i integrals.
97  for (int i = 0; i < 3; i++) // For each elliptic integral Ji
98  {
99  // See types.c, section "Derivatives of Ferers-Dysons' integrals".
100  // Ji_j = dJi[3*i+j-4], i,j=1..3.
101  point->dJi[3*i] = (J_pert[_Xp_][i+1] - J_pert[_Xm_][i+1]) / (2.0 * ndiff);
102  point->dJi[3*i+1] = (J_pert[_Yp_][i+1] - J_pert[_Ym_][i+1]) / (2.0 * ndiff);
103  point->dJi[3*i+2] = (J_pert[_Zp_][i+1] - J_pert[_Zm_][i+1]) / (2.0 * ndiff);
104 
105  // See types.c, section "Derivatives of Ferers-Dysons' integrals".
106  // Ji_jk = ddJi[9*i+3*j+k-13], i,j,k=1..3.
107  point->ddJi[9*i] = (J_pert[_Xp_][i+1] - 2.0 * J_pert[_CENTER_][i+1] + J_pert[_Xm_][i+1]) / (ndiff * ndiff); // d^2f(x,y,z)/dx^2 = (f(x+h,y,z) - 2*f(x,y,z) + f(x-h,y,z)) / h^2
108  point->ddJi[9*i+1] = (J_pert[_XpYp_][i+1] - J_pert[_XpYm_][i+1] - J_pert[_XmYp_][i+1] + J_pert[_XmYm_][i+1]) / (4.0*ndiff*ndiff); // d^2f(x,y,z)/dxdy = (f(x+h,y+h,z) - f(x+h,y-h,z) - f(x-h,y+h,z) + f(x-h,y-h,z)) / (4*h^2)
109  point->ddJi[9*i+2] = (J_pert[_XpZp_][i+1] - J_pert[_XpZm_][i+1] - J_pert[_XmZp_][i+1] + J_pert[_XmZm_][i+1]) / (4.0*ndiff*ndiff);
110 
111  point->ddJi[9*i+3] = point->ddJi[9*i+1];
112  point->ddJi[9*i+4] = (J_pert[_Yp_][i+1] - 2.0 * J_pert[_CENTER_][i+1] + J_pert[_Ym_][i+1]) / (ndiff * ndiff);
113  point->ddJi[9*i+5] = (J_pert[_YpZp_][i+1] - J_pert[_YpZm_][i+1] - J_pert[_YmZp_][i+1] + J_pert[_YmZm_][i+1]) / (4.0*ndiff*ndiff);
114 
115  point->ddJi[9*i+6] = point->ddJi[9*i+2];
116  point->ddJi[9*i+7] = point->ddJi[9*i+5];
117  point->ddJi[9*i+8] = (J_pert[_Zp_][i+1] - 2.0 * J_pert[_CENTER_][i+1] + J_pert[_Zm_][i+1]) / (ndiff * ndiff);
118  }
119 
120  // Compute numerial derivatives of first and second order of J_ij integrals.
121  for (int i = 0; i < 9; i++) // For each elliptic integral Jij
122  {
123  // See types.c, section "Derivatives of Ferers-Dysons' integrals".
124  // Jij_k = dJij[9*k+3*i+j-13], i,j,k=1..3.
125  point->dJij[i] = (J_pert[_Xp_][i+4] - J_pert[_Xm_][i+4]) / (2.0 * ndiff);
126  point->dJij[i+9] = (J_pert[_Yp_][i+4] - J_pert[_Ym_][i+4]) / (2.0 * ndiff);
127  point->dJij[i+18] = (J_pert[_Zp_][i+4] - J_pert[_Zm_][i+4]) / (2.0 * ndiff);
128 
129  // See types.c, section "Derivatives of Ferers-Dysons' integrals".
130  // Jij_kl = ddJi[27*i+9*j+3*k+l-40] i,j,k,l=1..3.
131  point->ddJij[9*i] = (J_pert[_Xp_][i+4] - 2.0 * J_pert[_CENTER_][i+4] + J_pert[_Xm_][i+4]) / (ndiff * ndiff);
132  point->ddJij[9*i+1] = (J_pert[_XpYp_][i+4] - J_pert[_XpYm_][i+4] - J_pert[_XmYp_][i+4] + J_pert[_XmYm_][i+4]) / (4.0*ndiff*ndiff);
133  point->ddJij[9*i+2] = (J_pert[_XpZp_][i+4] - J_pert[_XpZm_][i+4] - J_pert[_XmZp_][i+4] + J_pert[_XmZm_][i+4]) / (4.0*ndiff*ndiff);
134 
135  point->ddJij[9*i+3] = point->ddJij[9*i+1];
136  point->ddJij[9*i+4] = (J_pert[_Yp_][i+4] - 2.0 * J_pert[_CENTER_][i+4] + J_pert[_Ym_][i+4]) / (ndiff * ndiff);
137  point->ddJij[9*i+5] = (J_pert[_YpZp_][i+4] - J_pert[_YpZm_][i+4] - J_pert[_YmZp_][i+4] + J_pert[_YmZm_][i+4]) / (4.0*ndiff*ndiff);
138 
139  point->ddJij[9*i+6] = point->ddJij[9*i+2];
140  point->ddJij[9*i+7] = point->ddJij[9*i+5];
141  point->ddJij[9*i+8] = (J_pert[_Zp_][i+4] - 2.0 * J_pert[_CENTER_][i+4] + J_pert[_Zm_][i+4]) / (ndiff * ndiff);
142  }
143  //}
144  //else _errorr("point position is not defined");
145 }
146 
147 
148 // --------------------------------------------------------------------------
149 // PROTECTED FUNCTIONS
150 
151 // Function gives the solution of the integral I
152 // last edit: 11-Sep-2013
153 double eshelbySoluEllipticIntegralsProlateSpheroid::eI( double a[3], double k, double Theta, double mult )
154 {
155  double a1 = a[0], a3 = a[2];
156  legendreIntegrals ellInt;
157 
158  return( mult * ellInt.ellf( Theta, k ) / sqrt( SQR( a1 ) - SQR( a3 ) ) );
159 }
160 
161 // Function gives the solution of the integral I_1
162 // Last edit: 11-Sep-2013
163 double eshelbySoluEllipticIntegralsProlateSpheroid::I1(double a1, double a3, double I2, double lambda, bool intpoint)
164 {
165  if (intpoint) // Internal points
166  {
167  // Mura (11.29)
168  return _4PI_ - 2.0 * I2;
169  }
170  else // External points
171  {
172  // Mura (12.22)
173  double b = get_b(a1, a3, lambda);
174  double d = get_d(a1, a3, lambda);
175  return _4PI_ * a1 * SQR(a3) * (acosh(b) - d / b) / pow(SQR(a1) - SQR(a3), 3.0 / 2.0);
176  }
177 }
178 
179 // Function gives the solution of the integral I_2
180 // Last edit: 11-Sep-2013
181 double eshelbySoluEllipticIntegralsProlateSpheroid::I2(double a1, double a3, double lambda, bool intpoint)
182 {
183  if (intpoint) // Internal points
184  {
185  // Mura (11.29)
186  return 2.0 * PI * a1 * SQR(a3) / pow(SQR(a1) - SQR(a3), 3.0 / 2.0) * (a1 / a3 * sqrt(SQR(a1 / a3) - 1.0) - acosh(a1 / a3));
187  }
188  else // External points
189  {
190  // Mura (12.22)
191  double b = get_b(a1, a3, lambda);
192  double d = get_d(a1, a3, lambda);
193  return 2.0 * PI * a1 * SQR(a3) / pow(SQR(a1) - SQR(a3), 3.0 / 2.0) * (b * d - acosh(b));
194  }
195 }
196 
197 // Function gives the solution of the integral I_3
198 // Last edit: 11-Sep-2013
200 {
201  return I2;
202 }
203 
204 // Function gives the solution of the integral I_11
205 // Last edit: 11-Sep-2013
206 double eshelbySoluEllipticIntegralsProlateSpheroid::I11(double a1, double a3, double I13, double lambda, bool intpoint)
207 {
208  if (intpoint) // Internal points
209  {
210  // Mura (11.29)
211  return 1.0 / 3.0 * (_4PI_ / SQR(a1) - 2.0 * I13);
212  }
213  else // External points
214  {
215  // Mura (12.18)
216  double delta_lambda = get_delta_lambda(a1, a3, lambda);
217  return 1.0 / 3.0 * (_4PI_ * a1 * SQR(a3) / (SQR(a1) + lambda) / delta_lambda - 2.0 * I13);
218  }
219 }
220 
221 // Function gives the solution of the integral I_12
222 // Last edit: 11-Sep-2013
224 {
225  // Mura (11.29), also applies to external field.
226  return I13;
227 }
228 
229 // Function gives the solution of the integral I_13
230 // Last edit: 11-Sep-2013
231 double eshelbySoluEllipticIntegralsProlateSpheroid::I13( double a1, double a3, double I1, double I3 )
232 {
233  // Mura (11.29), (12.18)
234  return (I1 - I3)/(SQR(a3) - SQR(a1));
235 }
236 
237 // Function gives the solution of the integral I_22
238 // Last edit: 11-Sep-2013
240 {
241  // Mura (11.29), also applies to external field.
242  return I33;
243 }
244 
245 // Function gives the solution of the integral I_23
246 // Last edit: 11-Sep-2013
248 {
249  return I33;
250 }
251 
252 // Function gives the solution of the integral I_33
253 // Last edit: 11-Sep-2013
254 double eshelbySoluEllipticIntegralsProlateSpheroid::I33(double a1, double a3, double I13, double lambda, bool intpoint)
255 {
256  if (intpoint) // Internal points
257  {
258  // Mura (11.29)
259  return PI / SQR(a3) - I13 / 4.0;
260  }
261  else // External points
262  {
263  double delta_lambda = get_delta_lambda(a1, a3, lambda);
264  // Derived from third line in (12.18) and I11 = I22 = I12
265  return 1.0 / 4.0 * (_4PI_ * a1 * SQR(a3) / (SQR(a3) + lambda) / delta_lambda - I13);
266  }
267 }
268 
269 // Auxiliary value b, (Mura, p.94)
270 double eshelbySoluEllipticIntegralsProlateSpheroid::get_b(double a1, double a3, double lambda)
271 {
272  return sqrt((SQR(a1) + lambda) / (SQR(a3) + lambda));
273 }
274 
275 // Auxiliary value d, (Mura, p.94)
276 double eshelbySoluEllipticIntegralsProlateSpheroid::get_d(double a1, double a3, double lambda)
277 {
278  return sqrt((SQR(a1) - SQR(a3)) / (SQR(a3) + lambda));
279 }
280 
281 // Auxiliary value Delta_lambda, (Mura, p.93)
282 double eshelbySoluEllipticIntegralsProlateSpheroid::get_delta_lambda(double a1, double a3, double lambda)
283 {
284  return sqrt((SQR(a1) + lambda) * (SQR(a3) + lambda) * (SQR(a3) + lambda)); // Prolate spheroid: a2 == a3
285 }
286 
287 // Lambda computed according to Mura p. 86. The property that a2 == a3 is taken into account to simplify the computation.
288 double eshelbySoluEllipticIntegralsProlateSpheroid::getLambda(const double a[3], double x1, double x2, double x3)
289 {
290  double a1 = a[0];
291  double a3 = a[2];
292 
293  // Coeficients of quadratic equation
294  // a = 1
295  double b = SQR(a1) + SQR(a3) - SQR(x1) - SQR(x2) - SQR(x3);
296  double c = SQR(a1) * SQR(a3) - SQR(x1) * SQR(a3) - (SQR(x2) + SQR(x3)) * SQR(a1);
297 
298  return (-b + sqrt(SQR(b) - 4.0 * c)) / 2.0;
299 }
300 
301 
302 
303 } // end of namespace mumech
304 
305 /*end of file*/
void giveDerivativesOfEllipticIntegrals(Point *point, bool intpoint)
Function gives the values of Ferers-Dyson&#39;s elliptic integral derivatives of the inclusion this->I...
double loc_x[3]
Local coordinates of a point.
Definition: matrix.h:137
double get_b(double a1, double a3, double lambda)
Class legendreIntegrals provides functions calculating values of elliptical integrals.
Class legendreIntegrals.
#define PI
Definition: macros.h:71
const InclusionRecord3D * I
Definition: esei.h:45
static double ellf(double phi, double ak)
Function calculating the Legendre&#39;s integral of the first kind - numerical recepies.
double I1(double a1, double a3, double I13, double lambda, bool intpoint)
#define NUM_PERTURB
Definition: types.h:732
double I11(double a1, double a3, double I13, double lambda, bool intpoint)
The header file of usefull macros.
double I2(double a1, double a3, double lambda, bool intpoint)
double I33(double a1, double a3, double I13, double lambda, bool intpoint)
void getPerturbatedLambdas(double *lambdas, const double loc_x[3])
Helper function.
Definition: esei.cpp:51
Collection of the functions of basic manipulations, some of them can be used instead of their counter...
double ddJij[81]
Second derivatives of elliptic integral Iij.
Definition: matrix.h:145
Single Point data structure - contribution from Single inclusion.
Definition: matrix.h:133
double acosh(double x)
Inverse hyperbolic cosine.
double ndiff_1
derivative step for the first derivations
Definition: inclusion.h:108
Class inclusion contains and handles all inclusion data.
void giveEllipticIntegrals(double J[13], double lambda, bool intpoint)
Function gives the values of Ferers-Dyson&#39;s elliptic integrals of the inclusion this->I.
Class eshelbySoluEllipticIntegralsProlateSpheroid.
double eI(double a[3], double k, double Theta, double mult)
#define SQR(a)
Definition: macros.h:97
double dJi[9]
First derivatives of elliptic integral Ii.
Definition: matrix.h:142
double * a
Inclusion semiaxes&#39; dimensions in global arrangement.
Definition: inclusion.h:76
double ddJi[27]
Second derivatives of elliptic integral Ii.
Definition: matrix.h:144
#define _errorr(_1)
Definition: gelib.h:160
double I13(double a1, double a3, double I1, double I3)
double dJij[27]
First derivatives of elliptic integral Iij.
Definition: matrix.h:143
double get_d(double a1, double a3, double lambda)
double get_delta_lambda(double a1, double a3, double lambda)
double getLambda(const double a[3], double x1, double x2, double x3)
Returns lambda for a given point (x1, x2, x3)
#define _4PI_
Definition: types.h:50