"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "Functions/F_Hysteresis.cpp" between
getdp-3.4.0-source.tgz and getdp-3.5.0-source.tgz

About: GetDP is a general finite element solver using mixed elements to discretize de Rham-type complexes in one, two and three dimensions.

F_Hysteresis.cpp  (getdp-3.4.0-source.tgz):F_Hysteresis.cpp  (getdp-3.5.0-source.tgz)
// GetDP - Copyright (C) 1997-2021 P. Dular and C. Geuzaine, University of Liege // GetDP - Copyright (C) 1997-2022 P. Dular and C. Geuzaine, University of Liege
// //
// See the LICENSE.txt file for license information. Please report all // See the LICENSE.txt file for license information. Please report all
// issues on https://gitlab.onelab.info/getdp/getdp/issues. // issues on https://gitlab.onelab.info/getdp/getdp/issues.
// //
// Contributor(s): // Contributor(s):
// Johan Gyselinck // Johan Gyselinck
// Kevin Jacques // Kevin Jacques
// //
#include <math.h> #include <math.h>
#include <string.h> #include <string.h>
#include "ProData.h" #include "ProData.h"
#include "F.h" #include "F.h"
#include "Message.h" #include "Message.h"
#include <iostream> #include <iostream>
#define SQU(a) ((a)*(a)) #define SQU(a) ((a) * (a))
#define CUB(a) ((a)*(a)*(a)) #define CUB(a) ((a) * (a) * (a))
#define MU0 1.25663706144e-6 #define MU0 1.25663706144e-6
#define FLAG_WARNING_INFO_INV 1 #define FLAG_WARNING_INFO_INV 1
#define FLAG_WARNING_INFO_APPROACH 2 #define FLAG_WARNING_INFO_APPROACH 2
#define FLAG_WARNING_STOP_INV 10 #define FLAG_WARNING_STOP_INV 10
#define FLAG_WARNING_DISPABOVEITER 1 #define FLAG_WARNING_DISPABOVEITER 1
#define MIN(a,b) (((a)<(b))?(a):(b)) #define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define MAX(a,b) (((a)>(b))?(a):(b)) #define MAX(a, b) (((a) > (b)) ? (a) : (b))
extern struct CurrentData Current ; extern struct CurrentData Current;
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
/* /*
Vectorized Jiles-Atherton hysteresis model Vectorized Jiles-Atherton hysteresis model
J. Gyselinck, P. Dular, N. Sadowski, J. Leite and J.P.A. Bastos, J. Gyselinck, P. Dular, N. Sadowski, J. Leite and J.P.A. Bastos,
"Incorporation of a Jiles-Atherton vector hysteresis model in "Incorporation of a Jiles-Atherton vector hysteresis model in
2D FE magnetic field computations. Application of the Newton-Raphson method", 2D FE magnetic field computations. Application of the Newton-Raphson method",
Vol. 23, No. 3, pp. 685-693, 2004. Vol. 23, No. 3, pp. 685-693, 2004.
*/ */
double F_Man(double He, double Ms, double a) double F_Man(double He, double Ms, double a)
{ {
// Anhysteretic magnetisation // Anhysteretic magnetisation
if(fabs(He) < 0.01*a) if(fabs(He) < 0.01 * a)
//return Ms*He/(3.*a) ; // Aprox. up to 1st order // return Ms*He/(3.*a) ; // Aprox. up to 1st order
return Ms*(He/(3.*a)-1/45*CUB(He/a)) ; // Approx. up to 3rd order return Ms *
else return Ms*(cosh(He/a)/sinh(He/a)-a/He) ; (He / (3. * a) - 1 / 45 * CUB(He / a)); // Approx. up to 3rd order
else
return Ms * (cosh(He / a) / sinh(He / a) - a / He);
} }
double F_dMandHe(double He, double Ms, double a) double F_dMandHe(double He, double Ms, double a)
{ {
// Derivative of the magnetisation Man with respect to the effective field He // Derivative of the magnetisation Man with respect to the effective field He
if(fabs(He) < 0.01*a) if(fabs(He) < 0.01 * a)
//return Ms/(3.*a) ; // Aprox. up to 1st order // return Ms/(3.*a) ; // Aprox. up to 1st order
return Ms/(3.*a)-Ms/(15*a)*SQU(He/a) ; // Approx. up to 3rd order return Ms / (3. * a) -
else return Ms/a*(1-SQU(cosh(He/a)/sinh(He/a))+SQU(a/He)) ; Ms / (15 * a) * SQU(He / a); // Approx. up to 3rd order
else
return Ms / a * (1 - SQU(cosh(He / a) / sinh(He / a)) + SQU(a / He));
} }
void FV_Man(double He[3], double Ms, double a, double Man[3]) void FV_Man(double He[3], double Ms, double a, double Man[3])
{ {
double nHe = sqrt(He[0]*He[0]+He[1]*He[1]+He[2]*He[2]) ; double nHe = sqrt(He[0] * He[0] + He[1] * He[1] + He[2] * He[2]);
if( !nHe ) { if(!nHe) { Man[0] = Man[1] = Man[2] = 0.; }
Man[0] = Man[1] = Man[2]= 0. ;
}
else { else {
double auxMan = F_Man(nHe, Ms, a) ; double auxMan = F_Man(nHe, Ms, a);
Man[0] = auxMan * He[0]/nHe ; Man[0] = auxMan * He[0] / nHe;
Man[1] = auxMan * He[1]/nHe ; Man[1] = auxMan * He[1] / nHe;
Man[2] = auxMan * He[2]/nHe ; Man[2] = auxMan * He[2] / nHe;
} }
} }
void FV_dMandHe(double He[3], double Ms, double a, double dMandHe[6]) void FV_dMandHe(double He[3], double Ms, double a, double dMandHe[6])
{ {
double nHe = sqrt(He[0]*He[0]+He[1]*He[1]+He[2]*He[2]) ; double nHe = sqrt(He[0] * He[0] + He[1] * He[1] + He[2] * He[2]);
double Man = F_Man(nHe, Ms, a) ; double Man = F_Man(nHe, Ms, a);
double ndMandHe = F_dMandHe(nHe,Ms,a) ; double ndMandHe = F_dMandHe(nHe, Ms, a);
if( !nHe ) { if(!nHe) {
dMandHe[0] = dMandHe[3] = dMandHe[5] = ndMandHe ; dMandHe[0] = dMandHe[3] = dMandHe[5] = ndMandHe;
dMandHe[1] = dMandHe[2] = dMandHe[4] = 0. ; dMandHe[1] = dMandHe[2] = dMandHe[4] = 0.;
} }
else { else {
dMandHe[0] = Man/nHe + (ndMandHe - Man/nHe)*He[0]*He[0]/(nHe*nHe) ; dMandHe[0] =
dMandHe[3] = Man/nHe + (ndMandHe - Man/nHe)*He[1]*He[1]/(nHe*nHe) ; Man / nHe + (ndMandHe - Man / nHe) * He[0] * He[0] / (nHe * nHe);
dMandHe[5] = Man/nHe + (ndMandHe - Man/nHe)*He[2]*He[2]/(nHe*nHe) ; dMandHe[3] =
dMandHe[1] = (ndMandHe - Man/nHe)*He[0]*He[1]/(nHe*nHe) ; Man / nHe + (ndMandHe - Man / nHe) * He[1] * He[1] / (nHe * nHe);
dMandHe[2] = (ndMandHe - Man/nHe)*He[0]*He[2]/(nHe*nHe) ; dMandHe[5] =
dMandHe[4] = (ndMandHe - Man/nHe)*He[1]*He[2]/(nHe*nHe) ; Man / nHe + (ndMandHe - Man / nHe) * He[2] * He[2] / (nHe * nHe);
dMandHe[1] = (ndMandHe - Man / nHe) * He[0] * He[1] / (nHe * nHe);
dMandHe[2] = (ndMandHe - Man / nHe) * He[0] * He[2] / (nHe * nHe);
dMandHe[4] = (ndMandHe - Man / nHe) * He[1] * He[2] / (nHe * nHe);
} }
} }
void FV_dMidHe(double He[3], double Man[3], void FV_dMidHe(double He[3], double Man[3], double Mi[3], double dH[3],
double Mi[3], double dH[3], double k, double k, double dMidHe[6])
double dMidHe[6]) {
{ double dM = sqrt((Man[0] - Mi[0]) * (Man[0] - Mi[0]) +
double dM = sqrt( (Man[0]-Mi[0])*(Man[0]-Mi[0]) + (Man[1]-Mi[1])*(Man[1]-Mi[1] (Man[1] - Mi[1]) * (Man[1] - Mi[1]) +
) + (Man[2]-Mi[2])*(Man[2]-Mi[2]) ) ; (Man[2] - Mi[2]) * (Man[2] - Mi[2]));
if ( !dM || (Man[0]-Mi[0])*dH[0] + (Man[1]-Mi[1])*dH[1] + (Man[2]-Mi[2])*dH[2] if(!dM || (Man[0] - Mi[0]) * dH[0] + (Man[1] - Mi[1]) * dH[1] +
<= 0 ) { (Man[2] - Mi[2]) * dH[2] <=
dMidHe[0] = dMidHe[3] = dMidHe[5] = dMidHe[1] = dMidHe[2] = dMidHe[4] = 0. 0) {
; dMidHe[0] = dMidHe[3] = dMidHe[5] = dMidHe[1] = dMidHe[2] = dMidHe[4] = 0.;
} else { }
else {
double kdM = k * dM; double kdM = k * dM;
dMidHe[0] = (Man[0]-Mi[0])*(Man[0]-Mi[0]) / kdM ; dMidHe[0] = (Man[0] - Mi[0]) * (Man[0] - Mi[0]) / kdM;
dMidHe[3] = (Man[1]-Mi[1])*(Man[1]-Mi[1]) / kdM ; dMidHe[3] = (Man[1] - Mi[1]) * (Man[1] - Mi[1]) / kdM;
dMidHe[5] = (Man[2]-Mi[2])*(Man[2]-Mi[2]) / kdM ; dMidHe[5] = (Man[2] - Mi[2]) * (Man[2] - Mi[2]) / kdM;
dMidHe[1] = (Man[0]-Mi[0])*(Man[1]-Mi[1]) / kdM ; dMidHe[1] = (Man[0] - Mi[0]) * (Man[1] - Mi[1]) / kdM;
dMidHe[2] = (Man[0]-Mi[0])*(Man[2]-Mi[2]) / kdM ; dMidHe[2] = (Man[0] - Mi[0]) * (Man[2] - Mi[2]) / kdM;
dMidHe[4] = (Man[1]-Mi[1])*(Man[2]-Mi[2]) / kdM ; dMidHe[4] = (Man[1] - Mi[1]) * (Man[2] - Mi[2]) / kdM;
} }
} }
void Vector_dBdH(double H[3], double B[3], double dH[3], void Vector_dBdH(double H[3], double B[3], double dH[3],
struct FunctionActive *D, double dBdH[6]) struct FunctionActive *D, double dBdH[6])
{ {
double M[3], He[3], Man[3], Mi[3] ; double M[3], He[3], Man[3], Mi[3];
double dMandHe[6], dMidHe[6], dMdH[6] ; double dMandHe[6], dMidHe[6], dMdH[6];
double d[6], e[6], f[6] ; double d[6], e[6], f[6];
if(D->Case.Interpolation.NbrPoint != 5) if(D->Case.Interpolation.NbrPoint != 5)
Message::Error("Jiles-Atherton parameters missing: {List[{Ms, a, k, c, alpha Message::Error(
}]}"); "Jiles-Atherton parameters missing: {List[{Ms, a, k, c, alpha}]}");
double Ms = D->Case.Interpolation.x[0] ; double Ms = D->Case.Interpolation.x[0];
double a = D->Case.Interpolation.x[1] ; double a = D->Case.Interpolation.x[1];
double kk = D->Case.Interpolation.x[2] ; double kk = D->Case.Interpolation.x[2];
double c = D->Case.Interpolation.x[3] ; double c = D->Case.Interpolation.x[3];
double alpha = D->Case.Interpolation.x[4] ; double alpha = D->Case.Interpolation.x[4];
for(int i=0 ; i<3 ; i++){ for(int i = 0; i < 3; i++) {
M[i] = B[i]/MU0 - H[i] ; // Magnetisation M[i] = B[i] / MU0 - H[i]; // Magnetisation
He[i] = H[i] + alpha * M[i] ; // Effective field He[i] = H[i] + alpha * M[i]; // Effective field
} }
FV_Man(He, Ms, a, Man) ; FV_Man(He, Ms, a, Man);
for(int i=0 ; i<3 ; i++) for(int i = 0; i < 3; i++)
Mi[i] = (M[i]-c*Man[i]) / (1-c) ; // Irreversible magnetisation Mi[i] = (M[i] - c * Man[i]) / (1 - c); // Irreversible magnetisation
FV_dMandHe(He, Ms, a, dMandHe) ; FV_dMandHe(He, Ms, a, dMandHe);
FV_dMidHe(He, Man, Mi, dH, kk, dMidHe) ; FV_dMidHe(He, Man, Mi, dH, kk, dMidHe);
d[0] = 1 - alpha*c*dMandHe[0] - alpha*(1-c)*dMidHe[0] ; // xx d[0] = 1 - alpha * c * dMandHe[0] - alpha * (1 - c) * dMidHe[0]; // xx
d[3] = 1 - alpha*c*dMandHe[3] - alpha*(1-c)*dMidHe[3] ; // yy d[3] = 1 - alpha * c * dMandHe[3] - alpha * (1 - c) * dMidHe[3]; // yy
d[5] = 1 - alpha*c*dMandHe[5] - alpha*(1-c)*dMidHe[5] ; // zz d[5] = 1 - alpha * c * dMandHe[5] - alpha * (1 - c) * dMidHe[5]; // zz
d[1] = - alpha*c*dMandHe[1] - alpha*(1-c)*dMidHe[1] ; // xy d[1] = -alpha * c * dMandHe[1] - alpha * (1 - c) * dMidHe[1]; // xy
d[2] = - alpha*c*dMandHe[2] - alpha*(1-c)*dMidHe[2] ; // xz d[2] = -alpha * c * dMandHe[2] - alpha * (1 - c) * dMidHe[2]; // xz
d[4] = - alpha*c*dMandHe[4] - alpha*(1-c)*dMidHe[4] ; // yz d[4] = -alpha * c * dMandHe[4] - alpha * (1 - c) * dMidHe[4]; // yz
double dd = d[0] * (d[3] *d[5] - d[4] *d[4]) double dd = d[0] * (d[3] * d[5] - d[4] * d[4]) -
- d[1] * (d[1] *d[5] - d[4] *d[2]) d[1] * (d[1] * d[5] - d[4] * d[2]) +
+ d[2] * (d[1] *d[4] - d[3] *d[2]); d[2] * (d[1] * d[4] - d[3] * d[2]);
if(!dd) if(!dd) Message::Error("Null determinant of denominator of dm/dh!");
Message::Error("Null determinant of denominator of dm/dh!");
e[0] = (d[3] * d[5] - d[4] * d[4]) / dd;
e[0] = (d[3]*d[5]-d[4]*d[4])/dd ; e[1] = -(d[1] * d[5] - d[2] * d[4]) / dd;
e[1] = -(d[1]*d[5]-d[2]*d[4])/dd ; e[2] = (d[1] * d[4] - d[2] * d[3]) / dd;
e[2] = (d[1]*d[4]-d[2]*d[3])/dd ; e[3] = (d[0] * d[5] - d[2] * d[2]) / dd;
e[3] = (d[0]*d[5]-d[2]*d[2])/dd ; e[4] = -(d[0] * d[4] - d[1] * d[2]) / dd;
e[4] = -(d[0]*d[4]-d[1]*d[2])/dd ; e[5] = (d[0] * d[3] - d[1] * d[1]) / dd;
e[5] = (d[0]*d[3]-d[1]*d[1])/dd ;
for(int i = 0; i < 6; i++) f[i] = c * dMandHe[i] + (1 - c) * dMidHe[i];
for(int i=0 ; i<6 ; i++)
f[i] = c*dMandHe[i] + (1-c)*dMidHe[i] ; dMdH[0] = e[0] * f[0] + e[1] * f[1] + e[2] * f[2];
dMdH[1] = e[0] * f[1] + e[1] * f[3] + e[2] * f[4];
dMdH[0] = e[0]*f[0]+e[1]*f[1]+e[2]*f[2] ; dMdH[2] = e[0] * f[2] + e[1] * f[4] + e[2] * f[5];
dMdH[1] = e[0]*f[1]+e[1]*f[3]+e[2]*f[4] ; dMdH[3] = e[1] * f[1] + e[3] * f[3] + e[4] * f[4];
dMdH[2] = e[0]*f[2]+e[1]*f[4]+e[2]*f[5] ; dMdH[4] = e[1] * f[2] + e[3] * f[4] + e[4] * f[5];
dMdH[3] = e[1]*f[1]+e[3]*f[3]+e[4]*f[4] ; dMdH[5] = e[2] * f[2] + e[4] * f[4] + e[5] * f[5];
dMdH[4] = e[1]*f[2]+e[3]*f[4]+e[4]*f[5] ;
dMdH[5] = e[2]*f[2]+e[4]*f[4]+e[5]*f[5] ; double slope_factor = 1; // choose 1e2 for increasing slope, for reducing NR
// iterations (better convergence)
double slope_factor = 1; // choose 1e2 for increasing slope, for reducing NR i
terations (better convergence) dBdH[0] = MU0 * (slope_factor + dMdH[0]);
dBdH[3] = MU0 * (slope_factor + dMdH[3]);
dBdH[0] = MU0 * (slope_factor + dMdH[0]) ; dBdH[5] = MU0 * (slope_factor + dMdH[5]);
dBdH[3] = MU0 * (slope_factor + dMdH[3]) ; dBdH[1] = MU0 * dMdH[1];
dBdH[5] = MU0 * (slope_factor + dMdH[5]) ; dBdH[2] = MU0 * dMdH[2];
dBdH[1] = MU0 * dMdH[1] ; dBdH[4] = MU0 * dMdH[4];
dBdH[2] = MU0 * dMdH[2] ;
dBdH[4] = MU0 * dMdH[4] ;
} }
void Vector_dHdB(double H[3], double B[3], double dH[3], void Vector_dHdB(double H[3], double B[3], double dH[3],
struct FunctionActive *D, struct FunctionActive *D, double dHdB[6])
double dHdB[6])
{ {
double dBdH[6] ; double dBdH[6];
// Inverting the matrix representation of the db/dh we get dh/db // Inverting the matrix representation of the db/dh we get dh/db
Vector_dBdH(H, B, dH, D, dBdH) ; Vector_dBdH(H, B, dH, D, dBdH);
double det = dBdH[0] * (dBdH[3] *dBdH[5] - dBdH[4] *dBdH[4]) double det = dBdH[0] * (dBdH[3] * dBdH[5] - dBdH[4] * dBdH[4]) -
- dBdH[1] * (dBdH[1] *dBdH[5] - dBdH[4] *dBdH[2]) dBdH[1] * (dBdH[1] * dBdH[5] - dBdH[4] * dBdH[2]) +
+ dBdH[2] * (dBdH[1] *dBdH[4] - dBdH[3] *dBdH[2]); dBdH[2] * (dBdH[1] * dBdH[4] - dBdH[3] * dBdH[2]);
if(!det) if(!det) Message::Error("Null determinant of db/dh!");
Message::Error("Null determinant of db/dh!");
dHdB[0] = (dBdH[3] * dBdH[5] - dBdH[4] * dBdH[4]) / det;
dHdB[0] = (dBdH[3]*dBdH[5]-dBdH[4]*dBdH[4])/det ; dHdB[1] = -(dBdH[1] * dBdH[5] - dBdH[2] * dBdH[4]) / det;
dHdB[1] = -(dBdH[1]*dBdH[5]-dBdH[2]*dBdH[4])/det ; dHdB[2] = (dBdH[1] * dBdH[4] - dBdH[2] * dBdH[3]) / det;
dHdB[2] = (dBdH[1]*dBdH[4]-dBdH[2]*dBdH[3])/det ; dHdB[3] = (dBdH[0] * dBdH[5] - dBdH[2] * dBdH[2]) / det;
dHdB[3] = (dBdH[0]*dBdH[5]-dBdH[2]*dBdH[2])/det ; dHdB[4] = -(dBdH[0] * dBdH[4] - dBdH[1] * dBdH[2]) / det;
dHdB[4] = -(dBdH[0]*dBdH[4]-dBdH[1]*dBdH[2])/det ; dHdB[5] = (dBdH[0] * dBdH[3] - dBdH[1] * dBdH[1]) / det;
dHdB[5] = (dBdH[0]*dBdH[3]-dBdH[1]*dBdH[1])/det ;
} }
void F_dhdb_Jiles(F_ARG) void F_dhdb_Jiles(F_ARG)
{ {
// #define F_ARG struct Function * Fct, struct Value * A, struct Value * V // #define F_ARG struct Function * Fct, struct Value * A, struct Value * V
// input : h, b ,dh // input : h, b ,dh
// dhdb_Jiles[{h}, {d a}, {h}-{h}[1] ]{List[hyst_FeSi]} // dhdb_Jiles[{h}, {d a}, {h}-{h}[1] ]{List[hyst_FeSi]}
// Material parameters: e.g. hyst_FeSi = { Msat, a, k, c, alpha};==> struct Fu // Material parameters: e.g. hyst_FeSi = { Msat, a, k, c, alpha};==> struct
nctionActive *D // FunctionActive *D
double H[3], B[3], dH[3], dHdB[6] ; double H[3], B[3], dH[3], dHdB[6];
struct FunctionActive * D ; struct FunctionActive *D;
if( (A+0)->Type != VECTOR || (A+1)->Type != VECTOR || (A+2)->Type != VECTOR ) if((A + 0)->Type != VECTOR || (A + 1)->Type != VECTOR ||
(A + 2)->Type != VECTOR)
Message::Error("Three vector arguments required"); Message::Error("Three vector arguments required");
if(!Fct->Active) Fi_InitListX(Fct, A, V) ; if(!Fct->Active) Fi_InitListX(Fct, A, V);
D = Fct->Active ; D = Fct->Active;
for(int k=0 ; k<3 ; k++){ for(int k = 0; k < 3; k++) {
H[k] = (A+0)->Val[k] ; H[k] = (A + 0)->Val[k];
B[k] = (A+1)->Val[k] ; B[k] = (A + 1)->Val[k];
dH[k] = (A+2)->Val[k] ; dH[k] = (A + 2)->Val[k];
} }
Vector_dHdB(H, B, dH, D, dHdB) ; Vector_dHdB(H, B, dH, D, dHdB);
V->Type = TENSOR_SYM ;// xx, xy, xz, yy, yz, zz V->Type = TENSOR_SYM; // xx, xy, xz, yy, yz, zz
for(int k=0 ; k<6 ; k++) V->Val[k] = dHdB[k] ; for(int k = 0; k < 6; k++) V->Val[k] = dHdB[k];
} }
void F_dbdh_Jiles(F_ARG) void F_dbdh_Jiles(F_ARG)
{ {
// #define F_ARG struct Function * Fct, struct Value * A, struct Value * V // #define F_ARG struct Function * Fct, struct Value * A, struct Value * V
// input : h, b, dh // input : h, b, dh
// dbdh_Jiles[{h}, {b}, {h}-{h}[1] ]{List[hyst_FeSi]} // dbdh_Jiles[{h}, {b}, {h}-{h}[1] ]{List[hyst_FeSi]}
// Material parameters: e.g. hyst_FeSi = { Msat, a, k, c, alpha};==> struct Fu // Material parameters: e.g. hyst_FeSi = { Msat, a, k, c, alpha};==> struct
nctionActive *D // FunctionActive *D
double H[3], B[3], dH[3], dBdH[6] ; double H[3], B[3], dH[3], dBdH[6];
struct FunctionActive *D; struct FunctionActive *D;
if( (A+0)->Type != VECTOR || (A+1)->Type != VECTOR || (A+2)->Type != VECTOR ) if((A + 0)->Type != VECTOR || (A + 1)->Type != VECTOR ||
Message::Error("dbdh_Jiles requires three vector: {h} at t_i, {b} at t_i and (A + 2)->Type != VECTOR)
({h}-{h}[1]), i.e {h} at t_i - {h} at t_{i-1}"); Message::Error("dbdh_Jiles requires three vector: {h} at t_i, {b} at t_i "
"and ({h}-{h}[1]), i.e {h} at t_i - {h} at t_{i-1}");
if(!Fct->Active) Fi_InitListX(Fct, A, V) ; if(!Fct->Active) Fi_InitListX(Fct, A, V);
D = Fct->Active ; D = Fct->Active;
for(int k=0 ; k<3 ; k++){ for(int k = 0; k < 3; k++) {
H[k] = (A+0)->Val[k] ; H[k] = (A + 0)->Val[k];
B[k] = (A+1)->Val[k] ; B[k] = (A + 1)->Val[k];
dH[k] = (A+2)->Val[k] ; dH[k] = (A + 2)->Val[k];
} }
Vector_dBdH(H, B, dH, D, dBdH) ; Vector_dBdH(H, B, dH, D, dBdH);
V->Type = TENSOR_SYM ; V->Type = TENSOR_SYM;
for(int k=0 ; k<6 ; k++) V->Val[k] = dBdH[k] ; for(int k = 0; k < 6; k++) V->Val[k] = dBdH[k];
} }
void F_h_Jiles(F_ARG) void F_h_Jiles(F_ARG)
{ {
// #define F_ARG struct Function * Fct, struct Value * A, struct Value * V // #define F_ARG struct Function * Fct, struct Value * A, struct Value * V
// input : h1, b1, b2 // input : h1, b1, b2
// h_Jiles[ {h}[1], {b}[1], {b} ]{List[hyst_FeSi]} // h_Jiles[ {h}[1], {b}[1], {b} ]{List[hyst_FeSi]}
// Material parameters: e.g. hyst_FeSi = { Msat, a, k, c, alpha}; // Material parameters: e.g. hyst_FeSi = { Msat, a, k, c, alpha};
double Hone[3], Bone[3], Btwo[3], Htwo[3] ; double Hone[3], Bone[3], Btwo[3], Htwo[3];
struct FunctionActive *D; struct FunctionActive *D;
void Vector_H2(double Hone[3], double Bone[3], double Btwo[3], int n, void Vector_H2(double Hone[3], double Bone[3], double Btwo[3], int n,
struct FunctionActive *D, double Htwo[3]) ; struct FunctionActive *D, double Htwo[3]);
if( (A+0)->Type != VECTOR || (A+1)->Type != VECTOR || (A+2)->Type != VECTOR ) if((A + 0)->Type != VECTOR || (A + 1)->Type != VECTOR ||
Message::Error("h_Jiles requires three vector arguments: {h} at t_{i-1}, {b} (A + 2)->Type != VECTOR)
at t_{i-1} and {b} at t_i"); Message::Error("h_Jiles requires three vector arguments: {h} at t_{i-1}, "
"{b} at t_{i-1} and {b} at t_i");
if(!Fct->Active) Fi_InitListX(Fct, A, V) ; if(!Fct->Active) Fi_InitListX(Fct, A, V);
D = Fct->Active ; D = Fct->Active;
for(int k=0 ; k<3 ; k++) { for(int k = 0; k < 3; k++) {
Hone[k] = (A+0)->Val[k] ; Hone[k] = (A + 0)->Val[k];
Bone[k] = (A+1)->Val[k] ; Bone[k] = (A + 1)->Val[k];
Btwo[k] = (A+2)->Val[k] ; Btwo[k] = (A + 2)->Val[k];
} }
Vector_H2(Hone, Bone, Btwo, 10, D, Htwo) ; Vector_H2(Hone, Bone, Btwo, 10, D, Htwo);
V->Type = VECTOR ; V->Type = VECTOR;
for(int k=0 ; k<3 ; k++) V->Val[k] = Htwo[k] ; for(int k = 0; k < 3; k++) V->Val[k] = Htwo[k];
} }
void F_b_Jiles(F_ARG) void F_b_Jiles(F_ARG)
{ {
// #define F_ARG struct Function * Fct, struct Value * A, struct Value * V // #define F_ARG struct Function * Fct, struct Value * A, struct Value * V
// input : b1, h1, h2 // input : b1, h1, h2
// b_Jiles[ {b}[1], {h}[1], {h} ]{List[hyst_FeSi]} // b_Jiles[ {b}[1], {h}[1], {h} ]{List[hyst_FeSi]}
// Material parameters: e.g. hyst_FeSi = { Msat, a, k, c, alpha}; // Material parameters: e.g. hyst_FeSi = { Msat, a, k, c, alpha};
double Bone[3], Hone[3], Btwo[3], Htwo[3] ; double Bone[3], Hone[3], Btwo[3], Htwo[3];
struct FunctionActive * D ; struct FunctionActive *D;
void Vector_B2(double Bone[3], double Hone[3], double Htwo[3], int n, void Vector_B2(double Bone[3], double Hone[3], double Htwo[3], int n,
struct FunctionActive *D, double Btwo[3]) ; struct FunctionActive *D, double Btwo[3]);
if( (A+0)->Type != VECTOR || (A+1)->Type != VECTOR || (A+2)->Type != VECTOR ) if((A + 0)->Type != VECTOR || (A + 1)->Type != VECTOR ||
(A + 2)->Type != VECTOR)
Message::Error("b_Jiles requires three vector arguments: {b} at t_{i-1}, " Message::Error("b_Jiles requires three vector arguments: {b} at t_{i-1}, "
"{h} at t_{i-1} and {h} at t_i"); "{h} at t_{i-1} and {h} at t_i");
if(!Fct->Active) Fi_InitListX(Fct, A, V) ; if(!Fct->Active) Fi_InitListX(Fct, A, V);
D = Fct->Active ; D = Fct->Active;
for(int k = 0; k < 3 ; k++){ for(int k = 0; k < 3; k++) {
Bone[k] = (A+0)->Val[k] ; Bone[k] = (A + 0)->Val[k];
Hone[k] = (A+1)->Val[k] ; Hone[k] = (A + 1)->Val[k];
Htwo[k] = (A+2)->Val[k] ; Htwo[k] = (A + 2)->Val[k];
} }
Vector_B2(Bone, Hone, Htwo, 10, D, Btwo) ; Vector_B2(Bone, Hone, Htwo, 10, D, Btwo);
V->Type = VECTOR ; V->Type = VECTOR;
for(int k = 0; k < 3 ; k++) V->Val[k] = Btwo[k] ; for(int k = 0; k < 3; k++) V->Val[k] = Btwo[k];
} }
void Vector_H2(double Hone[3], double Bone[3], double Btwo[3], int n, void Vector_H2(double Hone[3], double Bone[3], double Btwo[3], int n,
struct FunctionActive *D, double Htwo[3]) struct FunctionActive *D, double Htwo[3])
{ {
double H[3], dH[3], B[3], dB[3] ; double H[3], dH[3], B[3], dB[3];
double dHdB[6] ; double dHdB[6];
for(int k=0 ; k<3 ; k++) { for(int k = 0; k < 3; k++) {
H[k] = Hone[k]; H[k] = Hone[k];
dB[k] = (Btwo[k] - Bone[k])/(double)n ; dB[k] = (Btwo[k] - Bone[k]) / (double)n;
} }
for(int i=0 ; i<n ; i++) { for(int i = 0; i < n; i++) {
for(int k=0 ; k<3 ; k++) for(int k = 0; k < 3; k++)
B[k] = (double)(n-i)/(double)n * Bone[k] + (double)i/(double)n * Btwo[k] ; B[k] =
(double)(n - i) / (double)n * Bone[k] + (double)i / (double)n * Btwo[k];
if(!i) { if(!i) {
for(int k=0; k<3; k++) dH[k] = dB[k] ; for(int k = 0; k < 3; k++) dH[k] = dB[k];
Vector_dHdB(H, B, dH, D, dHdB) ; Vector_dHdB(H, B, dH, D, dHdB);
dH[0] = dHdB[0] * dB[0] + dHdB[1] * dB[1] + dHdB[2] * dB[2] ; dH[0] = dHdB[0] * dB[0] + dHdB[1] * dB[1] + dHdB[2] * dB[2];
dH[1] = dHdB[1] * dB[0] + dHdB[3] * dB[1] + dHdB[4] * dB[2] ; dH[1] = dHdB[1] * dB[0] + dHdB[3] * dB[1] + dHdB[4] * dB[2];
dH[2] = dHdB[2] * dB[0] + dHdB[4] * dB[1] + dHdB[5] * dB[2] ; dH[2] = dHdB[2] * dB[0] + dHdB[4] * dB[1] + dHdB[5] * dB[2];
} }
Vector_dHdB(H, B, dH, D, dHdB) ; Vector_dHdB(H, B, dH, D, dHdB);
dH[0] = dHdB[0] * dB[0] + dHdB[1] * dB[1] + dHdB[2] * dB[2] ; dH[0] = dHdB[0] * dB[0] + dHdB[1] * dB[1] + dHdB[2] * dB[2];
dH[1] = dHdB[1] * dB[0] + dHdB[3] * dB[1] + dHdB[4] * dB[2] ; dH[1] = dHdB[1] * dB[0] + dHdB[3] * dB[1] + dHdB[4] * dB[2];
dH[2] = dHdB[2] * dB[0] + dHdB[4] * dB[1] + dHdB[5] * dB[2] ; dH[2] = dHdB[2] * dB[0] + dHdB[4] * dB[1] + dHdB[5] * dB[2];
for(int k=0 ; k<3 ; k++) H[k] += dH[k] ; for(int k = 0; k < 3; k++) H[k] += dH[k];
} }
for(int k=0 ; k<3 ; k++) Htwo[k] = H[k] ; for(int k = 0; k < 3; k++) Htwo[k] = H[k];
} }
void Vector_B2(double Bone[3], double Hone[3], double Htwo[3], int n, void Vector_B2(double Bone[3], double Hone[3], double Htwo[3], int n,
struct FunctionActive *D, double Btwo[3]) struct FunctionActive *D, double Btwo[3])
{ {
double H[3], dH[3], B[3] ; double H[3], dH[3], B[3];
double dBdH[6] ; double dBdH[6];
for(int k=0 ; k<3 ; k++) { for(int k = 0; k < 3; k++) {
B[k] = Bone[k]; B[k] = Bone[k];
dH[k] = (Htwo[k] - Hone[k])/(double)n ; dH[k] = (Htwo[k] - Hone[k]) / (double)n;
} }
for(int i=0 ; i<n ; i++) { for(int i = 0; i < n; i++) {
for(int k=0 ; k<3 ; k++) for(int k = 0; k < 3; k++)
H[k] = (double)(n-i)/(double)n * Hone[k] + (double)i/(double)n * Htwo[k] ; H[k] =
(double)(n - i) / (double)n * Hone[k] + (double)i / (double)n * Htwo[k];
Vector_dBdH(H, B, dH, D, dBdH) ; Vector_dBdH(H, B, dH, D, dBdH);
B[0] += dBdH[0] * dH[0] + dBdH[1] * dH[1] + dBdH[2] * dH[2] ; B[0] += dBdH[0] * dH[0] + dBdH[1] * dH[1] + dBdH[2] * dH[2];
B[1] += dBdH[1] * dH[0] + dBdH[3] * dH[1] + dBdH[4] * dH[2] ; B[1] += dBdH[1] * dH[0] + dBdH[3] * dH[1] + dBdH[4] * dH[2];
B[2] += dBdH[2] * dH[0] + dBdH[4] * dH[1] + dBdH[5] * dH[2] ; B[2] += dBdH[2] * dH[0] + dBdH[4] * dH[1] + dBdH[5] * dH[2];
} }
for(int k=0 ; k<3 ; k++) Btwo[k] = B[k] ; for(int k = 0; k < 3; k++) Btwo[k] = B[k];
} }
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
/* /*
Ducharne's model of static hysteresis Ducharne's model of static hysteresis
Raulet, M.A.; Ducharne, B.; Masson, J.P.; Bayada, G.; Raulet, M.A.; Ducharne, B.; Masson, J.P.; Bayada, G.;
"The magnetic field diffusion equation including dynamic hysteresis: "The magnetic field diffusion equation including dynamic hysteresis:
a linear formulation of the problem", a linear formulation of the problem",
IEEE Trans. Mag., vol. 40, no. 2, pp. 872-875 (2004). IEEE Trans. Mag., vol. 40, no. 2, pp. 872-875 (2004).
skipping to change at line 415 skipping to change at line 432
NL Number of lines NL Number of lines
NC Number of columns NC Number of columns
b0 Initial flux density (T) b0 Initial flux density (T)
h0 Initial magnetic field (A/m) h0 Initial magnetic field (A/m)
b Final flux density (T) b Final flux density (T)
*/ */
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
double Fi_h_Ducharne(double *hi, double *bi, double *M, int NL, int NC, double Fi_h_Ducharne(double *hi, double *bi, double *M, int NL, int NC,
double h0, double b0, double b) double h0, double b0, double b)
{ {
double db, dh, dHdB, s; double db, dh, dHdB, s;
int i, N = 200 ; // fixed number of steps for numerical integration int i, N = 200; // fixed number of steps for numerical integration
db = (b - b0)/N ; db = (b - b0) / N;
s = (b - b0 < 0) ? -1. : 1. ; s = (b - b0 < 0) ? -1. : 1.;
for(i=0 ; i < N ; ++i) { for(i = 0; i < N; ++i) {
bool IsInGrid = Fi_InterpolationBilinear(hi, bi, M, NL, NC, s*h0, s*b0, &dHd bool IsInGrid =
B); Fi_InterpolationBilinear(hi, bi, M, NL, NC, s * h0, s * b0, &dHdB);
if(!IsInGrid) dHdB = MU0 ; if(!IsInGrid) dHdB = MU0;
dh = dHdB * db; dh = dHdB * db;
h0 += dh; h0 += dh;
b0 += db; b0 += db;
} }
return h0 ; return h0;
} }
void F_h_Ducharne(F_ARG) void F_h_Ducharne(F_ARG)
{ {
int NL, NC, i; int NL, NC, i;
double b0, h0, b, h, *bi, *hi, *M; double b0, h0, b, h, *bi, *hi, *M;
struct FunctionActive * D; struct FunctionActive *D;
if(!Fct->Active) Fi_InitListMatrix(Fct, A, V) ; if(!Fct->Active) Fi_InitListMatrix(Fct, A, V);
D = Fct->Active ; D = Fct->Active;
NL = D->Case.ListMatrix.NbrLines ; NL = D->Case.ListMatrix.NbrLines;
NC = D->Case.ListMatrix.NbrColumns ; NC = D->Case.ListMatrix.NbrColumns;
hi = D->Case.ListMatrix.x ; hi = D->Case.ListMatrix.x;
bi = D->Case.ListMatrix.y ; bi = D->Case.ListMatrix.y;
M = D->Case.ListMatrix.data ; M = D->Case.ListMatrix.data;
for(i=0 ; i<3 ; ++i) { for(i = 0; i < 3; ++i) {
// (h0,b0) = state of the model, and b // (h0,b0) = state of the model, and b
h0 = (A+0)->Val[i] ; h0 = (A + 0)->Val[i];
b0 = (A+1)->Val[i] ; b0 = (A + 1)->Val[i];
b = (A+2)->Val[i] ; b = (A + 2)->Val[i];
// Compute the magnetic field // Compute the magnetic field
h = Fi_h_Ducharne(hi, bi, M, NL, NC, h0, b0, b); h = Fi_h_Ducharne(hi, bi, M, NL, NC, h0, b0, b);
V->Val[i] = h; V->Val[i] = h;
} }
V->Type = VECTOR ; V->Type = VECTOR;
} }
void F_nu_Ducharne(F_ARG) void F_nu_Ducharne(F_ARG)
{ {
int NL, NC, i; int NL, NC, i;
double b0, h0, b[3], h[3], *bi, *hi, *M; double b0, h0, b[3], h[3], *bi, *hi, *M;
struct FunctionActive * D; struct FunctionActive *D;
if(!Fct->Active) Fi_InitListMatrix(Fct, A, V) ; if(!Fct->Active) Fi_InitListMatrix(Fct, A, V);
D = Fct->Active ; D = Fct->Active;
NL = D->Case.ListMatrix.NbrLines ; NL = D->Case.ListMatrix.NbrLines;
NC = D->Case.ListMatrix.NbrColumns ; NC = D->Case.ListMatrix.NbrColumns;
hi = D->Case.ListMatrix.x ; hi = D->Case.ListMatrix.x;
bi = D->Case.ListMatrix.y ; bi = D->Case.ListMatrix.y;
M = D->Case.ListMatrix.data ; M = D->Case.ListMatrix.data;
for(i=0 ; i<3 ; ++i) { for(i = 0; i < 3; ++i) {
// Get (h0,b0) = state of the model, and b // Get (h0,b0) = state of the model, and b
h0 = (A+0)->Val[i] ; h0 = (A + 0)->Val[i];
b0 = (A+1)->Val[i] ; b0 = (A + 1)->Val[i];
b[i] = (A+2)->Val[i] ; b[i] = (A + 2)->Val[i];
// Compute h // Compute h
h[i] = Fi_h_Ducharne(hi, bi, M, NL, NC, h0, b0, b[i]); h[i] = Fi_h_Ducharne(hi, bi, M, NL, NC, h0, b0, b[i]);
} }
V->Type = TENSOR_SYM ; V->Type = TENSOR_SYM;
V->Val[0] = (b[0] == 0) ? 1/(1e4*MU0) : h[0]/b[0] ; V->Val[1] = 0.0 ; V->V V->Val[0] = (b[0] == 0) ? 1 / (1e4 * MU0) : h[0] / b[0];
al[2] = 0 ; V->Val[1] = 0.0;
V->Val[3] = (b[1] == 0) ? 1/(1e4*MU0) : h[1]/b[1] ; V->Val[4] = 0 ; V->Val[2] = 0;
V->Val[5] = (b[2] == 0) ? 1/(1e4*MU0) : h[2]/b[2] ; V->Val[3] = (b[1] == 0) ? 1 / (1e4 * MU0) : h[1] / b[1];
V->Val[4] = 0;
V->Val[5] = (b[2] == 0) ? 1 / (1e4 * MU0) : h[2] / b[2];
} }
void F_dhdb_Ducharne(F_ARG) void F_dhdb_Ducharne(F_ARG)
{ {
int NL, NC, i; int NL, NC, i;
double b0, h0, b[3], *bi, *hi, *M, dHdB[3], s; double b0, h0, b[3], *bi, *hi, *M, dHdB[3], s;
struct FunctionActive * D; struct FunctionActive *D;
if(!Fct->Active) Fi_InitListMatrix(Fct, A, V) ; if(!Fct->Active) Fi_InitListMatrix(Fct, A, V);
D = Fct->Active ; D = Fct->Active;
NL = D->Case.ListMatrix.NbrLines ; NL = D->Case.ListMatrix.NbrLines;
NC = D->Case.ListMatrix.NbrColumns ; NC = D->Case.ListMatrix.NbrColumns;
hi = D->Case.ListMatrix.x ; hi = D->Case.ListMatrix.x;
bi = D->Case.ListMatrix.y ; bi = D->Case.ListMatrix.y;
M = D->Case.ListMatrix.data ; M = D->Case.ListMatrix.data;
for(i=0 ; i<3 ; ++i) { for(i = 0; i < 3; ++i) {
// Get (h0,b0) = state of the model, and b // Get (h0,b0) = state of the model, and b
h0 = (A+0)->Val[i] ; h0 = (A + 0)->Val[i];
b0 = (A+1)->Val[i] ; b0 = (A + 1)->Val[i];
b[i] = (A+2)->Val[i] ; b[i] = (A + 2)->Val[i];
s = (b[i] - b0 < 0) ? -1 : +1; s = (b[i] - b0 < 0) ? -1 : +1;
bool IsInGrid = Fi_InterpolationBilinear(hi, bi, M, NL, NC, s*h0, s*b0, &(dH bool IsInGrid =
dB[i])); Fi_InterpolationBilinear(hi, bi, M, NL, NC, s * h0, s * b0, &(dHdB[i]));
if(!IsInGrid) dHdB[i] = MU0 ; if(!IsInGrid) dHdB[i] = MU0;
} }
V->Type = TENSOR_SYM ; V->Type = TENSOR_SYM;
V->Val[0] = dHdB[0] ; V->Val[1] = 0.0 ; V->Val[2] = 0 ; V->Val[0] = dHdB[0];
V->Val[3] = dHdB[1] ; V->Val[4] = 0 ; V->Val[1] = 0.0;
V->Val[5] = dHdB[2] ; V->Val[2] = 0;
V->Val[3] = dHdB[1];
V->Val[4] = 0;
V->Val[5] = dHdB[2];
} }
double norm(const double a[3]) double norm(const double a[3])
{ {
return sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]); return sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]);
} }
//============================================================== //==============================================================
// K. Jacques functions for the Energy-Based Hysteresis Model // K. Jacques functions for the Energy-Based Hysteresis Model
//============================================================== //==============================================================
//--------------------------------------------------------- //---------------------------------------------------------
// SENSITIVE PARAMETERS SET AS GLOBAL VALUES // SENSITIVE PARAMETERS SET AS GLOBAL VALUES
//--------------------------------------------------------- //---------------------------------------------------------
int FLAG_DIM; int FLAG_DIM;
int FLAG_SYM; int FLAG_SYM;
int FLAG_CENTRAL_DIFF; int FLAG_CENTRAL_DIFF;
int FLAG_INVMETHOD; int FLAG_INVMETHOD;
int FLAG_JACEVAL; int FLAG_JACEVAL;
int FLAG_APPROACH; int FLAG_APPROACH;
int FLAG_MINMETHOD; int FLAG_MINMETHOD;
int FLAG_ANHYLAW; int FLAG_ANHYLAW;
int FLAG_WARNING; int FLAG_WARNING;
double TOLERANCE_JS; double TOLERANCE_JS;
double TOLERANCE_0; double TOLERANCE_0;
double TOLERANCE_NR; double TOLERANCE_NR;
int MAX_ITER_NR; int MAX_ITER_NR;
double TOLERANCE_OM; double TOLERANCE_OM;
int MAX_ITER_OM ; int MAX_ITER_OM;
int FLAG_ANA ; int FLAG_ANA;
double TOLERANCE_NJ ; double TOLERANCE_NJ;
double DELTA_0; double DELTA_0;
double DELTAJ_0; double DELTAJ_0;
double SLOPE_FACTOR; double SLOPE_FACTOR;
int FLAG_HOMO; int FLAG_HOMO;
int NCOMP; int NCOMP;
void set_sensi_param(struct FunctionActive *D) void set_sensi_param(struct FunctionActive *D)
{ {
::FLAG_DIM = D->Case.Interpolation.x[0] ; ::FLAG_DIM = D->Case.Interpolation.x[0];
::FLAG_SYM = 0; ::FLAG_SYM = 0;
::FLAG_CENTRAL_DIFF = 1; ::FLAG_CENTRAL_DIFF = 1;
int j = 5+2*D->Case.Interpolation.x[1]; int j = 5 + 2 * D->Case.Interpolation.x[1];
//int j = 11 ; // int j = 11 ;
::FLAG_INVMETHOD = D->Case.Interpolation.x[j+1] ; ::FLAG_INVMETHOD = D->Case.Interpolation.x[j + 1];
/* /*
FLAG_INVMETHOD = 1 --> NR_ana (homemade) FLAG_INVMETHOD = 1 --> NR_ana (homemade)
FLAG_INVMETHOD = 2 --> NR_num (homemade) FLAG_INVMETHOD = 2 --> NR_num (homemade)
FLAG_INVMETHOD = 3 --> Good_bfgs (homemade) FLAG_INVMETHOD = 3 --> Good_bfgs (homemade)
*/ */
::FLAG_JACEVAL = D->Case.Interpolation.x[j+2] ; ::FLAG_JACEVAL = D->Case.Interpolation.x[j + 2];
/* /*
FLAG_JACEVAL = 1 --> JAC_ana FLAG_JACEVAL = 1 --> JAC_ana
FLAG_JACEVAL = 2 --> JAC_num FLAG_JACEVAL = 2 --> JAC_num
*/ */
::FLAG_APPROACH = D->Case.Interpolation.x[j+3] ; ::FLAG_APPROACH = D->Case.Interpolation.x[j + 3];
/* /*
FLAG_APPROACH = 1 --> variational approach (Jk) FLAG_APPROACH = 1 --> variational approach (Jk)
FLAG_APPROACH = 2 --> Vector Play Model approach (hrk) FLAG_APPROACH = 2 --> Vector Play Model approach (hrk)
FLAG_APPROACH = 3 --> full differential approach (hrk) FLAG_APPROACH = 3 --> full differential approach (hrk)
*/ */
::FLAG_MINMETHOD = D->Case.Interpolation.x[j+4] ; ::FLAG_MINMETHOD = D->Case.Interpolation.x[j + 4];
/* /*
FLAG_MINMETHOD = 1 --> steepest descent (homemade) FLAG_MINMETHOD = 1 --> steepest descent (homemade)
FLAG_MINMETHOD = 2 --> conjugate fr (gsl) FLAG_MINMETHOD = 2 --> conjugate fr (gsl)
FLAG_MINMETHOD = 3 --> conjugate pr (gsl) FLAG_MINMETHOD = 3 --> conjugate pr (gsl)
FLAG_MINMETHOD = 4 --> bfgs2 (gsl) FLAG_MINMETHOD = 4 --> bfgs2 (gsl)
FLAG_MINMETHOD = 5 --> bfgs (gsl) FLAG_MINMETHOD = 5 --> bfgs (gsl)
FLAG_MINMETHOD = 6 --> steepest descent (gsl) FLAG_MINMETHOD = 6 --> steepest descent (gsl)
FLAG_MINMETHOD = 11 --> steepest descent+ (homemade)\n" FLAG_MINMETHOD = 11 --> steepest descent+ (homemade)\n"
FLAG_MINMETHOD = 22 --> conjugate Fletcher-Reeves (homemade)\n" FLAG_MINMETHOD = 22 --> conjugate Fletcher-Reeves (homemade)\n"
FLAG_MINMETHOD = 33 --> conjugate Polak-Ribiere (homemade)\n" FLAG_MINMETHOD = 33 --> conjugate Polak-Ribiere (homemade)\n"
FLAG_MINMETHOD = 333 --> conjugate Polak-Ribiere+ (homemade)\n" FLAG_MINMETHOD = 333 --> conjugate Polak-Ribiere+ (homemade)\n"
FLAG_MINMETHOD = 1999 --> conjugate Dai Yuan 1999 (p.85) (homemade)\n" FLAG_MINMETHOD = 1999 --> conjugate Dai Yuan 1999 (p.85) (homemade)\n"
FLAG_MINMETHOD = 2005 --> conjugate Hager Zhang 2005 (p.161) (homemade)\n" FLAG_MINMETHOD = 2005 --> conjugate Hager Zhang 2005 (p.161) (homemade)\n"
FLAG_MINMETHOD = 77 --> newton (homemade)\n", ::FLAG_MINMETHOD); FLAG_MINMETHOD = 77 --> newton (homemade)\n", ::FLAG_MINMETHOD);
*/ */
::FLAG_ANHYLAW = D->Case.Interpolation.x[j+5] ; ::FLAG_ANHYLAW = D->Case.Interpolation.x[j + 5];
/* /*
FLAG_ANHYLAW = 1 --> hyperbolic tangent FLAG_ANHYLAW = 1 --> hyperbolic tangent
FLAG_ANHYLAW = 2 --> double langevin function FLAG_ANHYLAW = 2 --> double langevin function
*/ */
::FLAG_WARNING = D->Case.Interpolation.x[j+6] ; ::FLAG_WARNING = D->Case.Interpolation.x[j + 6];
/* /*
#define FLAG_WARNING_INFO_INV 1 #define FLAG_WARNING_INFO_INV 1
#define FLAG_WARNING_INFO_APPROACH 2 #define FLAG_WARNING_INFO_APPROACH 2
#define FLAG_WARNING_STOP_INV 10 #define FLAG_WARNING_STOP_INV 10
#define FLAG_WARNING_DISPABOVEITER 1 #define FLAG_WARNING_DISPABOVEITER 1
*/ */
::TOLERANCE_JS = D->Case.Interpolation.x[j+7] ; // SENSITIVE_PARAM (1.e ::TOLERANCE_JS =
-3) // 1.e-4 D->Case.Interpolation.x[j + 7]; // SENSITIVE_PARAM (1.e-3) // 1.e-4
::TOLERANCE_0 = D->Case.Interpolation.x[j+8] ; // SENSITIVE_PARAM (1.e ::TOLERANCE_0 = D->Case.Interpolation.x[j + 8]; // SENSITIVE_PARAM (1.e-7)
-7)
::TOLERANCE_NR =
::TOLERANCE_NR = D->Case.Interpolation.x[j+9] ; // SENSITIVE_PARAM (1.e D->Case.Interpolation.x[j + 9]; // SENSITIVE_PARAM (1.e-7) // 1.e-8 needed
-7) // 1.e-8 needed for diff with NR,1.e-5 // for diff with NR,1.e-5
::MAX_ITER_NR = D->Case.Interpolation.x[j+10] ; // SENSITIVE_PARAM (20 ::MAX_ITER_NR = D->Case.Interpolation.x[j + 10]; // SENSITIVE_PARAM (200)
0)
::TOLERANCE_OM =
::TOLERANCE_OM = D->Case.Interpolation.x[j+11] ; // SENSITIVE_PARAM (1. D->Case.Interpolation
e-11)// 1.e-15 allows to work for square if TOLERANCE_NJ=1.e-3 & DELTA_0=1.e-5 f .x[j + 11]; // SENSITIVE_PARAM (1.e-11)// 1.e-15 allows to work for square
or numjac) // if TOLERANCE_NJ=1.e-3 & DELTA_0=1.e-5 for numjac)
::MAX_ITER_OM = D->Case.Interpolation.x[j+12] ; // SENSITIVE_PARAM (70 ::MAX_ITER_OM = D->Case.Interpolation.x[j + 12]; // SENSITIVE_PARAM (700)
0)
::FLAG_ANA = D->Case.Interpolation
::FLAG_ANA = D->Case.Interpolation.x[j+13] ; // SENSITIVE_PARAM (0= .x[j + 13]; // SENSITIVE_PARAM (0='only numerical jacobian')
'only numerical jacobian') ::TOLERANCE_NJ =
::TOLERANCE_NJ = D->Case.Interpolation.x[j+14] ; // SENSITIVE_PARAM (1. D->Case.Interpolation
e-5 for square; .x[j + 14]; // SENSITIVE_PARAM (1.e-5 for square;
// 1. // 1.e-3 for VinchT.pro & transfo.pro)
e-3 for VinchT.pro & transfo.pro) ::DELTA_0 = D->Case.Interpolation
::DELTA_0 = D->Case.Interpolation.x[j+15] ; // SENSITIVE_PARAM (1. .x[j + 15]; // SENSITIVE_PARAM (1.e-3 for square;
e-3 for square; // 1.e0 for VinchT & transfo)
// 1. ::DELTAJ_0 = 1e-3; // only used with VAR approach when a Numerical approx of
e0 for VinchT & transfo) // the hessian dd_omega is called in Taylor approx
::DELTAJ_0 = 1e-3; //only used with VAR approach when a Numerical a ::SLOPE_FACTOR = 1; // or 1e2 for better convergence
pprox of the hessian dd_omega is called in Taylor approx ::FLAG_HOMO = D->Case.Interpolation.x[j + 16]; //
::SLOPE_FACTOR = 1; // or 1e2 for better convergence
::FLAG_HOMO = D->Case.Interpolation.x[j+16] ; //
/* /*
int LenX= D->Case.ListMatrix.NbrLines-(j+17); int LenX= D->Case.ListMatrix.NbrLines-(j+17);
printf("oh my: %d\n", LenX ); printf("oh my: %d\n", LenX );
for (int n=0; n<LenX;n++) for (int n=0; n<LenX;n++)
printf("h(%d): %g\n", n, D->Case.Interpolation.x[j+17+n] ); printf("h(%d): %g\n", n, D->Case.Interpolation.x[j+17+n] );
getchar(); getchar();
*/ */
switch(::FLAG_SYM) switch(::FLAG_SYM) {
{ case 1: ::NCOMP = 6; break;
case 1: case 0: ::NCOMP = 9; break;
::NCOMP=6; default:
break; Message::Error("Invalid parameter (FLAG_SYM = 0 or 1) for function "
case 0: "'set_sensi_param'.\n");
::NCOMP=9;
break;
default:
Message::Error("Invalid parameter (FLAG_SYM = 0 or 1) for function 'set_se
nsi_param'.\n");
break; break;
} }
} }
struct params_Cells_EB struct params_Cells_EB {
{
int idcell, N; int idcell, N;
double Ja, ha, Jb, hb; double Ja, ha, Jb, hb;
double *kappa, *w, *Xp; double *kappa, *w, *Xp;
double h[3]; double h[3];
int compout; int compout;
double Jp[3]; double Jp[3];
}; };
//---------------------------------------------------------- //----------------------------------------------------------
//************************************************ //************************************************
// Usefull Mathematical functions : // Usefull Mathematical functions :
//************************************************ //************************************************
bool limiter(const double Js, double v[3]) bool limiter(const double Js, double v[3])
{ {
double max = (1-::TOLERANCE_JS)*Js ; double max = (1 - ::TOLERANCE_JS) * Js;
double mod = norm(v); double mod = norm(v);
if(mod >= max){ if(mod >= max) {
for(int n = 0; n < 3; n++) v[n] *= max / mod;
for (int n=0; n<3; n++)
v[n] *= max/mod;
return true; return true;
//Message::Warning("Js=%g, norm(J)=%g", Js, mod); // Message::Warning("Js=%g, norm(J)=%g", Js, mod);
} }
return false; return false;
} }
double Mul_VecVec(const double *v1, const double *v2) double Mul_VecVec(const double *v1, const double *v2)
{ {
return v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2]; return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
} }
void Mul_TensorVec(const double *M, const double *v, double *Mv, const int trans void Mul_TensorVec(const double *M, const double *v, double *Mv,
pose_M) const int transpose_M)
{ {
switch(::FLAG_SYM) switch(::FLAG_SYM) {
{ case 1:
case 1: Mv[0] = M[0] * v[0] + M[1] * v[1] + M[2] * v[2];
Mv[0]=M[0]*v[0]+M[1]*v[1]+M[2]*v[2]; Mv[1] = M[1] * v[0] + M[3] * v[1] + M[4] * v[2];
Mv[1]=M[1]*v[0]+M[3]*v[1]+M[4]*v[2]; Mv[2] = M[2] * v[0] + M[4] * v[1] + M[5] * v[2];
Mv[2]=M[2]*v[0]+M[4]*v[1]+M[5]*v[2];
break; break;
case 0: case 0:
if(transpose_M==1) if(transpose_M == 1) {
{ Mv[0] = M[0] * v[0] + M[3] * v[1] + M[6] * v[2];
Mv[0]=M[0]*v[0]+M[3]*v[1]+M[6]*v[2]; Mv[1] = M[1] * v[0] + M[4] * v[1] + M[7] * v[2];
Mv[1]=M[1]*v[0]+M[4]*v[1]+M[7]*v[2]; Mv[2] = M[2] * v[0] + M[5] * v[1] + M[8] * v[2];
Mv[2]=M[2]*v[0]+M[5]*v[1]+M[8]*v[2]; }
} else {
else Mv[0] = M[0] * v[0] + M[1] * v[1] + M[2] * v[2];
{ Mv[1] = M[3] * v[0] + M[4] * v[1] + M[5] * v[2];
Mv[0]=M[0]*v[0]+M[1]*v[1]+M[2]*v[2]; Mv[2] = M[6] * v[0] + M[7] * v[1] + M[8] * v[2];
Mv[1]=M[3]*v[0]+M[4]*v[1]+M[5]*v[2]; }
Mv[2]=M[6]*v[0]+M[7]*v[1]+M[8]*v[2];
}
break; break;
default: default:
Message::Error("Invalid parameter for function 'Mul_TensorVec'"); Message::Error("Invalid parameter for function 'Mul_TensorVec'");
break; break;
} }
} }
void Mul_TensorSymTensorSym(double *A, double *B, double *C) void Mul_TensorSymTensorSym(double *A, double *B, double *C)
{ {
//---------------------- //----------------------
//What is done actually: C[9] = A[6] . B[6] // What is done actually: C[9] = A[6] . B[6]
//---------------------- //----------------------
C[0]=A[0]*B[0]+A[1]*B[1]+A[2]*B[2]; C[0] = A[0] * B[0] + A[1] * B[1] + A[2] * B[2];
C[1]=A[0]*B[1]+A[1]*B[3]+A[2]*B[4]; C[1] = A[0] * B[1] + A[1] * B[3] + A[2] * B[4];
C[2]=A[0]*B[2]+A[1]*B[4]+A[2]*B[5]; C[2] = A[0] * B[2] + A[1] * B[4] + A[2] * B[5];
C[3]=A[1]*B[0]+A[3]*B[1]+A[4]*B[2]; C[3] = A[1] * B[0] + A[3] * B[1] + A[4] * B[2];
C[4]=A[1]*B[1]+A[3]*B[3]+A[4]*B[4]; C[4] = A[1] * B[1] + A[3] * B[3] + A[4] * B[4];
C[5]=A[1]*B[2]+A[3]*B[4]+A[4]*B[5]; C[5] = A[1] * B[2] + A[3] * B[4] + A[4] * B[5];
C[6]=A[2]*B[0]+A[4]*B[1]+A[5]*B[2]; C[6] = A[2] * B[0] + A[4] * B[1] + A[5] * B[2];
C[7]=A[2]*B[1]+A[4]*B[3]+A[5]*B[4]; C[7] = A[2] * B[1] + A[4] * B[3] + A[5] * B[4];
C[8]=A[2]*B[2]+A[4]*B[4]+A[5]*B[5]; C[8] = A[2] * B[2] + A[4] * B[4] + A[5] * B[5];
} }
void Mul_TensorNonSymTensorNonSym(double *A, double *B, double *C) // NOT USED void Mul_TensorNonSymTensorNonSym(double *A, double *B, double *C) // NOT USED
{ {
//---------------------- //----------------------
//What is done actually: C[9] = A[9] . B[9] // What is done actually: C[9] = A[9] . B[9]
//---------------------- //----------------------
C[0]=A[0]*B[0]+A[1]*B[3]+A[2]*B[6]; C[0] = A[0] * B[0] + A[1] * B[3] + A[2] * B[6];
C[1]=A[0]*B[1]+A[1]*B[4]+A[2]*B[7]; C[1] = A[0] * B[1] + A[1] * B[4] + A[2] * B[7];
C[2]=A[0]*B[2]+A[1]*B[5]+A[2]*B[8]; C[2] = A[0] * B[2] + A[1] * B[5] + A[2] * B[8];
C[3]=A[3]*B[0]+A[4]*B[3]+A[5]*B[6]; C[3] = A[3] * B[0] + A[4] * B[3] + A[5] * B[6];
C[4]=A[3]*B[1]+A[4]*B[4]+A[5]*B[7]; C[4] = A[3] * B[1] + A[4] * B[4] + A[5] * B[7];
C[5]=A[3]*B[2]+A[4]*B[5]+A[5]*B[8]; C[5] = A[3] * B[2] + A[4] * B[5] + A[5] * B[8];
C[6]=A[6]*B[0]+A[7]*B[3]+A[8]*B[6]; C[6] = A[6] * B[0] + A[7] * B[3] + A[8] * B[6];
C[7]=A[6]*B[1]+A[7]*B[4]+A[8]*B[7]; C[7] = A[6] * B[1] + A[7] * B[4] + A[8] * B[7];
C[8]=A[6]*B[2]+A[7]*B[5]+A[8]*B[8]; C[8] = A[6] * B[2] + A[7] * B[5] + A[8] * B[8];
} }
void Mul_TensorNonSymTensorSym(double *A, double *B, double *C) //NOT USED void Mul_TensorNonSymTensorSym(double *A, double *B, double *C) // NOT USED
{ {
/* /*
//---------------------- //----------------------
//What is done actually: C[9] = A[9] . B[6] //What is done actually: C[9] = A[9] . B[6]
//---------------------- //----------------------
// Non Sym Output C + 3D case // Non Sym Output C + 3D case
C[0] = A[0] * B[0]+A[1] * B[1]+A[2] * B[2]; //xx C[0] = A[0] * B[0]+A[1] * B[1]+A[2] * B[2]; //xx
C[1] = A[0] * B[1]+A[1] * B[3]+A[2] * B[4]; //xy C[1] = A[0] * B[1]+A[1] * B[3]+A[2] * B[4]; //xy
C[2] = A[0] * B[2]+A[1] * B[4]+A[2] * B[5]; //xz C[2] = A[0] * B[2]+A[1] * B[4]+A[2] * B[5]; //xz
C[3] = A[3] * B[0]+A[4] * B[1]+A[5] * B[2]; //yx C[3] = A[3] * B[0]+A[4] * B[1]+A[5] * B[2]; //yx
skipping to change at line 798 skipping to change at line 825
// Sym Output C + 2D case // Sym Output C + 2D case
C[0] = A[0] * B[0]+A[1] * B[1]+A[2] * B[2]; //xx C[0] = A[0] * B[0]+A[1] * B[1]+A[2] * B[2]; //xx
C[1] = A[0] * B[1]+A[1] * B[3]+A[2] * B[4]; //xy C[1] = A[0] * B[1]+A[1] * B[3]+A[2] * B[4]; //xy
C[2] = 0.; //xz C[2] = 0.; //xz
C[3] = A[3] * B[1]+A[4] * B[3]+A[5] * B[4]; //yy C[3] = A[3] * B[1]+A[4] * B[3]+A[5] * B[4]; //yy
C[4] = 0.; //yz C[4] = 0.; //yz
C[5] = 1.; //zz C[5] = 1.; //zz
//---------------------- //----------------------
*/ */
C[0] = A[0] * B[0]+A[1] * B[1]+A[2] * B[2]; //xx C[0] = A[0] * B[0] + A[1] * B[1] + A[2] * B[2]; // xx
C[1] = A[0] * B[1]+A[1] * B[3]+A[2] * B[4]; //xy C[1] = A[0] * B[1] + A[1] * B[3] + A[2] * B[4]; // xy
switch(::FLAG_SYM) switch(::FLAG_SYM) {
{ case 1: // Symmetrical Tensor
case 1: // Symmetrical Tensor C[3] = A[3] * B[1] + A[4] * B[3] + A[5] * B[4]; // yy
C[3] = A[3] * B[1]+A[4] * B[3]+A[5] * B[4]; //yy switch(::FLAG_DIM) {
switch(::FLAG_DIM) { case 2: // 2D case
case 2: // 2D case C[5] = 1.; // zz
C[5] = 1.; // zz C[2] = C[4] = 0.; // xz //yz
C[2] = C[4] = 0.; //xz //yz break;
break; case 3: // 3D case
case 3: // 3D case C[2] = A[0] * B[2] + A[1] * B[4] + A[2] * B[5]; // xz
C[2] = A[0] * B[2]+A[1] * B[4]+A[2] * B[5]; //xz C[4] = A[3] * B[2] + A[4] * B[4] + A[5] * B[5]; // yz
C[4] = A[3] * B[2]+A[4] * B[4]+A[5] * B[5]; //yz C[5] = A[6] * B[2] + A[7] * B[4] + A[8] * B[5]; // zz
C[5] = A[6] * B[2]+A[7] * B[4]+A[8] * B[5]; //zz break;
break; default:
default: Message::Error("Invalid parameter (dimension = 2 or 3) for function "
Message::Error("Invalid parameter (dimension = 2 or 3) for function 'M "'Mul_TensorSymTensorNonSym'.");
ul_TensorSymTensorNonSym'."); break;
break; }
}
break;
case 0: // Non Symmetrical Tensor
C[3] = A[3] * B[0]+A[4] * B[1]+A[5] * B[2]; //yx
C[4] = A[3] * B[1]+A[4] * B[3]+A[5] * B[4]; //yy
switch(::FLAG_DIM) {
case 2: // 2D case
C[8] = 1.; // zz
C[2] = C[5] = C[6] = C[7] = 0.; //xz //yz //zx //zy
break;
case 3: // 3D case
C[2] = A[0] * B[2]+A[1] * B[4]+A[2] * B[5]; //xz
C[5] = A[3] * B[2]+A[4] * B[4]+A[5] * B[5]; //yz
C[6] = A[6] * B[0]+A[7] * B[1]+A[8] * B[2]; //zx
C[7] = A[6] * B[1]+A[7] * B[3]+A[8] * B[4]; //zy
C[8] = A[6] * B[2]+A[7] * B[4]+A[8] * B[5]; //zz
break;
default:
Message::Error("Invalid parameter (dimension = 2 or 3) for function 'M
ul_TensorSymTensorNonSym'.");
break;
}
break; break;
case 0: // Non Symmetrical Tensor
C[3] = A[3] * B[0] + A[4] * B[1] + A[5] * B[2]; // yx
C[4] = A[3] * B[1] + A[4] * B[3] + A[5] * B[4]; // yy
switch(::FLAG_DIM) {
case 2: // 2D case
C[8] = 1.; // zz
C[2] = C[5] = C[6] = C[7] = 0.; // xz //yz //zx //zy
break;
case 3: // 3D case
C[2] = A[0] * B[2] + A[1] * B[4] + A[2] * B[5]; // xz
C[5] = A[3] * B[2] + A[4] * B[4] + A[5] * B[5]; // yz
C[6] = A[6] * B[0] + A[7] * B[1] + A[8] * B[2]; // zx
C[7] = A[6] * B[1] + A[7] * B[3] + A[8] * B[4]; // zy
C[8] = A[6] * B[2] + A[7] * B[4] + A[8] * B[5]; // zz
break;
default: default:
Message::Error("Invalid parameter (FLAG_SYM = 0 or 1) for function 'Mul_Te Message::Error("Invalid parameter (dimension = 2 or 3) for function "
nsorSymTensorNonSym'.\n"); "'Mul_TensorSymTensorNonSym'.");
break;
}
break;
default:
Message::Error("Invalid parameter (FLAG_SYM = 0 or 1) for function "
"'Mul_TensorSymTensorNonSym'.\n");
break; break;
} }
} }
void Mul_TensorSymTensorNonSym(double *A, double *B, double *C) void Mul_TensorSymTensorNonSym(double *A, double *B, double *C)
{ {
/* /*
//---------------------- //----------------------
//What is done actually: C[9] = A[6] . B[9] //What is done actually: C[9] = A[6] . B[9]
//---------------------- //----------------------
// Non Sym Output C + 3D case // Non Sym Output C + 3D case
C[0] = A[0] * B[0]+A[1] * B[3]+A[2] * B[6]; //xx C[0] = A[0] * B[0]+A[1] * B[3]+A[2] * B[6]; //xx
C[1] = A[0] * B[1]+A[1] * B[4]+A[2] * B[7]; //xy C[1] = A[0] * B[1]+A[1] * B[4]+A[2] * B[7]; //xy
C[2] = A[0] * B[2]+A[1] * B[5]+A[2] * B[8]; //xz C[2] = A[0] * B[2]+A[1] * B[5]+A[2] * B[8]; //xz
C[3] = A[1] * B[0]+A[3] * B[3]+A[4] * B[6]; //yx C[3] = A[1] * B[0]+A[3] * B[3]+A[4] * B[6]; //yx
C[4] = A[1] * B[1]+A[3] * B[4]+A[4] * B[7]; //yy C[4] = A[1] * B[1]+A[3] * B[4]+A[4] * B[7]; //yy
skipping to change at line 892 skipping to change at line 920
// Sym Output C + 2D case // Sym Output C + 2D case
C[0] = A[0] * B[0]+A[1] * B[3]+A[2] * B[6]; //xx C[0] = A[0] * B[0]+A[1] * B[3]+A[2] * B[6]; //xx
C[1] = A[0] * B[1]+A[1] * B[4]+A[2] * B[7]; //xy C[1] = A[0] * B[1]+A[1] * B[4]+A[2] * B[7]; //xy
C[2] = 0.; //xz C[2] = 0.; //xz
C[3] = A[1] * B[1]+A[3] * B[4]+A[4] * B[7]; //yy C[3] = A[1] * B[1]+A[3] * B[4]+A[4] * B[7]; //yy
C[4] = 0.; //yz C[4] = 0.; //yz
C[5] = 1.; //zz C[5] = 1.; //zz
//---------------------- //----------------------
*/ */
C[0] = A[0] * B[0]+A[1] * B[3]+A[2] * B[6]; //xx C[0] = A[0] * B[0] + A[1] * B[3] + A[2] * B[6]; // xx
C[1] = A[0] * B[1]+A[1] * B[4]+A[2] * B[7]; //xy C[1] = A[0] * B[1] + A[1] * B[4] + A[2] * B[7]; // xy
switch(::FLAG_SYM) switch(::FLAG_SYM) {
{ case 1: // Symmetrical Tensor
case 1: // Symmetrical Tensor C[3] = A[1] * B[1] + A[3] * B[4] + A[4] * B[7]; // yy
C[3] = A[1] * B[1]+A[3] * B[4]+A[4] * B[7]; //yy switch(::FLAG_DIM) {
switch(::FLAG_DIM) { case 2: // 2D case
case 2: // 2D case C[5] = 1.; // zz
C[5] = 1.; // zz C[2] = C[4] = 0.; // xz //yz
C[2] = C[4] = 0.; //xz //yz break;
break; case 3: // 3D case
case 3: // 3D case C[2] = A[0] * B[2] + A[1] * B[5] + A[2] * B[8]; // xz
C[2] = A[0] * B[2]+A[1] * B[5]+A[2] * B[8]; //xz C[4] = A[1] * B[2] + A[3] * B[5] + A[4] * B[8]; // yz
C[4] = A[1] * B[2]+A[3] * B[5]+A[4] * B[8]; //yz C[5] = A[2] * B[2] + A[4] * B[5] + A[5] * B[8]; // zz
C[5] = A[2] * B[2]+A[4] * B[5]+A[5] * B[8]; //zz break;
break; default:
default: Message::Error("Invalid parameter (dimension = 2 or 3) for function "
Message::Error("Invalid parameter (dimension = 2 or 3) for function 'M "'Mul_TensorSymTensorNonSym'.");
ul_TensorSymTensorNonSym'."); break;
break; }
}
break;
case 0: // Non Symmetrical Tensor
C[3] = A[1] * B[0]+A[3] * B[3]+A[4] * B[6]; //yx
C[4] = A[1] * B[1]+A[3] * B[4]+A[4] * B[7]; //yy
switch(::FLAG_DIM) {
case 2: // 2D case
C[8] = 1.; // zz
C[2] = C[5] = C[6] = C[7] = 0.; //xz //yz //zx //zy
break;
case 3: // 3D case
C[2] = A[0] * B[2]+A[1] * B[5]+A[2] * B[8]; //xz
C[5] = A[1] * B[2]+A[3] * B[5]+A[4] * B[8]; //yz
C[6] = A[2] * B[0]+A[4] * B[3]+A[5] * B[6]; //zx
C[7] = A[2] * B[1]+A[4] * B[4]+A[5] * B[7]; //zy
C[8] = A[2] * B[2]+A[4] * B[5]+A[5] * B[8]; //zz
break;
default:
Message::Error("Invalid parameter (dimension = 2 or 3) for function 'M
ul_TensorSymTensorNonSym'.");
break;
}
break; break;
case 0: // Non Symmetrical Tensor
C[3] = A[1] * B[0] + A[3] * B[3] + A[4] * B[6]; // yx
C[4] = A[1] * B[1] + A[3] * B[4] + A[4] * B[7]; // yy
switch(::FLAG_DIM) {
case 2: // 2D case
C[8] = 1.; // zz
C[2] = C[5] = C[6] = C[7] = 0.; // xz //yz //zx //zy
break;
case 3: // 3D case
C[2] = A[0] * B[2] + A[1] * B[5] + A[2] * B[8]; // xz
C[5] = A[1] * B[2] + A[3] * B[5] + A[4] * B[8]; // yz
C[6] = A[2] * B[0] + A[4] * B[3] + A[5] * B[6]; // zx
C[7] = A[2] * B[1] + A[4] * B[4] + A[5] * B[7]; // zy
C[8] = A[2] * B[2] + A[4] * B[5] + A[5] * B[8]; // zz
break;
default: default:
Message::Error("Invalid parameter (FLAG_SYM = 0 or 1) for function 'Mul_Te Message::Error("Invalid parameter (dimension = 2 or 3) for function "
nsorSymTensorNonSym'.\n"); "'Mul_TensorSymTensorNonSym'.");
break;
}
break;
default:
Message::Error("Invalid parameter (FLAG_SYM = 0 or 1) for function "
"'Mul_TensorSymTensorNonSym'.\n");
break; break;
} }
} }
void Inv_Tensor3x3(double *T, double *invT) void Inv_Tensor3x3(double *T, double *invT)
{ {
double det; double det;
switch(::FLAG_DIM) switch(::FLAG_DIM) {
{ case 2:
case 2: det = T[0] * T[4] - T[1] * T[3];
det = T[0] * T[4] - T[1] * T[3]; if(!det) Message::Error("Null determinant of invT! Case %d", ::FLAG_DIM);
if (!det) invT[0] = T[4] / det;
Message::Error("Null determinant of invT! Case %d", ::FLAG_DIM); invT[1] = -T[1] / det;
invT[0]= T[4]/det; invT[3] = -T[3] / det;
invT[1]= -T[1]/det; invT[4] = T[0] / det;
invT[3]= -T[3]/det; invT[2] = invT[5] = invT[6] = invT[7] = 0.;
invT[4]= T[0]/det; invT[8] = 1.;
invT[2]= invT[5] = invT[6] = invT[7] = 0.;
invT[8]= 1.; break;
case 3:
break; det = T[0] * T[4] * T[8] + T[1] * T[5] * T[6] + T[2] * T[3] * T[7] -
case 3: T[2] * T[4] * T[6] - T[0] * T[5] * T[7] - T[1] * T[3] * T[8];
det= T[0]*T[4]*T[8]+T[1]*T[5]*T[6]+T[2]*T[3]*T[7] if(!det) Message::Error("Null determinant of invT! Case %d", ::FLAG_DIM);
-T[2]*T[4]*T[6]-T[0]*T[5]*T[7]-T[1]*T[3]*T[8]; invT[0] = (T[4] * T[8] - T[5] * T[7]) / det;
if (!det) invT[1] = (T[2] * T[7] - T[1] * T[8]) / det;
Message::Error("Null determinant of invT! Case %d", ::FLAG_DIM); invT[2] = (T[1] * T[5] - T[2] * T[4]) / det;
invT[0]=(T[4]*T[8]-T[5]*T[7])/det; invT[3] = (T[5] * T[6] - T[3] * T[8]) / det;
invT[1]=(T[2]*T[7]-T[1]*T[8])/det; invT[4] = (T[0] * T[8] - T[2] * T[6]) / det;
invT[2]=(T[1]*T[5]-T[2]*T[4])/det; invT[5] = (T[2] * T[3] - T[0] * T[5]) / det;
invT[3]=(T[5]*T[6]-T[3]*T[8])/det; invT[6] = (T[3] * T[7] - T[4] * T[6]) / det;
invT[4]=(T[0]*T[8]-T[2]*T[6])/det; invT[7] = (T[1] * T[6] - T[0] * T[7]) / det;
invT[5]=(T[2]*T[3]-T[0]*T[5])/det; invT[8] = (T[0] * T[4] - T[1] * T[3]) / det;
invT[6]=(T[3]*T[7]-T[4]*T[6])/det;
invT[7]=(T[1]*T[6]-T[0]*T[7])/det;
invT[8]=(T[0]*T[4]-T[1]*T[3])/det;
break; break;
default: default:
Message::Error("Invalid parameter for function 'Inv_Tensor3x3'"); Message::Error("Invalid parameter for function 'Inv_Tensor3x3'");
break; break;
} }
} }
void Inv_TensorSym3x3(double *T, double *invT) void Inv_TensorSym3x3(double *T, double *invT)
{ {
double det ; double det;
switch(::FLAG_DIM) switch(::FLAG_DIM) {
{ case 2:
case 2: det = T[0] * T[3] - T[1] * T[1];
det = T[0] * T[3] - T[1] * T[1]; if(!det)
if (!det) Message::Error("Null determinant of Sym invT! Case %d", ::FLAG_DIM);
Message::Error("Null determinant of Sym invT! Case %d", ::FLAG_DIM); invT[0] = T[3] / det;
invT[0] = T[3]/det ; invT[1] = -T[1] / det;
invT[1] = -T[1]/det ; invT[3] = T[0] / det;
invT[3] = T[0]/det ; invT[2] = invT[4] = 0.;
invT[2] = invT[4] = 0. ; invT[5] = 1.;
invT[5] = 1.; break;
break;
case 3:
case 3: det = T[0] * (T[3] * T[5] - T[4] * T[4]) -
det = T[0] * (T[3] * T[5] - T[4] * T[4]) T[1] * (T[1] * T[5] - T[4] * T[2]) +
- T[1] * (T[1] * T[5] - T[4] * T[2]) T[2] * (T[1] * T[4] - T[3] * T[2]);
+ T[2] * (T[1] * T[4] - T[3] * T[2]); if(!det)
if (!det) Message::Error("Null determinant of Sym invT! Case %d", ::FLAG_DIM);
Message::Error("Null determinant of Sym invT! Case %d", ::FLAG_DIM); invT[0] = (T[3] * T[5] - T[4] * T[4]) / det;
invT[0] = (T[3]*T[5]-T[4]*T[4])/det ; invT[1] = -(T[1] * T[5] - T[2] * T[4]) / det;
invT[1] = -(T[1]*T[5]-T[2]*T[4])/det ; invT[2] = (T[1] * T[4] - T[2] * T[3]) / det;
invT[2] = (T[1]*T[4]-T[2]*T[3])/det ; invT[3] = (T[0] * T[5] - T[2] * T[2]) / det;
invT[3] = (T[0]*T[5]-T[2]*T[2])/det ; invT[4] = -(T[0] * T[4] - T[1] * T[2]) / det;
invT[4] = -(T[0]*T[4]-T[1]*T[2])/det ; invT[5] = (T[0] * T[3] - T[1] * T[1]) / det;
invT[5] = (T[0]*T[3]-T[1]*T[1])/det ;
break; break;
default: default:
Message::Error("Invalid parameter for function 'Inv_TensorSym3x3'"); Message::Error("Invalid parameter for function 'Inv_TensorSym3x3'");
break; break;
} }
} }
// pour info // pour info
// #define F_ARG struct Function * Fct, struct Value * A, struct Value * V // #define F_ARG struct Function * Fct, struct Value * A, struct Value * V
// http://www.gnu.org/software/gsl/manual/html_node/Multimin-Examples.html // http://www.gnu.org/software/gsl/manual/html_node/Multimin-Examples.html
#if defined(HAVE_GSL) #if defined(HAVE_GSL)
#include <gsl/gsl_vector.h> #include <gsl/gsl_vector.h>
skipping to change at line 1035 skipping to change at line 1061
#include <gsl/gsl_roots.h> #include <gsl/gsl_roots.h>
#endif #endif
//************************************************ //************************************************
// Anhysteretic curve Characteristics : // Anhysteretic curve Characteristics :
//************************************************ //************************************************
// 1. Hyperbolic tangent ( used parameters : Js, alpha) // 1. Hyperbolic tangent ( used parameters : Js, alpha)
double Janhy(double nhr, double Js, double alpha) double Janhy(double nhr, double Js, double alpha)
{ {
double y=nhr/alpha; double y = nhr / alpha;
if (fabs(y)<(::TOLERANCE_0)) if(fabs(y) < (::TOLERANCE_0))
return Js*y; return Js * y;
else else
return Js*tanh(y); return Js * tanh(y);
} }
double dJanhy(double nhr, double Js, double alpha) double dJanhy(double nhr, double Js, double alpha)
{ {
double y=nhr/alpha; double y = nhr / alpha;
if (fabs(y)<(::TOLERANCE_0)) if(fabs(y) < (::TOLERANCE_0))
return Js/alpha; return Js / alpha;
else if (fabs(y)>350) // otherwise overflow else if(fabs(y) > 350) // otherwise overflow
return 0; return 0;
else else
return Js/alpha*(1.-SQU(tanh(y))); return Js / alpha * (1. - SQU(tanh(y)));
} }
double Xanhy(double nhr,double Js, double alpha) double Xanhy(double nhr, double Js, double alpha)
{ {
double y=nhr/alpha; double y = nhr / alpha;
if (fabs(y)<(::TOLERANCE_0)) if(fabs(y) < (::TOLERANCE_0))
return Js/alpha; return Js / alpha;
else else
return Js*tanh(y)/nhr; return Js * tanh(y) / nhr;
} }
double dXanhy(double nhr,double Js, double alpha) double dXanhy(double nhr, double Js, double alpha)
{ {
double y=nhr/alpha; double y = nhr / alpha;
if (fabs(y)<(::TOLERANCE_0)) if(fabs(y) < (::TOLERANCE_0))
return 2./3.*Js*y/alpha; // DOUBT : need to add .../ fxc ?? return 2. / 3. * Js * y / alpha; // DOUBT : need to add .../ fxc ??
else else
return (dJanhy(nhr,Js,alpha)-Xanhy(nhr,Js,alpha))/nhr; return (dJanhy(nhr, Js, alpha) - Xanhy(nhr, Js, alpha)) / nhr;
} }
double IJanhy(double nhr, double Js, double alpha) // = Co-energy double IJanhy(double nhr, double Js, double alpha) // = Co-energy
{ {
double y=nhr/alpha; double y = nhr / alpha;
if (fabs(y)<(::TOLERANCE_0)) if(fabs(y) < (::TOLERANCE_0))
return Js*alpha*SQU(y)/2.; return Js * alpha * SQU(y) / 2.;
else else
return Js*alpha*log(cosh(y)); return Js * alpha * log(cosh(y));
} }
double InvJanhy(double nJ, double Js, double alpha) // = y + y^3/3 + y^5/5 + y^7 double InvJanhy(double nJ, double Js,
/7 double alpha) // = y + y^3/3 + y^5/5 + y^7/7
{ {
double x=nJ/Js; double x = nJ / Js;
if (fabs(x)<(::TOLERANCE_0)) if(fabs(x) < (::TOLERANCE_0))
return alpha*x; return alpha * x;
else else
return alpha*atanh(x); return alpha * atanh(x);
} }
double dInvJanhy(double nJ, double Js, double alpha) double dInvJanhy(double nJ, double Js, double alpha)
{ {
double x=nJ/Js; double x = nJ / Js;
return (alpha/Js)*(1/(1-SQU(x))); // Warning : case x -> 1 <=> J -> Js return (alpha / Js) * (1 / (1 - SQU(x))); // Warning : case x -> 1 <=> J -> Js
} }
// 2. Double Langevin function ( used parameters : Ja, ha, Jb, hb) // 2. Double Langevin function ( used parameters : Ja, ha, Jb, hb)
double Lang(double nhr, double Ja, double ha) //Langevin function = x/3-x^3/45+2 double Lang(double nhr, double Ja,
*x^5/945-x^7/4725+... double ha) // Langevin function = x/3-x^3/45+2*x^5/945-x^7/4725+...
{ {
double y=nhr/ha; double y = nhr / ha;
if (fabs(y)<(::TOLERANCE_0)) if(fabs(y) < (::TOLERANCE_0))
return Ja*y/3.; return Ja * y / 3.;
else else
return Ja*(1./tanh(y)-1./y); return Ja * (1. / tanh(y) - 1. / y);
} }
double dLang(double nhr, double Ja, double ha) double dLang(double nhr, double Ja, double ha)
{ {
double y=nhr/ha; double y = nhr / ha;
if (fabs(y)<(::TOLERANCE_0)) if(fabs(y) < (::TOLERANCE_0))
return Ja/ha/3. ; return Ja / ha / 3.;
else if (fabs(y)>350) // otherwise overflow else if(fabs(y) > 350) // otherwise overflow
return 0 ; return 0;
else else
return Ja/ha*(1./SQU(y)-1./SQU(sinh(y))) ; return Ja / ha * (1. / SQU(y) - 1. / SQU(sinh(y)));
} }
double LangOverx(double nhr, double Ja, double ha) double LangOverx(double nhr, double Ja, double ha)
{ double y=nhr/ha; {
if (fabs(y)<(::TOLERANCE_0)) double y = nhr / ha;
return Ja/ha/3.; if(fabs(y) < (::TOLERANCE_0))
else return Ja / ha / 3.;
return Ja*(1./tanh(y)-1./y)/nhr; else
return Ja * (1. / tanh(y) - 1. / y) / nhr;
} }
double dLangOverx(double nhr, double Ja, double ha) double dLangOverx(double nhr, double Ja, double ha)
{ {
double y=nhr/ha; double y = nhr / ha;
if (fabs(y)<(::TOLERANCE_0)) if(fabs(y) < (::TOLERANCE_0))
return 2./45.*Ja*y/ha; // DOUBT : need to add .../ fxc ?? return 2. / 45. * Ja * y / ha; // DOUBT : need to add .../ fxc ??
else else
return (dLang(nhr,Ja,ha)-LangOverx(nhr,Ja,ha))/nhr; return (dLang(nhr, Ja, ha) - LangOverx(nhr, Ja, ha)) / nhr;
} }
double ILang(double nhr, double Ja, double ha) double ILang(double nhr, double Ja, double ha)
{ {
double y=nhr/ha; double y = nhr / ha;
if (fabs(y)<(::TOLERANCE_0)) if(fabs(y) < (::TOLERANCE_0))
return Ja*ha*SQU(y)/6.; return Ja * ha * SQU(y) / 6.;
else // ILdx(x)=log(sinh(x)/x) gives infinity for x>~300 else // ILdx(x)=log(sinh(x)/x) gives infinity for x>~300
return Ja*ha*( y + log(1.-exp(-2.*y)) - log(2.*y) ); return Ja * ha * (y + log(1. - exp(-2. * y)) - log(2. * y));
} }
double Janhy(double nhr, double Ja, double ha, double Jb, double hb) double Janhy(double nhr, double Ja, double ha, double Jb, double hb)
{ {
return Lang(nhr,Ja,ha)+Lang(nhr,Jb,hb); return Lang(nhr, Ja, ha) + Lang(nhr, Jb, hb);
} }
double dJanhy(double nhr, double Ja, double ha, double Jb, double hb) double dJanhy(double nhr, double Ja, double ha, double Jb, double hb)
{ {
return dLang(nhr,Ja,ha)+dLang(nhr,Jb,hb); return dLang(nhr, Ja, ha) + dLang(nhr, Jb, hb);
} }
double Xanhy(double nhr, double Ja, double ha, double Jb, double hb) double Xanhy(double nhr, double Ja, double ha, double Jb, double hb)
{ {
return LangOverx(nhr,Ja,ha)+LangOverx(nhr,Jb,hb); return LangOverx(nhr, Ja, ha) + LangOverx(nhr, Jb, hb);
} }
double dXanhy(double nhr, double Ja, double ha, double Jb, double hb) double dXanhy(double nhr, double Ja, double ha, double Jb, double hb)
{ {
return dLangOverx(nhr,Ja,ha)+dLangOverx(nhr,Jb,hb); return dLangOverx(nhr, Ja, ha) + dLangOverx(nhr, Jb, hb);
} }
double IJanhy(double nhr, double Ja, double ha, double Jb, double hb) // = Co-e double IJanhy(double nhr, double Ja, double ha, double Jb,
nergy double hb) // = Co-energy
{ {
return ILang(nhr,Ja,ha)+ILang(nhr,Jb,hb); return ILang(nhr, Ja, ha) + ILang(nhr, Jb, hb);
} }
double InvJanhy(double nJ, double Ja, double ha, double Jb, double hb) double InvJanhy(double nJ, double Ja, double ha, double Jb, double hb)
{ {
double y=nJ; double y = nJ;
if (fabs(y)<(::TOLERANCE_0)) if(fabs(y) < (::TOLERANCE_0)) return y / dJanhy(0., Ja, ha, Jb, hb);
return y/dJanhy(0.,Ja,ha,Jb,hb); ///* Fictitious slope above 1e6 (09/06/2016)-------------
///* Fictitious slope above 1e6 (09/06/2016)------------- double tmp = y - Janhy(1100, Ja, ha, Jb, hb);
double tmp = y - Janhy(1100,Ja,ha,Jb,hb); if(tmp > 0) return 1100 + 1e16 * tmp;
if (tmp>0) //*///------------------------------------------------------------------------
return 1100+1e16*tmp; ---
//*///--------------------------------------------------------------------- int i = 0;
------ double x = 0.0;
int i=0; double dJan = dJanhy(x, Ja, ha, Jb, hb);
double x=0.0; dJan = (dJan > 1e-10) ? dJan : 1e-10; // Limitation
double dJan=dJanhy(x,Ja,ha,Jb,hb); double dx = (y - Janhy(x, Ja, ha, Jb, hb)) / dJan;
dJan=(dJan>1e-10)?dJan:1e-10; // Limitation int imax = 100;
double dx = (y-Janhy(x,Ja,ha,Jb,hb))/dJan; while(((fabs(dx) / ((1 > fabs(x)) ? 1 : fabs(x))) > ::TOLERANCE_NR) &&
int imax=100; (i < imax)) {
while ( ((fabs(dx)/((1>fabs(x))?1:fabs(x))) > ::TOLERANCE_NR) && (i<imax) dJan = dJanhy(x, Ja, ha, Jb, hb);
) dJan = (dJan > 1e-10) ? dJan : 1e-10; // Limitation
{ dx = (y - Janhy(x, Ja, ha, Jb, hb)) / dJan;
dJan = dJanhy(x,Ja,ha,Jb,hb); x += dx;
dJan = (dJan>1e-10)?dJan:1e-10; // Limitation i++;
dx = (y-Janhy(x,Ja,ha,Jb,hb))/dJan; }
x += dx; return x;
i++;
}
return x;
} }
double dInvJanhy_hr(double nhr, double Ja, double ha, double Jb, double hb) double dInvJanhy_hr(double nhr, double Ja, double ha, double Jb, double hb)
{ {
double dJdhr=dJanhy(nhr, Ja, ha, Jb, hb); double dJdhr = dJanhy(nhr, Ja, ha, Jb, hb);
if (dJdhr==0.) if(dJdhr == 0.) {
{ Message::Warning(
Message::Warning("dJdhr is too small to be inverted in function 'dInvJanhy_h "dJdhr is too small to be inverted in function 'dInvJanhy_hr'.");
r'.");
return 1.; return 1.;
} }
else else
return 1/dJdhr; return 1 / dJdhr;
} }
double u_hr(double nhr, double Ja, double ha, double Jb, double hb) // = Energy double u_hr(double nhr, double Ja, double ha, double Jb,
with hr as input double hb) // = Energy with hr as input
{ {
return Janhy(nhr,Ja,ha,Jb,hb)*nhr - IJanhy(nhr,Ja,ha,Jb,hb); return Janhy(nhr, Ja, ha, Jb, hb) * nhr - IJanhy(nhr, Ja, ha, Jb, hb);
} }
double u_J(double nJ, double Js, double alpha) // = Energy with J as input = IIn double u_J(double nJ, double Js,
vJanhy // only valid for TANH version double alpha) // = Energy with J as input = IInvJanhy // only valid
// for TANH version
{ {
return alpha*Js *( nJ/Js*atanh(nJ/Js) + 0.5*log(fabs(SQU(nJ/Js)-1)) ); return alpha * Js *
(nJ / Js * atanh(nJ / Js) + 0.5 * log(fabs(SQU(nJ / Js) - 1)));
} }
void Vector_Jk_From_hrk(const double hrk[3], void Vector_Jk_From_hrk(const double hrk[3], void *params, double Jk[3])
void * params,
double Jk[3])
{ {
struct params_Cells_EB *p = (struct params_Cells_EB *) params; struct params_Cells_EB *p = (struct params_Cells_EB *)params;
double wk=1; double wk = 1;
if (p->idcell>=0 && p->idcell<p->N) if(p->idcell >= 0 && p->idcell < p->N) wk = p->w[p->idcell];
wk = p->w[p->idcell]; double Ja = wk * p->Ja;
double Ja = wk*p->Ja; double Jb = wk * p->Jb;
double Jb = wk*p->Jb; double ha = p->ha;
double ha = p->ha ; double hb = p->hb;
double hb = p->hb ;
double nhrk = norm(hrk); double nhrk = norm(hrk);
double Xan = 0; double Xan = 0;
switch(::FLAG_ANHYLAW) { switch(::FLAG_ANHYLAW) {
case 1: // Hyperbolic Tangent Case case 1: // Hyperbolic Tangent Case
Xan = Xanhy(nhrk, Ja, ha); Xan = Xanhy(nhrk, Ja, ha);
break; break;
case 2: // Double Langevin Function Case case 2: // Double Langevin Function Case
Xan = Xanhy(nhrk, Ja, ha, Jb, hb); Xan = Xanhy(nhrk, Ja, ha, Jb, hb);
break; break;
default: default:
Message::Error("Invalid parameter (AnhyLaw = 1 (Tanh) or 2 (DLan) )" Message::Error("Invalid parameter (AnhyLaw = 1 (Tanh) or 2 (DLan) )"
"for function 'Vector_Jk_From_hrk'."); "for function 'Vector_Jk_From_hrk'.");
break; break;
} }
for (int n = 0; n < 3 ; n++) for(int n = 0; n < 3; n++) Jk[n] = Xan * hrk[n];
Jk[n] = Xan * hrk[n];
} }
void Vector_hrk_From_Jk(const double Jk[3], void Vector_hrk_From_Jk(const double Jk[3], void *params, double hrk[3])
void * params,
double hrk[3])
{ {
struct params_Cells_EB *p = (struct params_Cells_EB *)params;
struct params_Cells_EB *p = (struct params_Cells_EB *) params; double wk = 1;
double wk=1; if(p->idcell >= 0 && p->idcell < p->N) wk = p->w[p->idcell];
if (p->idcell >= 0 && p->idcell < p->N) double Ja = wk * p->Ja;
wk = p->w[p->idcell]; double Jb = wk * p->Jb;
double Ja = wk*p->Ja; double ha = p->ha;
double Jb = wk*p->Jb; double hb = p->hb;
double ha = p->ha;
double hb = p->hb;
double nhrk = 0; double nhrk = 0;
double nJk = norm(Jk); double nJk = norm(Jk);
switch(::FLAG_ANHYLAW) { switch(::FLAG_ANHYLAW) {
case 1: // Hyperbolic Tangent Case case 1: // Hyperbolic Tangent Case
nhrk = InvJanhy(nJk, Ja, ha) ; nhrk = InvJanhy(nJk, Ja, ha);
break; break;
case 2: // Double Langevin Function Case case 2: // Double Langevin Function Case
nhrk = InvJanhy(nJk, Ja, ha, Jb, hb) ; nhrk = InvJanhy(nJk, Ja, ha, Jb, hb);
break; break;
default: default:
Message::Error("Invalid parameter (AnhyLaw = 1 (Tanh) or 2 (DLan) )" Message::Error("Invalid parameter (AnhyLaw = 1 (Tanh) or 2 (DLan) )"
"for function 'Vector_hrk_From_Jk'."); "for function 'Vector_hrk_From_Jk'.");
break; break;
} }
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) hrk[n] = (nJk) ? (nhrk / nJk) * Jk[n] : 0.;
hrk[n] = (nJk) ? (nhrk/nJk)*Jk[n] : 0. ; // hrk[n] = (nJk>(::TOLERANCE_0)) ? (nhrk/nJk)*Jk[n] : 0. ;
//hrk[n] = (nJk>(::TOLERANCE_0)) ? (nhrk/nJk)*Jk[n] : 0. ;
} }
void Tensor_dJkdhrk(const double hr[3], void Tensor_dJkdhrk(const double hr[3], void *params, double mutg[6])
void * params,
double mutg[6])
{ {
struct params_Cells_EB *p = (struct params_Cells_EB *)params;
double wk = 1.;
if(p->idcell >= 0 && p->idcell < p->N) wk = p->w[p->idcell];
double Ja = wk * p->Ja;
double Jb = wk * p->Jb;
double ha = p->ha;
double hb = p->hb;
struct params_Cells_EB *p = (struct params_Cells_EB *) params; double nhr = norm(hr);
double wk=1.; double Xan = 0., dXandH2 = 0.;
if (p->idcell>=0 && p->idcell<p->N)
wk = p->w[p->idcell];
double Ja = wk*p->Ja;
double Jb = wk*p->Jb;
double ha = p->ha ;
double hb = p->hb ;
double nhr = norm(hr);
double Xan=0., dXandH2=0.;
switch(::FLAG_ANHYLAW) { switch(::FLAG_ANHYLAW) {
case 1: // Hyperbolic Tangent Case case 1: // Hyperbolic Tangent Case
Xan = Xanhy(nhr, Ja, ha); Xan = Xanhy(nhr, Ja, ha);
dXandH2 = (nhr>(::TOLERANCE_0)) ? (dXanhy(nhr, Ja, ha)/(2*nhr)) : 0. ; dXandH2 = (nhr > (::TOLERANCE_0)) ? (dXanhy(nhr, Ja, ha) / (2 * nhr)) : 0.;
break; break;
case 2: // Double Langevin Function Case case 2: // Double Langevin Function Case
Xan = Xanhy(nhr, Ja, ha, Jb, hb); Xan = Xanhy(nhr, Ja, ha, Jb, hb);
dXandH2 = (nhr>(::TOLERANCE_0)) ? (dXanhy(nhr, Ja, ha, Jb, hb)/(2*nhr)) : dXandH2 =
0. ; (nhr > (::TOLERANCE_0)) ? (dXanhy(nhr, Ja, ha, Jb, hb) / (2 * nhr)) : 0.;
break; break;
default: default:
Message::Error("Invalid parameter (AnhyLaw = 1 (Tanh) or 2 (DLan) )" Message::Error("Invalid parameter (AnhyLaw = 1 (Tanh) or 2 (DLan) )"
"for function 'Tensor_dJkdhrk'."); "for function 'Tensor_dJkdhrk'.");
break; break;
} }
mutg[0] = Xan + 2 * dXandH2 * ( hr[0]* hr[0] ) ;//xx mutg[0] = Xan + 2 * dXandH2 * (hr[0] * hr[0]); // xx
mutg[3] = Xan + 2 * dXandH2 * ( hr[1]* hr[1] ); //yy mutg[3] = Xan + 2 * dXandH2 * (hr[1] * hr[1]); // yy
mutg[1] = 2 * dXandH2 * ( hr[1]* hr[0] ); //xy mutg[1] = 2 * dXandH2 * (hr[1] * hr[0]); // xy
switch(::FLAG_DIM) { switch(::FLAG_DIM) {
case 2: // 2D case case 2: // 2D case
mutg[5] = 1.; mutg[5] = 1.;
mutg[2] = mutg[4] = 0.; mutg[2] = mutg[4] = 0.;
break; break;
case 3: // 3D case case 3: // 3D case
mutg[5]= Xan + 2 * dXandH2 * ( hr[2]* hr[2] ) ; //zz mutg[5] = Xan + 2 * dXandH2 * (hr[2] * hr[2]); // zz
mutg[2]= 2 * dXandH2 * ( hr[2]* hr[0] ) ; //xz mutg[2] = 2 * dXandH2 * (hr[2] * hr[0]); // xz
mutg[4]= 2 * dXandH2 * ( hr[2]* hr[1] ) ; //yz mutg[4] = 2 * dXandH2 * (hr[2] * hr[1]); // yz
break; break;
default: default:
Message::Error("Invalid parameter (dimension = 2 or 3)" Message::Error(
"for function 'Tensor_dJkdhrk'. Analytic Jacobian computation."); "Invalid parameter (dimension = 2 or 3)"
"for function 'Tensor_dJkdhrk'. Analytic Jacobian computation.");
break; break;
} }
} }
//************************************************ //************************************************
// Pseudo-Potential Functional Characteristics : // Pseudo-Potential Functional Characteristics :
//************************************************ //************************************************
#if defined(HAVE_GSL) // due to the use of gsl_vector #if defined(HAVE_GSL) // due to the use of gsl_vector
double omega_f(const gsl_vector *v, void *params) // not in F.h double omega_f(const gsl_vector *v, void *params) // not in F.h
{ {
struct params_Cells_EB *p = (struct params_Cells_EB *) params; struct params_Cells_EB *p = (struct params_Cells_EB *)params;
double wk = p->w[p->idcell]; double wk = p->w[p->idcell];
double Ja = wk*p->Ja; double Ja = wk * p->Ja;
double Jb = wk*p->Jb; double Jb = wk * p->Jb;
double h[3]; double h[3];
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) h[n] = p->h[n];
h[n] = p->h[n];
double J[3]; double J[3];
for (int i=0; i<3; i++) J[i] = gsl_vector_get(v, i); for(int i = 0; i < 3; i++) J[i] = gsl_vector_get(v, i);
limiter(Ja+Jb, J) ; limiter(Ja + Jb, J);
double omega = fct_omega_VAR(h, J, params) ; double omega = fct_omega_VAR(h, J, params);
return omega; return omega;
} }
void omega_df (const gsl_vector *v, void *params, gsl_vector *df) // not in F.h void omega_df(const gsl_vector *v, void *params, gsl_vector *df) // not in F.h
{ {
struct params_Cells_EB *p = (struct params_Cells_EB *)params;
struct params_Cells_EB *p = (struct params_Cells_EB *) params; double wk = p->w[p->idcell];
double wk = p->w[p->idcell]; double Ja = wk * p->Ja;
double Ja = wk*p->Ja; double Jb = wk * p->Jb;
double Jb = wk*p->Jb;
double h[3]; double h[3];
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) h[n] = p->h[n];
h[n] = p->h[n];
double J[3]; double J[3];
for (int i=0; i<3; i++) J[i] = gsl_vector_get(v, i); for(int i = 0; i < 3; i++) J[i] = gsl_vector_get(v, i);
limiter(Ja+Jb, J); limiter(Ja + Jb, J);
double d_omega[3]; double d_omega[3];
fct_d_omega_VAR (J,d_omega,h, params ) ; fct_d_omega_VAR(J, d_omega, h, params);
for (int i=0; i<3; i++) gsl_vector_set(df, i, d_omega[i]); for(int i = 0; i < 3; i++) gsl_vector_set(df, i, d_omega[i]);
} }
void omega_fdf (const gsl_vector *x, void *params, double *f, gsl_vector *df) / void omega_fdf(const gsl_vector *x, void *params, double *f,
/ not in F.h gsl_vector *df) // not in F.h
{ {
*f = omega_f(x, params); *f = omega_f(x, params);
omega_df(x, params, df); omega_df(x, params, df);
} }
#endif #endif
double fct_omega_VAR(const double h[3], double fct_omega_VAR(const double h[3], const double Jk[3], void *params)
const double Jk[3], {
void * params ) struct params_Cells_EB *p = (struct params_Cells_EB *)params;
{
struct params_Cells_EB *p = (struct params_Cells_EB *) params; double kappa = p->kappa[p->idcell];
double wk = p->w[p->idcell];
double kappa = p->kappa[p->idcell]; double Ja = wk * p->Ja;
double wk = p->w[p->idcell]; double ha = p->ha;
double Ja = wk*p->Ja; double Jb = wk * p->Jb;
double ha = p->ha ; double hb = p->hb;
double Jb = wk*p->Jb;
double hb = p->hb ;
double Jkp[3]; double Jkp[3];
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) Jkp[n] = p->Xp[n + 3 * p->idcell];
Jkp[n] = p->Xp[n+3*p->idcell];
double diff[3]; double diff[3];
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) diff[n] = Jk[n] - Jkp[n]; // J-Jp
diff[n] = Jk[n]-Jkp[n]; // J-Jp
// magnetisation Jk assumed to be < the saturation magnetisation Js // magnetisation Jk assumed to be < the saturation magnetisation Js
double nJk = norm(Jk), u=0., nhr=0.; double nJk = norm(Jk), u = 0., nhr = 0.;
// TODO: build a generic u function // TODO: build a generic u function
switch(::FLAG_ANHYLAW) { switch(::FLAG_ANHYLAW) {
case 1: // Hyperbolic Tangent Case case 1: // Hyperbolic Tangent Case
u = u_J(nJk,Ja,ha); // magnetic energy u(J) u = u_J(nJk, Ja, ha); // magnetic energy u(J)
break; break;
case 2: // Double Langevin Function Case case 2: // Double Langevin Function Case
nhr = InvJanhy(nJk, Ja, ha, Jb, hb); nhr = InvJanhy(nJk, Ja, ha, Jb, hb);
u = u_hr(nhr,Ja,ha,Jb,hb); // magnetic energy u(J) u = u_hr(nhr, Ja, ha, Jb, hb); // magnetic energy u(J)
break; break;
default: default:
Message::Error("Invalid parameter (AnhyLaw = 1 (Tanh) or 2 (DLan) )" Message::Error("Invalid parameter (AnhyLaw = 1 (Tanh) or 2 (DLan) )"
"for function 'fct_omega_VAR'."); "for function 'fct_omega_VAR'.");
break; break;
} }
double Jh = Jk[0] * h[0] + Jk[1] * h[1] + Jk[2] * h[2]; // -J.h double Jh = Jk[0] * h[0] + Jk[1] * h[1] + Jk[2] * h[2]; // -J.h
double Dissip = kappa * norm(diff) ; // kappa | J-Jp | double Dissip = kappa * norm(diff); // kappa | J-Jp |
return (u-Jh+Dissip); return (u - Jh + Dissip);
} }
void fct_d_omega_VAR(const double Jk[3], void fct_d_omega_VAR(const double Jk[3], double *d_omega, double h[3],
double *d_omega, void *params)
double h[3],
void * params )
{ {
struct params_Cells_EB *p = (struct params_Cells_EB *) params; struct params_Cells_EB *p = (struct params_Cells_EB *)params;
double kappa = p->kappa[p->idcell]; double kappa = p->kappa[p->idcell];
double Jkp[3], dJk[3], hrk[3]; double Jkp[3], dJk[3], hrk[3];
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) Jkp[n] = p->Xp[n + 3 * p->idcell];
Jkp[n] = p->Xp[n+3*p->idcell];
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) dJk[n] = Jk[n] - Jkp[n];
dJk[n] = Jk[n]-Jkp[n];
double ndJk = norm(dJk); double ndJk = norm(dJk);
Vector_hrk_From_Jk(Jk, params, hrk); Vector_hrk_From_Jk(Jk, params, hrk);
d_omega[0] = d_omega[1] = d_omega[2] = 0.; d_omega[0] = d_omega[1] = d_omega[2] = 0.;
for (int n = 0; n < 3; n++) { for(int n = 0; n < 3; n++) {
d_omega[n] += hrk[n] - h[n]; d_omega[n] += hrk[n] - h[n];
if(ndJk) d_omega[n] += kappa * dJk[n]/ndJk ; if(ndJk) d_omega[n] += kappa * dJk[n] / ndJk;
} }
} }
void fct_dd_omega_VAR(const double h[3], void fct_dd_omega_VAR(const double h[3], const double Jk[3], void *params,
const double Jk[3],
void * params,
double *ddfdJ2) double *ddfdJ2)
{ {
struct params_Cells_EB *p = (struct params_Cells_EB *) params; struct params_Cells_EB *p = (struct params_Cells_EB *)params;
double Jkp[3]; double Jkp[3];
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) Jkp[n] = p->Xp[n + 3 * p->idcell];
Jkp[n] = p->Xp[n+3*p->idcell];
double kappa = p->kappa[p->idcell]; double kappa = p->kappa[p->idcell];
double wk = p->w[p->idcell]; double wk = p->w[p->idcell];
double Ja = wk*p->Ja; double Ja = wk * p->Ja;
double ha = p->ha ; double ha = p->ha;
double Jb = wk*p->Jb; double Jb = wk * p->Jb;
double hb = p->hb ; double hb = p->hb;
double dJk[3]; double dJk[3];
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) dJk[n] = Jk[n] - Jkp[n];
dJk[n] = Jk[n]-Jkp[n];
double nJk = norm(Jk); double nJk = norm(Jk);
double ndJk = norm(dJk); double ndJk = norm(dJk);
if ( (::FLAG_ANA) && (nJk>(::TOLERANCE_NJ) && ndJk>(::TOLERANCE_NJ))){ if((::FLAG_ANA) && (nJk > (::TOLERANCE_NJ) && ndJk > (::TOLERANCE_NJ))) {
Message::Debug("--- fct_dd_omega_VAR: Analytical Jacobian ---"); Message::Debug("--- fct_dd_omega_VAR: Analytical Jacobian ---");
double kappaOverndJk = kappa/ndJk; double kappaOverndJk = kappa / ndJk;
double nhr=0.; double dhrdJkOvernJk2=0.; double nhrOvernJk=0.; double nhr = 0.;
double dhrdJkOvernJk2 = 0.;
double nhrOvernJk = 0.;
switch(::FLAG_ANHYLAW) { switch(::FLAG_ANHYLAW) {
case 1: // Hyperbolic Tangent Case case 1: // Hyperbolic Tangent Case
nhr = InvJanhy(nJk, Ja, ha) ; nhr = InvJanhy(nJk, Ja, ha);
nhrOvernJk = nhr/nJk; nhrOvernJk = nhr / nJk;
dhrdJkOvernJk2 = dInvJanhy(nJk, Ja, ha) /SQU(nJk); dhrdJkOvernJk2 = dInvJanhy(nJk, Ja, ha) / SQU(nJk);
break;
case 2: // Double Langevin Function Case
nhr = InvJanhy(nJk, Ja, ha, Jb, hb) ;
nhrOvernJk = nhr/nJk;
dhrdJkOvernJk2 = dInvJanhy_hr(nhr, Ja, ha, Jb, hb) /SQU(nJk);
break; break;
default: case 2: // Double Langevin Function Case
Message::Error("Invalid parameter (AnhyLaw = 1 (Tanh) or 2 (DLan) )" nhr = InvJanhy(nJk, Ja, ha, Jb, hb);
"for function 'fct_dd_omega_VAR'."); nhrOvernJk = nhr / nJk;
dhrdJkOvernJk2 = dInvJanhy_hr(nhr, Ja, ha, Jb, hb) / SQU(nJk);
break;
default:
Message::Error("Invalid parameter (AnhyLaw = 1 (Tanh) or 2 (DLan) )"
"for function 'fct_dd_omega_VAR'.");
break; break;
} }
ddfdJ2[0] = dhrdJkOvernJk2 * (Jk[0]*Jk[0]) ddfdJ2[0] =
+ nhrOvernJk * (1. - (1/SQU(nJk))*(Jk[0]*Jk[0])) dhrdJkOvernJk2 * (Jk[0] * Jk[0]) +
+ kappaOverndJk * (1. - (1/SQU(ndJk))*(dJk[0]*dJk[0])) ; //xx nhrOvernJk * (1. - (1 / SQU(nJk)) * (Jk[0] * Jk[0])) +
ddfdJ2[1] = dhrdJkOvernJk2 * (Jk[1]*Jk[0]) kappaOverndJk * (1. - (1 / SQU(ndJk)) * (dJk[0] * dJk[0])); // xx
+ nhrOvernJk * ( - (1/SQU(nJk))*(Jk[1]*Jk[0])) ddfdJ2[1] = dhrdJkOvernJk2 * (Jk[1] * Jk[0]) +
+ kappaOverndJk * ( - (1/SQU(ndJk))*(dJk[1]*dJk[0])) ; //xy nhrOvernJk * (-(1 / SQU(nJk)) * (Jk[1] * Jk[0])) +
switch(::FLAG_SYM) kappaOverndJk * (-(1 / SQU(ndJk)) * (dJk[1] * dJk[0])); // xy
{ switch(::FLAG_SYM) {
case 1: // Symmetric tensor case 1: // Symmetric tensor
ddfdJ2[3] = dhrdJkOvernJk2 * (Jk[1]*Jk[1]) ddfdJ2[3] =
+ nhrOvernJk * (1. - (1/SQU(nJk))*(Jk[1]*Jk[1])) dhrdJkOvernJk2 * (Jk[1] * Jk[1]) +
+ kappaOverndJk * (1. - (1/SQU(ndJk))*(dJk[1]*dJk[1])) ; //yy nhrOvernJk * (1. - (1 / SQU(nJk)) * (Jk[1] * Jk[1])) +
switch(::FLAG_DIM) { kappaOverndJk * (1. - (1 / SQU(ndJk)) * (dJk[1] * dJk[1])); // yy
case 2: // 2D case switch(::FLAG_DIM) {
ddfdJ2[5] = 1.; case 2: // 2D case
ddfdJ2[2] = ddfdJ2[4] = 0.; ddfdJ2[5] = 1.;
break; ddfdJ2[2] = ddfdJ2[4] = 0.;
case 3: // 3D case break;
ddfdJ2[5] = dhrdJkOvernJk2 * (Jk[2]*Jk[2]) case 3: // 3D case
+ nhrOvernJk * (1. - (1/SQU(nJk))*(Jk[2]*Jk[2])) ddfdJ2[5] =
+ kappaOverndJk * (1. - (1/SQU(ndJk))*(dJk[2]*dJk[2])) ; dhrdJkOvernJk2 * (Jk[2] * Jk[2]) +
//zz nhrOvernJk * (1. - (1 / SQU(nJk)) * (Jk[2] * Jk[2])) +
ddfdJ2[2] = dhrdJkOvernJk2 * (Jk[2]*Jk[0]) kappaOverndJk * (1. - (1 / SQU(ndJk)) * (dJk[2] * dJk[2])); // zz
+ nhrOvernJk * ( - (1/SQU(nJk))*(Jk[2]*Jk[0])) ddfdJ2[2] =
+ kappaOverndJk * ( - (1/SQU(ndJk))*(dJk[2]*dJk[0])) ; dhrdJkOvernJk2 * (Jk[2] * Jk[0]) +
//xz nhrOvernJk * (-(1 / SQU(nJk)) * (Jk[2] * Jk[0])) +
ddfdJ2[4] = dhrdJkOvernJk2 * (Jk[2]*Jk[1]) kappaOverndJk * (-(1 / SQU(ndJk)) * (dJk[2] * dJk[0])); // xz
+ nhrOvernJk * ( - (1/SQU(nJk))*(Jk[2]*Jk[1])) ddfdJ2[4] =
+ kappaOverndJk * ( - (1/SQU(ndJk))*(dJk[2]*dJk[1])) ; dhrdJkOvernJk2 * (Jk[2] * Jk[1]) +
//yz nhrOvernJk * (-(1 / SQU(nJk)) * (Jk[2] * Jk[1])) +
break; kappaOverndJk * (-(1 / SQU(ndJk)) * (dJk[2] * dJk[1])); // yz
default: break;
Message::Error("Invalid parameter (dimension = 2 or 3)" default:
"for function 'fct_dd_omega_VAR'. Analytic Jacobian computation.") Message::Error(
; "Invalid parameter (dimension = 2 or 3)"
break; "for function 'fct_dd_omega_VAR'. Analytic Jacobian computation.");
} break;
break; }
case 0: // Non Symmetric Tensor
ddfdJ2[3] = ddfdJ2[1]; //yx
ddfdJ2[4] = dhrdJkOvernJk2 * (Jk[1]*Jk[1])
+ nhrOvernJk * (1. - (1/SQU(nJk))*(Jk[1]*Jk[1]))
+ kappaOverndJk * (1. - (1/SQU(ndJk))*(dJk[1]*dJk[1])) ; //y
y
switch(::FLAG_DIM) {
case 2: // 2D case
ddfdJ2[8] = 1.; // zz
ddfdJ2[2] = ddfdJ2[5] = ddfdJ2[6] =ddfdJ2[7] =0.; //xz //xy //zx //z
y
break;
case 3: // 3D case
ddfdJ2[8] = dhrdJkOvernJk2 * (Jk[2]*Jk[2])
+ nhrOvernJk * (1. - (1/SQU(nJk))*(Jk[2]*Jk[2]))
+ kappaOverndJk * (1. - (1/SQU(ndJk))*(dJk[2]*dJk[2])) ;
//zz
ddfdJ2[2] = dhrdJkOvernJk2 * (Jk[2]*Jk[0])
+ nhrOvernJk * ( - (1/SQU(nJk))*(Jk[2]*Jk[0]))
+ kappaOverndJk * ( - (1/SQU(ndJk))*(dJk[2]*dJk[0])) ;
//xz
ddfdJ2[5] = dhrdJkOvernJk2 * (Jk[2]*Jk[1])
+ nhrOvernJk * ( - (1/SQU(nJk))*(Jk[2]*Jk[1]))
+ kappaOverndJk * ( - (1/SQU(ndJk))*(dJk[2]*dJk[1])) ;
//yz
ddfdJ2[6] = ddfdJ2[2]; //zx
ddfdJ2[7] = ddfdJ2[5]; //zy
break;
default:
Message::Error("Invalid parameter (dimension = 2 or 3)"
"for function 'fct_dd_omega_VAR'. Analytic Jacobian computation.")
;
break;
}
break; break;
case 0: // Non Symmetric Tensor
ddfdJ2[3] = ddfdJ2[1]; // yx
ddfdJ2[4] =
dhrdJkOvernJk2 * (Jk[1] * Jk[1]) +
nhrOvernJk * (1. - (1 / SQU(nJk)) * (Jk[1] * Jk[1])) +
kappaOverndJk * (1. - (1 / SQU(ndJk)) * (dJk[1] * dJk[1])); // yy
switch(::FLAG_DIM) {
case 2: // 2D case
ddfdJ2[8] = 1.; // zz
ddfdJ2[2] = ddfdJ2[5] = ddfdJ2[6] = ddfdJ2[7] = 0.; // xz //xy //zx //zy
break;
case 3: // 3D case
ddfdJ2[8] =
dhrdJkOvernJk2 * (Jk[2] * Jk[2]) +
nhrOvernJk * (1. - (1 / SQU(nJk)) * (Jk[2] * Jk[2])) +
kappaOverndJk * (1. - (1 / SQU(ndJk)) * (dJk[2] * dJk[2])); // zz
ddfdJ2[2] =
dhrdJkOvernJk2 * (Jk[2] * Jk[0]) +
nhrOvernJk * (-(1 / SQU(nJk)) * (Jk[2] * Jk[0])) +
kappaOverndJk * (-(1 / SQU(ndJk)) * (dJk[2] * dJk[0])); // xz
ddfdJ2[5] =
dhrdJkOvernJk2 * (Jk[2] * Jk[1]) +
nhrOvernJk * (-(1 / SQU(nJk)) * (Jk[2] * Jk[1])) +
kappaOverndJk * (-(1 / SQU(ndJk)) * (dJk[2] * dJk[1])); // yz
ddfdJ2[6] = ddfdJ2[2]; // zx
ddfdJ2[7] = ddfdJ2[5]; // zy
break;
default: default:
Message::Error("Invalid parameter (FLAG_SYM = 0 or 1)" Message::Error(
"for function 'fct_dd_omega_VAR'.\n"); "Invalid parameter (dimension = 2 or 3)"
"for function 'fct_dd_omega_VAR'. Analytic Jacobian computation.");
break;
}
break;
default:
Message::Error("Invalid parameter (FLAG_SYM = 0 or 1)"
"for function 'fct_dd_omega_VAR'.\n");
break; break;
} }
} }
else else {
{
Message::Debug("--- fct_dd_omega_VAR: Numerical Jacobian ---"); Message::Debug("--- fct_dd_omega_VAR: Numerical Jacobian ---");
double hcopy[3]={h[0],h[1],h[2]}; // because h is constant double double hcopy[3] = {h[0], h[1], h[2]}; // because h is constant double
Tensor_num(fct_d_omega_VAR, Jk, ::DELTAJ_0, hcopy, params, ddfdJ2); Tensor_num(fct_d_omega_VAR, Jk, ::DELTAJ_0, hcopy, params, ddfdJ2);
} }
} }
//************************************************ //************************************************
// Usefull Functions for the Full Differential Approach // Usefull Functions for the Full Differential Approach
//************************************************ //************************************************
void fct_ehirr_DIFF_3d(const double x[2], void fct_ehirr_DIFF_3d(const double x[2], double ehi[3])
double ehi[3])
{ {
const double theta = x[0]; const double theta = x[0];
const double phi = x[1]; const double phi = x[1];
ehi[0]=sin(phi)*cos(theta); ehi[0] = sin(phi) * cos(theta);
ehi[1]=sin(phi)*sin(theta); ehi[1] = sin(phi) * sin(theta);
ehi[2]=cos(phi) ; ehi[2] = cos(phi);
} }
void fct_hr_DIFF_3d(const double x[2], void fct_hr_DIFF_3d(const double x[2], const double kappa, const double ehi[3],
const double kappa, const double h[3], double xup[3])
const double ehi[3],
const double h[3],
double xup[3])
{ {
for (int n=0 ; n<3 ; n++) for(int n = 0; n < 3; n++) xup[n] = h[n] + kappa * ehi[n];
xup[n]=h[n] + kappa*ehi[n];
} }
void fct_fall_DIFF_3d (const double ang[2], void fct_fall_DIFF_3d(const double ang[2], void *params, double fall[3])
void *params,
double fall[3])
{ {
struct params_Cells_EB *p = (struct params_Cells_EB *)params;
struct params_Cells_EB *p = (struct params_Cells_EB *) params; double kappa = p->kappa[p->idcell];
double kappa = p->kappa[p->idcell]; double h[3] = {p->h[0], p->h[1], p->h[2]};
double h[3] = { p->h[0] , p->h[1] , p->h[2] }; double Jp[3] = {p->Jp[0], p->Jp[1], p->Jp[2]};
double Jp[3] = { p->Jp[0], p->Jp[1], p->Jp[2] };
double xup[3]; double xup[3];
double dJ[3]; double dJ[3];
double ehi[3]; double ehi[3];
fct_ehirr_DIFF_3d(ang,ehi); fct_ehirr_DIFF_3d(ang, ehi);
fct_hr_DIFF_3d(ang, kappa, ehi,h, xup); fct_hr_DIFF_3d(ang, kappa, ehi, h, xup);
Vector_Jk_From_hrk (xup, params, dJ); // dJ contains Jup here Vector_Jk_From_hrk(xup, params, dJ); // dJ contains Jup here
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++)
dJ[n] -= Jp[n]; // dJ = Jup - Jp as it should be here dJ[n] -= Jp[n]; // dJ = Jup - Jp as it should be here
fall[0] = dJ[1]*ehi[2] - dJ[2]*ehi[1]; fall[0] = dJ[1] * ehi[2] - dJ[2] * ehi[1];
fall[1] = dJ[2]*ehi[0] - dJ[0]*ehi[2]; fall[1] = dJ[2] * ehi[0] - dJ[0] * ehi[2];
fall[2] = dJ[0]*ehi[1] - dJ[1]*ehi[0]; fall[2] = dJ[0] * ehi[1] - dJ[1] * ehi[0];
} }
// due to the use of gsl_vector, GSL_SUCCESS, gsl_multiroot_fsolver, ... // due to the use of gsl_vector, GSL_SUCCESS, gsl_multiroot_fsolver, ...
#if defined(HAVE_GSL) #if defined(HAVE_GSL)
int fct_f_DIFF_3d ( const gsl_vector * gsl_ang, int fct_f_DIFF_3d(const gsl_vector *gsl_ang, void *params,
void *params, gsl_vector *f) // not in F.h
gsl_vector * f) // not in F.h
{ {
struct params_Cells_EB *p = (struct params_Cells_EB *)params;
struct params_Cells_EB *p = (struct params_Cells_EB *) params;
double ang[2]; double ang[2];
for (int n=0; n<2; n++) for(int n = 0; n < 2; n++) ang[n] = gsl_vector_get(gsl_ang, n);
ang[n]=gsl_vector_get (gsl_ang, n);
double fall[3]; double fall[3];
fct_fall_DIFF_3d(ang,params,fall); fct_fall_DIFF_3d(ang, params, fall);
// remove compout from fall: // remove compout from fall:
int i=0; int i = 0;
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) {
{ if(p->compout != n) {
if(p->compout!=n) gsl_vector_set(f, i, fall[n]);
{
gsl_vector_set (f, i, fall[n]);
i++; i++;
} }
} }
/* Actually do this: /* Actually do this:
if (p->compout==0) if (p->compout==0)
{ {
gsl_vector_set (f, 0, fall[1]); gsl_vector_set (f, 0, fall[1]);
gsl_vector_set (f, 1, fall[2]); gsl_vector_set (f, 1, fall[2]);
} }
else if (p->compout==1) else if (p->compout==1)
skipping to change at line 1680 skipping to change at line 1682
} }
else //if (p-> compout==2) else //if (p-> compout==2)
{ {
gsl_vector_set (f, 0, fall[0]); gsl_vector_set (f, 0, fall[0]);
gsl_vector_set (f, 1, fall[1]); gsl_vector_set (f, 1, fall[1]);
} }
*/ */
return GSL_SUCCESS; return GSL_SUCCESS;
} }
void print_state_3d (int iterb, void print_state_3d(int iterb, const char *s_name, int status,
const char *s_name, gsl_multiroot_fsolver *s) // not in F.h
int status,
gsl_multiroot_fsolver * s) // not in F.h
{ {
if(::FLAG_WARNING>=FLAG_WARNING_INFO_APPROACH if(::FLAG_WARNING >= FLAG_WARNING_INFO_APPROACH &&
&& iterb>=FLAG_WARNING_DISPABOVEITER) iterb >= FLAG_WARNING_DISPABOVEITER) {
{ if(iterb == FLAG_WARNING_DISPABOVEITER) printf("using %s method", s_name);
if (iterb == FLAG_WARNING_DISPABOVEITER)
printf ("using %s method", printf("\niter = %3u x = % .3f % .3f "
s_name); "f(x) = % .3e % .3e",
iterb, gsl_vector_get(s->x, 0), gsl_vector_get(s->x, 1),
printf ("\niter = %3u x = % .3f % .3f " gsl_vector_get(s->f, 0), gsl_vector_get(s->f, 1));
"f(x) = % .3e % .3e",
iterb,
gsl_vector_get (s->x, 0),
gsl_vector_get (s->x, 1),
gsl_vector_get (s->f, 0),
gsl_vector_get (s->f, 1));
if (status == GSL_SUCCESS) if(status == GSL_SUCCESS) printf(" (Converged)\n");
printf (" (Converged)\n");
} }
} }
#endif #endif
void Vector_hirr_DIFF_2d(double x, void Vector_hirr_DIFF_2d(double x, double kappa, double ex[3])
double kappa, {
double ex[3]) ex[0] = kappa * cos(x);
{ ex[1] = kappa * sin(x);
ex[0]=kappa*cos(x); ex[2] = 0;
ex[1]=kappa*sin(x);
ex[2]=0;
} }
void fct_hr_DIFF_2d(double x, void fct_hr_DIFF_2d(double x, double kappa, double h[3], double xup[3])
double kappa,
double h[3],
double xup[3])
{ {
double hi[3]; double hi[3];
Vector_hirr_DIFF_2d(x, kappa, hi); Vector_hirr_DIFF_2d(x, kappa, hi);
for (int n=0 ; n<3 ; n++) for(int n = 0; n < 3; n++) xup[n] = h[n] - hi[n];
xup[n]=h[n]-hi[n];
} }
double fct_f_DIFF_2d (double y, double fct_f_DIFF_2d(double y, void *params)
void *params)
{ {
struct params_Cells_EB *p = (struct params_Cells_EB *) params; struct params_Cells_EB *p = (struct params_Cells_EB *)params;
double kappa = p->kappa[p->idcell]; double kappa = p->kappa[p->idcell];
double h[3] ,Jp[3] ; double h[3], Jp[3];
for (int n=0; n<3; n++){ for(int n = 0; n < 3; n++) {
Jp[n] = p->Jp[n]; Jp[n] = p->Jp[n];
h[n] = p->h[n] ; h[n] = p->h[n];
} }
double xup[3], dJ[3]; double xup[3], dJ[3];
fct_hr_DIFF_2d(y, kappa, h, xup); fct_hr_DIFF_2d(y, kappa, h, xup);
Vector_Jk_From_hrk (xup, params, dJ); // dJ contains Jup here Vector_Jk_From_hrk(xup, params, dJ); // dJ contains Jup here
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++)
dJ[n] -= Jp[n]; // dJ = Jup - Jp as it should be here dJ[n] -= Jp[n]; // dJ = Jup - Jp as it should be here
return dJ[0]*sin(y)-dJ[1]*cos(y); return dJ[0] * sin(y) - dJ[1] * cos(y);
} }
#if defined(HAVE_GSL) // due to the use of GSL_SUCCESS #if defined(HAVE_GSL) // due to the use of GSL_SUCCESS
void print_state_2d ( int iterb, void print_state_2d(int iterb, const char *s_name, int status, double al,
const char *s_name, double br, double alpha,
int status, double err) // not in F.h
double al, {
double br, if(::FLAG_WARNING >= FLAG_WARNING_INFO_APPROACH &&
double alpha, iterb >= FLAG_WARNING_DISPABOVEITER) {
double err) // not in F.h if(iterb == FLAG_WARNING_DISPABOVEITER) {
{ printf("using %s method\n", s_name);
if(::FLAG_WARNING>=FLAG_WARNING_INFO_APPROACH printf("%5s [%9s, %9s] %9s %9s\n", "iter", "lower", "upper", "alpha",
&& iterb>=FLAG_WARNING_DISPABOVEITER ) "err(est)");
{ }
if( iterb==FLAG_WARNING_DISPABOVEITER)
{ if(status == GSL_SUCCESS) printf("Converged:\n");
printf ("using %s method\n",
s_name); printf("%5d [%.7f, %.7f] "
printf ("%5s [%9s, %9s] %9s %9s\n", "%.7f %.7f\n",
"iter", "lower", "upper", "alpha", "err(est)"); iterb, al, br, alpha, err);
}
if (status == GSL_SUCCESS)
printf ("Converged:\n");
printf ("%5d [%.7f, %.7f] "
"%.7f %.7f\n",
iterb, al, br,
alpha, err);
} }
} }
#endif #endif
//************************************************ //************************************************
// Energy-Based Model - Vector Update // Energy-Based Model - Vector Update
//************************************************ //************************************************
void Vector_Update_Jk_VAR(const double h[3], void Vector_Update_Jk_VAR(const double h[3], double Jk[3], double Jk0[3],
double Jk[3], void *params)
double Jk0[3],
void * params)
{ {
double Jkp[3]; double Jkp[3];
double hcopy[3]={h[0],h[1],h[2]}; // because h is constant double double hcopy[3] = {h[0], h[1], h[2]}; // because h is constant double
struct params_Cells_EB *p = (struct params_Cells_EB *) params; struct params_Cells_EB *p = (struct params_Cells_EB *)params;
for (int n=0; n<3; n++){ for(int n = 0; n < 3; n++) {
Jkp[n] = p->Xp[n+3*p->idcell]; Jkp[n] = p->Xp[n + 3 * p->idcell];
p->h[n] = h[n]; p->h[n] = h[n];
} }
double kappa = p->kappa[p->idcell]; double kappa = p->kappa[p->idcell];
double wk = p->w[p->idcell]; double wk = p->w[p->idcell];
double Ja = wk*p->Ja; double Ja = wk * p->Ja;
double Jb = wk*p->Jb; double Jb = wk * p->Jb;
//No minimization needed when |h-hrp|<kappa! ==> |nhirrp|<kappa ==> Jk = Jkp // No minimization needed when |h-hrp|<kappa! ==> |nhirrp|<kappa ==> Jk = Jkp
double hrp[3]; double hrp[3];
Vector_hrk_From_Jk(Jkp,params, hrp); Vector_hrk_From_Jk(Jkp, params, hrp);
double hirrp[3]; double hirrp[3];
for (int n = 0; n < 3; n++) for(int n = 0; n < 3; n++) hirrp[n] = h[n] - hrp[n];
hirrp[n]=h[n] - hrp[n];
double nhirrp=norm(hirrp); double nhirrp = norm(hirrp);
if (nhirrp<=kappa) if(nhirrp <= kappa) {
{ for(int n = 0; n < 3; n++) Jk[n] = Jkp[n];
for (int n = 0; n < 3; n++)
Jk[n]=Jkp[n];
return; return;
} }
// If one wants to start from Jk = Jk from VPM Approach------------------ // If one wants to start from Jk = Jk from VPM Approach------------------
double hr[3], Jk_VPM[3]; double hr[3], Jk_VPM[3];
Vector_Update_hrk_VPM_ (h, hr, hrp, kappa); Vector_Update_hrk_VPM_(h, hr, hrp, kappa);
Vector_Jk_From_hrk (hr, params, Jk_VPM); // dJ contains Jup here Vector_Jk_From_hrk(hr, params, Jk_VPM); // dJ contains Jup here
double nJ0[3]; double nJ0[3];
for (int n=0; n<3; n++) nJ0[n] = Jk_VPM[n]-Jkp[n]; for(int n = 0; n < 3; n++) nJ0[n] = Jk_VPM[n] - Jkp[n];
// diff hr induced an imperceptible diff Jk in that case => kill early // diff hr induced an imperceptible diff Jk in that case => kill early
if (norm(nJ0)<1e-16*norm(Jk_VPM) ) if(norm(nJ0) < 1e-16 * norm(Jk_VPM)) {
{ for(int n = 0; n < 3; n++) Jk[n] = Jkp[n];
for (int n = 0; n < 3; n++)
Jk[n]=Jkp[n];
return; return;
} }
double J0[3]; double J0[3];
for (int n=0; n<3; n++) J0[n] = Jk_VPM[n]; for(int n = 0; n < 3; n++) J0[n] = Jk_VPM[n];
switch(::FLAG_MINMETHOD) { switch(::FLAG_MINMETHOD) {
case 1: case 1: {
{ //-------------------------------------------------------------------
//------------------------------------------------------------------- // Updating Jk with a steepest descent algorithm
// Updating Jk with a steepest descent algorithm //-------------------------------------------------------------------
//-------------------------------------------------------------------
double min_Jk[3];
double min_Jk[3] ; for(int n = 0; n < 3; n++) min_Jk[n] = J0[n];
for (int n=0 ; n<3 ; n++) min_Jk[n] = J0[n]; double d_omega[3];
double d_omega[3] ; double sdfactor = 0.1; // suitable value of tol for most applications
double sdfactor = 0.1; //suitable value of tol for most applications double TOL = ::TOLERANCE_OM;
double TOL = ::TOLERANCE_OM; double Js = (Ja + Jb);
double Js=(Ja+Jb); for(int n = 0; n < 3; n++) Jk[n] = J0[n];
for (int n=0; n<3; n++) Jk[n] = J0[n];
limiter(Js, Jk); // avoiding possible NaN with atanh
fct_d_omega_VAR(Jk, d_omega, hcopy,
params); // updating the derivative of omega
double omega = fct_omega_VAR(h, Jk, params); // updating omega
double min_omega = 1e+22;
int iter = 0;
const int MAX_ITER = ::MAX_ITER_OM;
while(iter < MAX_ITER &&
(fabs(d_omega[0]) / (1 + fabs(omega)) * sdfactor > TOL ||
fabs(d_omega[1]) / (1 + fabs(omega)) * sdfactor > TOL ||
fabs(d_omega[2]) / (1 + fabs(omega)) * sdfactor > TOL)) {
for(int n = 0; n < 3; n++)
min_Jk[n] = Jk[n] - sdfactor * d_omega[n]; // gradient descent algorithm
limiter(Js, min_Jk);
min_omega = fct_omega_VAR(h, min_Jk, params); // updating omega
if(min_omega < omega - TOL / 10 && norm(min_Jk) < Js) {
fct_d_omega_VAR(min_Jk, d_omega, hcopy,
params); // update the derivative d_omega
omega = min_omega;
// if(Jk[0]==Jkp[0] && Jk[1]==Jkp[1] && Jk[2]==Jkp[2])
if(fabs(Jk[0] - Jkp[0]) <= TOL && fabs(Jk[1] - Jkp[1]) <= TOL &&
fabs(Jk[2] - Jkp[2]) <= TOL) //(diff zero)
sdfactor = 0.1; // re-initialize rfactor which may have become very
// small due to an angulous starting point
limiter(Js, Jk ); // avoiding possible NaN with atanh for(int n = 0; n < 3; n++) Jk[n] = min_Jk[n];
}
else
sdfactor = sdfactor / 2;
fct_d_omega_VAR(Jk, d_omega, hcopy, params) ; // updating the derivative o iter++;
f omega }
double omega = fct_omega_VAR(h,Jk, params); // updating omega if(::FLAG_WARNING >= FLAG_WARNING_INFO_APPROACH && iter == MAX_ITER)
Message::Warning(
"\t\tMinimization status : the minimization has not converged yet,"
"after %d iteration(s)",
MAX_ITER);
for(int n = 0; n < 3; n++) Jk[n] = min_Jk[n];
} break;
case 11: // steepest descent
case 22: // Fletcher-Reeves
case 33: // Polak-Ribiere
case 333: // Polak-Ribiere+
case 1999: // 85 Dai Yuan 1999
case 2005: // 161 Hager Zhang 2005
case 77: // newton
{
//-------------------------------------------------------------------
// NEW Updating Jk with a steepest descent algorithm
//-------------------------------------------------------------------
int FLAG_TAYLORCRIT = 1;
double GTOL = 1e-7; //::TOLERANCE_OM;
double TOL_DX = ::TOLERANCE_OM;
double TOL_TAYLOR = 1e-8;
double TOL_LOOSECRIT = 1e-14;
/*
double GTOL = 1e-5*norm(J0);//::TOLERANCE_OM;
double TOL_DX = ::TOLERANCE_OM*norm(J0);
double TOL_TAYLOR = 1e-12*norm(J0);
double TOL_LOOSECRIT = 1e-14*norm(J0);
*/
// for cg
double deltak, beta = 0, ykpk, yk2;
double gfkp1[3], yk[3];
// for sd & cg
double gnorm, pknorm, pk2, min_fval, gfkpk, xkpk;
double xknorm, a1, a2, alpha_max, sqrdelta, sum_ddfdJ2_pkpkT = 0;
double xk[3], min_xk[3], gfk[3], pk[3], pkpkT[6];
double alpha = 0.1; // suitable value of tol for most applications
double Js = (Ja + Jb);
for(int n = 0; n < 3; n++) xk[n] = J0[n];
double old_fval = fct_omega_VAR(h, xk, params); // updating omega
fct_d_omega_VAR(xk, gfk, hcopy,
params); // updating the derivative of omega = gfk
for(int n = 0; n < 3; n++) pk[n] = -gfk[n];
gnorm = norm(gfk);
pknorm = norm(pk);
double min_omega = 1e+22 ; int ncomp = ::NCOMP;
double *ddfdJ2;
int iter = 0 ; ddfdJ2 = new double[ncomp];
const int MAX_ITER = ::MAX_ITER_OM;
while( iter < MAX_ITER &&
(fabs(d_omega[0])/(1+fabs(omega))*sdfactor > TOL ||
fabs(d_omega[1])/(1+fabs(omega))*sdfactor > TOL ||
fabs(d_omega[2])/(1+fabs(omega))*sdfactor > TOL ))
{
for (int n = 0; n < 3; n++)
min_Jk[n] = Jk[n] - sdfactor * d_omega[n] ; // gradient descent algori
thm
limiter(Js, min_Jk); int k = 1;
min_omega = fct_omega_VAR(h,min_Jk, params); //updating omega const int MAX_ITER = ::MAX_ITER_OM;
if( min_omega < omega-TOL/10 && norm(min_Jk) < Js ){ // while( k <= MAX_ITER && gnorm > GTOL )
fct_d_omega_VAR(min_Jk, d_omega,hcopy, params) ; //update the deriva // while( k <= MAX_ITER && alpha*pknorm>TOL_DX )
tive d_omega while(k <= MAX_ITER && alpha * pknorm > TOL_DX && gnorm > GTOL) {
omega = min_omega; xkpk = xk[0] * pk[0] + xk[1] * pk[1] + xk[2] * pk[2];
//if(Jk[0]==Jkp[0] && Jk[1]==Jkp[1] && Jk[2]==Jkp[2]) xknorm = norm(xk);
if( fabs(Jk[0]-Jkp[0])<= TOL && pk2 = SQU(pknorm);
fabs(Jk[1]-Jkp[1])<= TOL && sqrdelta = sqrt(SQU(xkpk) - pk2 * (SQU(xknorm) - SQU(Js)));
fabs(Jk[2]-Jkp[2])<= TOL ) //(diff zero) a1 = (pk2 != 0) ? (-xkpk - sqrdelta) / pk2 : 0.;
sdfactor=0.1; // re-initialize rfactor which may have become very sm a2 = (pk2 != 0) ? (-xkpk + sqrdelta) / pk2 : 0.;
all due to an angulous starting point alpha_max = (a1 > a2) ? a1 : a2;
gfkpk = gfk[0] * pk[0] + gfk[1] * pk[1] + gfk[2] * pk[2];
int k_ls = 1;
// while( gnorm > GTOL )
// while(alpha*pknorm>TOL_DX)
while(alpha * pknorm > TOL_DX && gnorm > GTOL) {
if(gfkpk > 0) break;
for (int n=0; n<3; n++) Jk[n] = min_Jk[n]; alpha = (alpha < alpha_max) ? alpha : alpha_max;
}
else sdfactor = sdfactor/2 ;
iter++ ; if(FLAG_TAYLORCRIT && alpha * pknorm <= TOL_TAYLOR) // taylorcrit
}
if (::FLAG_WARNING>=FLAG_WARNING_INFO_APPROACH && iter==MAX_ITER)
Message::Warning("\t\tMinimization status : the minimization has not con
verged yet,"
"after %d iteration(s)", MAX_ITER);
for (int n=0 ; n<3 ; n++)
Jk[n] = min_Jk[n];
}
break;
case 11: //steepest descent
case 22: //Fletcher-Reeves
case 33: //Polak-Ribiere
case 333: //Polak-Ribiere+
case 1999: //85 Dai Yuan 1999
case 2005: //161 Hager Zhang 2005
case 77: //newton
{
//-------------------------------------------------------------------
// NEW Updating Jk with a steepest descent algorithm
//-------------------------------------------------------------------
int FLAG_TAYLORCRIT = 1;
double GTOL = 1e-7;//::TOLERANCE_OM;
double TOL_DX = ::TOLERANCE_OM;
double TOL_TAYLOR = 1e-8;
double TOL_LOOSECRIT = 1e-14;
/*
double GTOL = 1e-5*norm(J0);//::TOLERANCE_OM;
double TOL_DX = ::TOLERANCE_OM*norm(J0);
double TOL_TAYLOR = 1e-12*norm(J0);
double TOL_LOOSECRIT = 1e-14*norm(J0);
*/
//for cg
double deltak, beta = 0, ykpk, yk2;
double gfkp1[3], yk[3];
//for sd & cg
double gnorm, pknorm, pk2, min_fval, gfkpk, xkpk;
double xknorm, a1,a2,alpha_max,sqrdelta, sum_ddfdJ2_pkpkT = 0;
double xk[3], min_xk[3] ,gfk[3], pk[3], pkpkT[6] ;
double alpha = 0.1; //suitable value of tol for most applications
double Js=(Ja+Jb);
for (int n=0; n<3; n++)
xk[n] = J0[n];
double old_fval = fct_omega_VAR(h,xk, params); // updating omega
fct_d_omega_VAR(xk, gfk,hcopy, params) ; // updating the derivative of om
ega = gfk
for (int n = 0; n < 3; n++)
pk[n]=-gfk[n];
gnorm=norm(gfk);
pknorm=norm(pk);
int ncomp=::NCOMP;
double *ddfdJ2; ddfdJ2 = new double[ncomp];
int k = 1 ;
const int MAX_ITER = ::MAX_ITER_OM;
//while( k <= MAX_ITER && gnorm > GTOL )
//while( k <= MAX_ITER && alpha*pknorm>TOL_DX )
while( k <= MAX_ITER && alpha*pknorm>TOL_DX && gnorm > GTOL )
{
xkpk=xk[0]*pk[0]+xk[1]*pk[1]+xk[2]*pk[2];
xknorm=norm(xk);
pk2 = SQU(pknorm);
sqrdelta=sqrt(SQU(xkpk)-pk2*(SQU(xknorm)-SQU(Js)));
a1=(pk2!=0)? (- xkpk- sqrdelta )/pk2: 0.;
a2=(pk2!=0)? (- xkpk+ sqrdelta )/pk2: 0.;
alpha_max=(a1>a2)?a1:a2;
gfkpk=gfk[0]*pk[0]+gfk[1]*pk[1]+gfk[2]*pk[2];
int k_ls=1;
//while( gnorm > GTOL )
//while(alpha*pknorm>TOL_DX)
while(alpha*pknorm>TOL_DX && gnorm > GTOL)
{ {
if (gfkpk>0) fct_dd_omega_VAR(h, xk, params, ddfdJ2);
// compute pkpkT
pkpkT[0] = pk[0] * pk[0]; // xx
pkpkT[1] = pk[0] * pk[1]; // xy
pkpkT[2] = pk[0] * pk[2]; // xz
pkpkT[3] = pk[1] * pk[1]; // yy
pkpkT[4] = pk[1] * pk[2]; // yz
pkpkT[5] = pk[2] * pk[2]; // zz
// compute new alpha
switch(::FLAG_SYM) {
case 1: // ddfdJ2 Symmetric tensor
sum_ddfdJ2_pkpkT = ddfdJ2[0] * pkpkT[0] + ddfdJ2[3] * pkpkT[3] +
ddfdJ2[5] * pkpkT[5] + 2 * ddfdJ2[1] * pkpkT[1] +
2 * ddfdJ2[2] * pkpkT[2] +
2 * ddfdJ2[4] * pkpkT[4];
break;
case 0: // ddfdJ2 Non Symmetric tensor
sum_ddfdJ2_pkpkT = ddfdJ2[0] * pkpkT[0] + ddfdJ2[1] * pkpkT[1] +
ddfdJ2[2] * pkpkT[2] + ddfdJ2[3] * pkpkT[1] +
ddfdJ2[4] * pkpkT[3] + ddfdJ2[5] * pkpkT[4] +
ddfdJ2[6] * pkpkT[2] + ddfdJ2[7] * pkpkT[4] +
ddfdJ2[8] * pkpkT[5];
break;
default:
Message::Error("Invalid parameter (sym = 0 or 1)"
"for function 'Vector_Update_Jk_VAR'.");
break; break;
}
alpha = ((sum_ddfdJ2_pkpkT) != 0) ? -gfkpk / sum_ddfdJ2_pkpkT : 0.;
alpha=(alpha<alpha_max)? alpha: alpha_max; if(alpha > alpha_max) {
Message::Warning("alpha from taylor %g >= alpha_max %g", alpha,
alpha_max);
alpha = alpha_max / (k + 1);
}
for(int n = 0; n < 3; n++) min_xk[n] = xk[n] + alpha * pk[n];
min_fval = fct_omega_VAR(h, min_xk, params); // updating omega
if (FLAG_TAYLORCRIT && alpha*pknorm<=TOL_TAYLOR) //taylorcrit for(int n = 0; n < 3; n++) xk[n] = min_xk[n];
{ old_fval = min_fval;
fct_dd_omega_VAR(h,xk,params,ddfdJ2);
// compute pkpkT
pkpkT[0]=pk[0]*pk[0]; //xx
pkpkT[1]=pk[0]*pk[1]; //xy
pkpkT[2]=pk[0]*pk[2]; //xz
pkpkT[3]=pk[1]*pk[1]; //yy
pkpkT[4]=pk[1]*pk[2]; //yz
pkpkT[5]=pk[2]*pk[2]; //zz
// compute new alpha
switch(::FLAG_SYM)
{
case 1: // ddfdJ2 Symmetric tensor
sum_ddfdJ2_pkpkT= ddfdJ2[0]*pkpkT[0]+
ddfdJ2[3]*pkpkT[3]+
ddfdJ2[5]*pkpkT[5]+
2*ddfdJ2[1]*pkpkT[1]+
2*ddfdJ2[2]*pkpkT[2]+
2*ddfdJ2[4]*pkpkT[4];
break;
case 0: // ddfdJ2 Non Symmetric tensor
sum_ddfdJ2_pkpkT= ddfdJ2[0]*pkpkT[0]+
ddfdJ2[1]*pkpkT[1]+
ddfdJ2[2]*pkpkT[2]+
ddfdJ2[3]*pkpkT[1]+
ddfdJ2[4]*pkpkT[3]+
ddfdJ2[5]*pkpkT[4]+
ddfdJ2[6]*pkpkT[2]+
ddfdJ2[7]*pkpkT[4]+
ddfdJ2[8]*pkpkT[5];
break;
default:
Message::Error("Invalid parameter (sym = 0 or 1)"
"for function 'Vector_Update_Jk_VAR'.");
break;
}
alpha=((sum_ddfdJ2_pkpkT)!=0)? -gfkpk/sum_ddfdJ2_pkpkT:0.;
if (alpha> alpha_max)
{
Message::Warning("alpha from taylor %g >= alpha_max %g",alpha,alph
a_max);
alpha=alpha_max/(k+1);
}
for (int n = 0; n < 3; n++)
min_xk[n] = xk[n] + alpha * pk[n] ;
min_fval = fct_omega_VAR(h,min_xk, params);//updating omega
for (int n=0; n<3; n++)
xk[n] = min_xk[n];
old_fval=min_fval;
break; break;
} // end taylorcrit } // end taylorcrit
if (!FLAG_TAYLORCRIT && alpha*pknorm<TOL_LOOSECRIT) if(!FLAG_TAYLORCRIT && alpha * pknorm < TOL_LOOSECRIT) break;
break;
for (int n = 0; n < 3; n++) for(int n = 0; n < 3; n++) min_xk[n] = xk[n] + alpha * pk[n];
min_xk[n] = xk[n] + alpha * pk[n] ; min_fval = fct_omega_VAR(h, min_xk, params); // updating omega
min_fval = fct_omega_VAR(h,min_xk, params);//updating omega
if( min_fval < old_fval && norm(min_xk) < Js )
{
alpha=((k+1)/k)*alpha; //sure that alpha > alphap with this
// Is this useful ? .............
if(xk[0]==J0[0] && xk[1]==J0[1] && xk[2]==J0[2])
//if( fabs(xk[0]-J0[0])<TOL &&
// fabs(xk[1]-J0[1])<TOL &&
// fabs(xk[2]-J0[2])<TOL ) //(diff zero)
alpha=0.1; // re-initialize alpha which may have become
// very small due to an angulous starting point
//...............................
for (int n=0; n<3; n++) if(min_fval < old_fval && norm(min_xk) < Js) {
xk[n] = min_xk[n]; alpha = ((k + 1) / k) * alpha; // sure that alpha > alphap with this
old_fval=min_fval; // Is this useful ? .............
break; if(xk[0] == J0[0] && xk[1] == J0[1] && xk[2] == J0[2])
} // if( fabs(xk[0]-J0[0])<TOL &&
else // fabs(xk[1]-J0[1])<TOL &&
{ // fabs(xk[2]-J0[2])<TOL ) //(diff zero)
alpha = alpha/2 ; alpha = 0.1; // re-initialize alpha which may have become
} // very small due to an angulous starting point
k_ls+=1; //...............................
} //end first while
if ( (gfkpk<0) && for(int n = 0; n < 3; n++) xk[n] = min_xk[n];
( (alpha*pknorm<TOL_LOOSECRIT) || (gnorm <= GTOL ) ) old_fval = min_fval;
)
break; break;
}
else {
alpha = alpha / 2;
}
k_ls += 1;
} // end first while
if((gfkpk < 0) && ((alpha * pknorm < TOL_LOOSECRIT) || (gnorm <= GTOL)))
break;
switch(::FLAG_MINMETHOD) {
case 11: // steepest descent
{
fct_d_omega_VAR(xk, gfk, hcopy, params); // update the derivative
// d_omega
for(int n = 0; n < 3; n++) pk[n] = -gfk[n];
} break;
case 22: // conjugate gradient
case 33:
case 333:
case 1999:
case 2005: {
deltak = gfk[0] * gfk[0] + gfk[1] * gfk[1] + gfk[2] * gfk[2];
fct_d_omega_VAR(xk, gfkp1, hcopy,
params); // update the derivative d_omega
for(int n = 0; n < 3; n++) yk[n] = gfkp1[n] - gfk[n];
switch(::FLAG_MINMETHOD) { switch(::FLAG_MINMETHOD) {
case 11: //steepest descent case 22: // Fletcher-Reeves
{ beta =
fct_d_omega_VAR(xk, gfk, hcopy, params) ; //update the derivative d (gfkp1[0] * gfkp1[0] + gfkp1[1] * gfkp1[1] + gfkp1[2] * gfkp1[2]) /
_omega deltak;
for (int n = 0; n < 3; n++) break;
pk[n]=-gfk[n]; case 33: // Polak-Ribiere
} beta =
(yk[0] * gfkp1[0] + yk[1] * gfkp1[1] + yk[2] * gfkp1[2]) / deltak;
break;
case 333: // Polak-Ribiere+ #original
beta =
(yk[0] * gfkp1[0] + yk[1] * gfkp1[1] + yk[2] * gfkp1[2]) / deltak;
beta = (beta > 0) ? beta : 0;
break;
case 1999: // 85 Dai Yuan 1999
beta =
(gfkp1[0] * gfkp1[0] + gfkp1[1] * gfkp1[1] + gfkp1[2] * gfkp1[2]) /
(yk[0] * pk[0] + yk[1] * pk[1] + yk[2] * pk[2]);
break;
case 2005: // 161 Hager Zhang 2005
yk2 = (yk[0] * yk[0] + yk[1] * yk[1] + yk[2] * yk[2]);
ykpk = (yk[0] * pk[0] + yk[1] * pk[1] + yk[2] * pk[2]);
beta = 0;
for(int n = 0; n < 3; n++)
beta += (yk[n] - 2 * pk[n] * (yk2 / ykpk)) * (gfkp1[n] / ykpk);
break; break;
case 22: //conjugate gradient default: break;
case 33: }
case 333:
case 1999:
case 2005:
{
deltak = gfk[0]*gfk[0]+gfk[1]*gfk[1]+gfk[2]*gfk[2];
fct_d_omega_VAR(xk, gfkp1, hcopy, params) ; //update the derivative
d_omega
for (int n=0; n<3; n++)
yk[n]=gfkp1[n]-gfk[n];
switch(::FLAG_MINMETHOD) {
case 22: //Fletcher-Reeves
beta= (gfkp1[0]*gfkp1[0]+gfkp1[1]*gfkp1[1]+gfkp1[2]*gfkp1[2])/de
ltak;
break;
case 33: //Polak-Ribiere
beta= (yk[0]*gfkp1[0]+yk[1]*gfkp1[1]+yk[2]*gfkp1[2])/deltak;
break;
case 333: //Polak-Ribiere+ #original
beta= (yk[0]*gfkp1[0]+yk[1]*gfkp1[1]+yk[2]*gfkp1[2])/deltak;
beta = (beta>0)? beta : 0;
break;
case 1999: //85 Dai Yuan 1999
beta= (gfkp1[0]*gfkp1[0]+gfkp1[1]*gfkp1[1]+gfkp1[2]*gfkp1[2])
/(yk[0]*pk[0]+yk[1]*pk[1]+yk[2]*pk[2]);
break;
case 2005: //161 Hager Zhang 2005
yk2=(yk[0]*yk[0]+yk[1]*yk[1]+yk[2]*yk[2]);
ykpk=(yk[0]*pk[0]+yk[1]*pk[1]+yk[2]*pk[2]);
beta=0;
for (int n = 0; n < 3; n++)
beta+= (yk[n]-2*pk[n]*(yk2/ykpk))*(gfkp1[n]/ykpk);
break;
default:
break;
}
for (int n = 0; n < 3; n++)
{
pk[n] = -gfkp1[n]+ beta*pk[n];
gfk[n]= gfkp1[n];
}
} for(int n = 0; n < 3; n++) {
break; pk[n] = -gfkp1[n] + beta * pk[n];
case 77: //newton gfk[n] = gfkp1[n];
{ }
fct_d_omega_VAR(xk, gfk, hcopy, params) ; //update the derivative d_
omega
fct_dd_omega_VAR(h,xk,params,ddfdJ2);
int ncomp = ::NCOMP;
double *iddfdJ2; iddfdJ2 = new double[ncomp];
switch(::FLAG_SYM)
{
case 1: // Symmetric tensor
Inv_TensorSym3x3(ddfdJ2, iddfdJ2); // T, invT
pk[0]= -(iddfdJ2[0]*gfk[0]+iddfdJ2[1]*gfk[1]+iddfdJ2[2]*gfk[2]);
pk[1]= -(iddfdJ2[1]*gfk[0]+iddfdJ2[3]*gfk[1]+iddfdJ2[4]*gfk[2]);
pk[2]= -(iddfdJ2[2]*gfk[0]+iddfdJ2[4]*gfk[1]+iddfdJ2[6]*gfk[2]);
break;
case 0: // Non Symmetric Tensor
Inv_Tensor3x3(ddfdJ2, iddfdJ2); // T, invT
pk[0]= -(iddfdJ2[0]*gfk[0]+iddfdJ2[1]*gfk[1]+iddfdJ2[2]*gfk[2]);
pk[1]= -(iddfdJ2[3]*gfk[0]+iddfdJ2[4]*gfk[1]+iddfdJ2[5]*gfk[2]);
pk[2]= -(iddfdJ2[6]*gfk[0]+iddfdJ2[7]*gfk[1]+iddfdJ2[8]*gfk[2]);
break;
default:
Message::Error("Invalid parameter (FLAG_SYM = 0 or 1) for newton
"
"in function 'Vector_Update_Jk_VAR'.\n");
break;
}
//alpha=1;
delete [] iddfdJ2; } break;
} case 77: // newton
{
fct_d_omega_VAR(xk, gfk, hcopy, params); // update the derivative
// d_omega
fct_dd_omega_VAR(h, xk, params, ddfdJ2);
int ncomp = ::NCOMP;
double *iddfdJ2;
iddfdJ2 = new double[ncomp];
switch(::FLAG_SYM) {
case 1: // Symmetric tensor
Inv_TensorSym3x3(ddfdJ2, iddfdJ2); // T, invT
pk[0] =
-(iddfdJ2[0] * gfk[0] + iddfdJ2[1] * gfk[1] + iddfdJ2[2] * gfk[2]);
pk[1] =
-(iddfdJ2[1] * gfk[0] + iddfdJ2[3] * gfk[1] + iddfdJ2[4] * gfk[2]);
pk[2] =
-(iddfdJ2[2] * gfk[0] + iddfdJ2[4] * gfk[1] + iddfdJ2[6] * gfk[2]);
break;
case 0: // Non Symmetric Tensor
Inv_Tensor3x3(ddfdJ2, iddfdJ2); // T, invT
pk[0] =
-(iddfdJ2[0] * gfk[0] + iddfdJ2[1] * gfk[1] + iddfdJ2[2] * gfk[2]);
pk[1] =
-(iddfdJ2[3] * gfk[0] + iddfdJ2[4] * gfk[1] + iddfdJ2[5] * gfk[2]);
pk[2] =
-(iddfdJ2[6] * gfk[0] + iddfdJ2[7] * gfk[1] + iddfdJ2[8] * gfk[2]);
break; break;
default: default:
Message::Error("Invalid parameter (FLAG_SYM = 0 or 1) for newton"
"in function 'Vector_Update_Jk_VAR'.\n");
break; break;
} }
gnorm=norm(gfk); // alpha=1;
pknorm=norm(pk);
k++; delete[] iddfdJ2;
} // end second while } break;
delete [] ddfdJ2; default: break;
if (::FLAG_WARNING>=FLAG_WARNING_INFO_APPROACH && k>=MAX_ITER) }
Message::Warning("\t\tMinimization status : the minimization has not con gnorm = norm(gfk);
verged yet," pknorm = norm(pk);
"after %d iteration(s)", MAX_ITER); k++;
for (int n=0 ; n<3 ; n++) } // end second while
Jk[n] = xk[n]; delete[] ddfdJ2;
} if(::FLAG_WARNING >= FLAG_WARNING_INFO_APPROACH && k >= MAX_ITER)
break; Message::Warning(
case 2: "\t\tMinimization status : the minimization has not converged yet,"
case 3: "after %d iteration(s)",
case 4: MAX_ITER);
case 5: for(int n = 0; n < 3; n++) Jk[n] = xk[n];
case 6: } break;
{ case 2:
//------------------------------------------------------------------- case 3:
// Updating Jk with gnu gsl case 4:
//------------------------------------------------------------------- case 5:
case 6: {
//-------------------------------------------------------------------
// Updating Jk with gnu gsl
//-------------------------------------------------------------------
#if !defined(HAVE_GSL) #if !defined(HAVE_GSL)
Message::Error("FLAG_MINMETHOD = %d requires the GSL in function 'Vector_U Message::Error(
pdate_Jk_VAR'.\n" "FLAG_MINMETHOD = %d requires the GSL in function "
"FLAG_MINMETHOD = 1 --> steepest descent (homemade)\n" "'Vector_Update_Jk_VAR'.\n"
"FLAG_MINMETHOD = 2 --> conjugate fr (gsl)\n" "FLAG_MINMETHOD = 1 --> steepest descent (homemade)\n"
"FLAG_MINMETHOD = 3 --> conjugate pr (gsl)\n" "FLAG_MINMETHOD = 2 --> conjugate fr (gsl)\n"
"FLAG_MINMETHOD = 4 --> bfgs2 (gsl)\n" "FLAG_MINMETHOD = 3 --> conjugate pr (gsl)\n"
"FLAG_MINMETHOD = 5 --> bfgs (gsl)\n" "FLAG_MINMETHOD = 4 --> bfgs2 (gsl)\n"
"FLAG_MINMETHOD = 6 --> steepest descent (gsl)\n" "FLAG_MINMETHOD = 5 --> bfgs (gsl)\n"
"FLAG_MINMETHOD = 11 --> steepest descent (homemade)\n "FLAG_MINMETHOD = 6 --> steepest descent (gsl)\n"
" "FLAG_MINMETHOD = 11 --> steepest descent (homemade)\n"
"FLAG_MINMETHOD = 22 --> conjugate Fletcher-Reeves (ho "FLAG_MINMETHOD = 22 --> conjugate Fletcher-Reeves (homemade)\n"
memade)\n" "FLAG_MINMETHOD = 33 --> conjugate Polak-Ribiere (homemade)\n"
"FLAG_MINMETHOD = 33 --> conjugate Polak-Ribiere (home "FLAG_MINMETHOD = 333 --> conjugate Polak-Ribiere+ (homemade)\n"
made)\n" "FLAG_MINMETHOD = 1999 --> conjugate Dai Yuan 1999 (p.85) (homemade)\n"
"FLAG_MINMETHOD = 333 --> conjugate Polak-Ribiere+ (hom "FLAG_MINMETHOD = 2005 --> conjugate Hager Zhang 2005 (p.161) "
emade)\n" "(homemade)\n"
"FLAG_MINMETHOD = 1999 --> conjugate Dai Yuan 1999 (p.85 "FLAG_MINMETHOD = 77 --> newton (homemade)\n",
) (homemade)\n" ::FLAG_MINMETHOD);
"FLAG_MINMETHOD = 2005 --> conjugate Hager Zhang 2005 (p
.161) (homemade)\n"
"FLAG_MINMETHOD = 77 --> newton (homemade)\n", ::FLAG_
MINMETHOD);
#else #else
const int MAX_ITER = ::MAX_ITER_OM; const int MAX_ITER = ::MAX_ITER_OM;
int iter = 0, status; int iter = 0, status;
double step_size = 0.01; // 0.01 at basic double step_size = 0.01; // 0.01 at basic
double TOL = ::TOLERANCE_OM; double TOL = ::TOLERANCE_OM;
double tol = TOL; //(0.1 recommended for bfgs and steepest descent else to double tol =
l=TOL) TOL; //(0.1 recommended for bfgs and steepest descent else tol=TOL)
double omegap; double omegap;
double J[3] = { J0[0], J0[1], J0[2] }; double J[3] = {J0[0], J0[1], J0[2]};
//http://www.gnu.org/software/gsl/manual/html_node/Multimin-Algorithms-wit // http://www.gnu.org/software/gsl/manual/html_node/Multimin-Algorithms-with
h-Derivatives.html -Derivatives.html
const gsl_multimin_fdfminimizer_type *TYPE = 0; const gsl_multimin_fdfminimizer_type *TYPE = 0;
switch(::FLAG_MINMETHOD) { switch(::FLAG_MINMETHOD) {
case 2: case 2: TYPE = gsl_multimin_fdfminimizer_conjugate_fr; break;
TYPE = gsl_multimin_fdfminimizer_conjugate_fr; case 3: TYPE = gsl_multimin_fdfminimizer_conjugate_pr; break;
break; case 4:
case 3: // FIXME: test GSL version (requires 1.?)
TYPE = gsl_multimin_fdfminimizer_conjugate_pr; TYPE = gsl_multimin_fdfminimizer_vector_bfgs2; // not work
break; break;
case 4: case 5: TYPE = gsl_multimin_fdfminimizer_vector_bfgs; break;
//FIXME: test GSL version (requires 1.?) case 6:
TYPE = gsl_multimin_fdfminimizer_vector_bfgs2; // not work // (The steepest descent method is inefficient and is included only for
break; // demonstration purposes)
case 5: TYPE = gsl_multimin_fdfminimizer_steepest_descent;
TYPE = gsl_multimin_fdfminimizer_vector_bfgs; break;
break; default: break;
case 6: }
// (The steepest descent method is inefficient and is included only fo
r demonstration purposes)
TYPE = gsl_multimin_fdfminimizer_steepest_descent;
break;
default:
break;
}
gsl_multimin_function_fdf my_func;
my_func.n = 3;
my_func.f = omega_f ;
my_func.df = omega_df ;
my_func.fdf = omega_fdf;
my_func.params = params;
gsl_vector* x = gsl_vector_alloc (3);
for (int i=0; i<3; i++) gsl_vector_set(x, i, J[i]) ; // initial value for
the minimizer
gsl_multimin_fdfminimizer *solver = gsl_multimin_fdfminimizer_alloc(TYPE, gsl_multimin_function_fdf my_func;
3);
gsl_multimin_fdfminimizer_set (solver, &my_func, x, step_size, tol);
do { my_func.n = 3;
iter++; my_func.f = omega_f;
omegap = solver->f; my_func.df = omega_df;
status = gsl_multimin_fdfminimizer_iterate (solver); my_func.fdf = omega_fdf;
if (status) break; // check if solver is stuck my_func.params = params;
} while( fabs(solver->f-omegap)>TOL && iter < MAX_ITER);
gsl_vector *x = gsl_vector_alloc(3);
if (::FLAG_WARNING>=FLAG_WARNING_INFO_APPROACH && iter==MAX_ITER) for(int i = 0; i < 3; i++)
Message::Warning("Minimization status : the iteration has not converged gsl_vector_set(x, i, J[i]); // initial value for the minimizer
yet,"
"after %d iteration(s)", iter); gsl_multimin_fdfminimizer *solver =
gsl_multimin_fdfminimizer_alloc(TYPE, 3);
gsl_multimin_fdfminimizer_set(solver, &my_func, x, step_size, tol);
do {
iter++;
omegap = solver->f;
status = gsl_multimin_fdfminimizer_iterate(solver);
if(status) break; // check if solver is stuck
} while(fabs(solver->f - omegap) > TOL && iter < MAX_ITER);
if(::FLAG_WARNING >= FLAG_WARNING_INFO_APPROACH && iter == MAX_ITER)
Message::Warning(
"Minimization status : the iteration has not converged yet,"
"after %d iteration(s)",
iter);
for (int n=0 ; n<3 ; n++) for(int n = 0; n < 3; n++) Jk[n] = gsl_vector_get(solver->x, n);
Jk[n] = gsl_vector_get (solver->x, n) ;
gsl_multimin_fdfminimizer_free (solver); gsl_multimin_fdfminimizer_free(solver);
gsl_vector_free (x); gsl_vector_free(x);
#endif #endif
} } break;
break; default:
default: Message::Error(
Message::Error("Invalid parameter (FLAG_MINMETHOD = 1,2,..6,11,22,33,333,1 "Invalid parameter (FLAG_MINMETHOD = 1,2,..6,11,22,33,333,1999,2005,77) "
999,2005,77) for function 'Vector_Update_Jk_VAR'.\n" "for function 'Vector_Update_Jk_VAR'.\n"
"FLAG_MINMETHOD = 1 --> steepest descent (homemade)\n" "FLAG_MINMETHOD = 1 --> steepest descent (homemade)\n"
"FLAG_MINMETHOD = 2 --> conjugate fr (gsl)\n" "FLAG_MINMETHOD = 2 --> conjugate fr (gsl)\n"
"FLAG_MINMETHOD = 3 --> conjugate pr (gsl)\n" "FLAG_MINMETHOD = 3 --> conjugate pr (gsl)\n"
"FLAG_MINMETHOD = 4 --> bfgs2 (gsl)\n" "FLAG_MINMETHOD = 4 --> bfgs2 (gsl)\n"
"FLAG_MINMETHOD = 5 --> bfgs (gsl)\n" "FLAG_MINMETHOD = 5 --> bfgs (gsl)\n"
"FLAG_MINMETHOD = 6 --> steepest descent (gsl)\n" "FLAG_MINMETHOD = 6 --> steepest descent (gsl)\n"
"FLAG_MINMETHOD = 11 --> steepest descent (homemade)\n "FLAG_MINMETHOD = 11 --> steepest descent (homemade)\n"
" "FLAG_MINMETHOD = 22 --> conjugate Fletcher-Reeves (homemade)\n"
"FLAG_MINMETHOD = 22 --> conjugate Fletcher-Reeves (ho "FLAG_MINMETHOD = 33 --> conjugate Polak-Ribiere (homemade)\n"
memade)\n" "FLAG_MINMETHOD = 333 --> conjugate Polak-Ribiere+ (homemade)\n"
"FLAG_MINMETHOD = 33 --> conjugate Polak-Ribiere (home "FLAG_MINMETHOD = 1999 --> conjugate Dai Yuan 1999 (p.85) (homemade)\n"
made)\n" "FLAG_MINMETHOD = 2005 --> conjugate Hager Zhang 2005 (p.161) "
"FLAG_MINMETHOD = 333 --> conjugate Polak-Ribiere+ (hom "(homemade)\n"
emade)\n" "FLAG_MINMETHOD = 77 --> newton (homemade)\n");
"FLAG_MINMETHOD = 1999 --> conjugate Dai Yuan 1999 (p.85
) (homemade)\n"
"FLAG_MINMETHOD = 2005 --> conjugate Hager Zhang 2005 (p
.161) (homemade)\n"
"FLAG_MINMETHOD = 77 --> newton (homemade)\n");
break; break;
} }
} }
void Vector_Update_hrk_DIFF_3d( const double h[3], void Vector_Update_hrk_DIFF_3d(const double h[3], double hr[3],
double hr[3], void *params) // not in F.h
void *params) // not in F.h
{ {
#if !defined(HAVE_GSL) #if !defined(HAVE_GSL)
Message::Error("FLAG_APPROACH = %d requires the GSL for the moment in Vector_U Message::Error("FLAG_APPROACH = %d requires the GSL for the moment in "
pdate_hrk_DIFF\n" "Vector_Update_hrk_DIFF\n"
"FLAG_APPROACH = 1 --> Variational Approach\n" "FLAG_APPROACH = 1 --> Variational Approach\n"
"FLAG_APPROACH = 2 --> Vector Play Model approach\n" "FLAG_APPROACH = 2 --> Vector Play Model approach\n"
"FLAG_APPROACH = 3 --> Full Differential Approach (gsl)", "FLAG_APPROACH = 3 --> Full Differential Approach (gsl)",
::FLAG_APPROACH); ::FLAG_APPROACH);
#else #else
struct params_Cells_EB *p = (struct params_Cells_EB *) params; struct params_Cells_EB *p = (struct params_Cells_EB *)params;
double hrp[3]; double hrp[3];
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) hrp[n] = p->Xp[n + 3 * p->idcell];
hrp[n] = p->Xp[n+3*p->idcell];
double kappa = p->kappa[p->idcell]; double kappa = p->kappa[p->idcell];
// Full Differential Case // Full Differential Case
if (kappa==0) // When kappa =0, we automatically know that hr=h !!! if(kappa == 0) // When kappa =0, we automatically know that hr=h !!!
{ {
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) hr[n] = h[n];
hr[n]=h[n];
} }
else else {
{
double tmp[3]; double tmp[3];
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) tmp[n] = h[n] - hrp[n];
tmp[n] = h[n]-hrp[n];
if (norm(tmp)>kappa) if(norm(tmp) > kappa) {
{
int status; int status;
int iterb = 0, max_iterb = ::MAX_ITER_NR; int iterb = 0, max_iterb = ::MAX_ITER_NR;
double TOL = ::TOLERANCE_OM; double TOL = ::TOLERANCE_OM;
for (int n=0 ; n<3 ; n++) for(int n = 0; n < 3; n++) p->h[n] = h[n];
p->h[n]=h[n]; Vector_Jk_From_hrk(hrp, params, p->Jp); // init p->Jp
Vector_Jk_From_hrk (hrp, params, p->Jp); // init p->Jp
const size_t nang = 2; const size_t nang = 2;
char solver_type[100]="'Multivariate Angles Root Finding for Update hr' "; char solver_type[100] =
"'Multivariate Angles Root Finding for Update hr' ";
const gsl_multiroot_fsolver_type *T; const gsl_multiroot_fsolver_type *T;
gsl_multiroot_fsolver *s; gsl_multiroot_fsolver *s;
double xinit[2]= {atan2(-tmp[1],-tmp[0]), acos(-tmp[2]/norm(tmp))}; double xinit[2] = {atan2(-tmp[1], -tmp[0]), acos(-tmp[2] / norm(tmp))};
double finit[3]; double finit[3];
fct_fall_DIFF_3d(xinit, params,finit); fct_fall_DIFF_3d(xinit, params, finit);
p->compout=0; p->compout = 0;
double finitmin=abs(finit[0]); double finitmin = abs(finit[0]);
for (int n=1; n<3; n++) for(int n = 1; n < 3; n++) {
{ if(abs(finit[n]) < finitmin) {
if (abs(finit[n])<finitmin) finitmin = abs(finit[n]);
{ p->compout = n;
finitmin=abs(finit[n]);
p->compout=n;
} }
} }
gsl_multiroot_function f = {&fct_f_DIFF_3d, nang, params}; gsl_multiroot_function f = {&fct_f_DIFF_3d, nang, params};
gsl_vector *x = gsl_vector_alloc(nang); gsl_vector *x = gsl_vector_alloc(nang);
gsl_vector_set (x, 0, xinit[0]); gsl_vector_set(x, 0, xinit[0]);
gsl_vector_set (x, 1, xinit[1]); gsl_vector_set(x, 1, xinit[1]);
T = gsl_multiroot_fsolver_hybrids; // BEST T = gsl_multiroot_fsolver_hybrids; // BEST
//T = gsl_multiroot_fsolver_hybrid; // T = gsl_multiroot_fsolver_hybrid;
//T = gsl_multiroot_fsolver_dnewton; // may lead to Error : GSL: matrix // T = gsl_multiroot_fsolver_dnewton; // may lead to Error : GSL: matrix
is singular // is singular T = gsl_multiroot_fsolver_broyden; // may lead to Error :
//T = gsl_multiroot_fsolver_broyden; // may lead to Error : GSL: matrix // GSL: matrix is singular
is singular
s = gsl_multiroot_fsolver_alloc (T, 2); s = gsl_multiroot_fsolver_alloc(T, 2);
gsl_multiroot_fsolver_set (s, &f, x); gsl_multiroot_fsolver_set(s, &f, x);
strcat(solver_type,gsl_multiroot_fsolver_name(s)); strcat(solver_type, gsl_multiroot_fsolver_name(s));
do do {
{ iterb++;
iterb++; status = gsl_multiroot_fsolver_iterate(s);
status = gsl_multiroot_fsolver_iterate (s);
if (status) //check if solver is stuck if(status) // check if solver is stuck
break; break;
status = status = gsl_multiroot_test_residual(s->f, TOL);
gsl_multiroot_test_residual (s->f, TOL);
print_state_3d (iterb, solver_type, status, s); print_state_3d(iterb, solver_type, status, s);
} } while(status == GSL_CONTINUE && iterb < max_iterb);
while (status == GSL_CONTINUE && iterb < max_iterb);
double x0[2]; double x0[2];
x0[0]=gsl_vector_get (s->x, 0); x0[0] = gsl_vector_get(s->x, 0);
x0[1]=gsl_vector_get (s->x, 1); x0[1] = gsl_vector_get(s->x, 1);
double ehi[3]; double ehi[3];
fct_ehirr_DIFF_3d(x0, ehi); fct_ehirr_DIFF_3d(x0, ehi);
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) hr[n] = h[n] + kappa * ehi[n];
hr[n]=h[n]+kappa*ehi[n];
gsl_multiroot_fsolver_free (s); gsl_multiroot_fsolver_free(s);
gsl_vector_free (x); gsl_vector_free(x);
} }
else else {
{ for(int n = 0; n < 3; n++) hr[n] = hrp[n];
for (int n=0; n<3; n++)
hr[n]=hrp[n];
} }
} }
#endif #endif
} }
void Vector_Update_hrk_DIFF_2d (const double h[3], void Vector_Update_hrk_DIFF_2d(const double h[3], double hr[3],
double hr[3], void *params) // not in F.h
void * params) // not in F.h
{ {
#if !defined(HAVE_GSL) #if !defined(HAVE_GSL)
Message::Error("FLAG_APPROACH = %d requires the GSL for the moment in Vector_U Message::Error("FLAG_APPROACH = %d requires the GSL for the moment in "
pdate_hrk_DIFF\n" "Vector_Update_hrk_DIFF\n"
"FLAG_APPROACH = 1 --> Variational Approach\n" "FLAG_APPROACH = 1 --> Variational Approach\n"
"FLAG_APPROACH = 2 --> Vector Play Model approach\n" "FLAG_APPROACH = 2 --> Vector Play Model approach\n"
"FLAG_APPROACH = 3 --> Full Differential Approach (gsl)", "FLAG_APPROACH = 3 --> Full Differential Approach (gsl)",
::FLAG_APPROACH); ::FLAG_APPROACH);
#else #else
struct params_Cells_EB *p = (struct params_Cells_EB *) params; struct params_Cells_EB *p = (struct params_Cells_EB *)params;
double hrp[3]; double hrp[3];
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) hrp[n] = p->Xp[n + 3 * p->idcell];
hrp[n] = p->Xp[n+3*p->idcell];
double kappa = p->kappa[p->idcell]; double kappa = p->kappa[p->idcell];
// Full Differential Case // Full Differential Case
if (kappa==0) // When kappa =0, we automatically know that hr=h !!! if(kappa == 0) // When kappa =0, we automatically know that hr=h !!!
{ {
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) hr[n] = h[n];
hr[n]=h[n];
} }
else else {
{
double tmp[3]; double tmp[3];
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) tmp[n] = h[n] - hrp[n];
tmp[n] = h[n]-hrp[n];
if (norm(tmp)>kappa) if(norm(tmp) > kappa) {
{
int status; int status;
int iterb = 0, max_iterb = ::MAX_ITER_NR; int iterb = 0, max_iterb = ::MAX_ITER_NR;
double TOL = ::TOLERANCE_OM; double TOL = ::TOLERANCE_OM;
for (int n=0 ; n<3 ; n++) for(int n = 0; n < 3; n++) p->h[n] = h[n];
p->h[n]=h[n];
Vector_Jk_From_hrk(hrp, params, p->Jp); // init p->Jp Vector_Jk_From_hrk(hrp, params, p->Jp); // init p->Jp
char solver_type[100]="'1D Brent for Update hr' "; char solver_type[100] = "'1D Brent for Update hr' ";
const gsl_root_fsolver_type *T; const gsl_root_fsolver_type *T;
gsl_root_fsolver *s; gsl_root_fsolver *s;
double xinit= atan2(tmp[1],tmp[0]); double xinit = atan2(tmp[1], tmp[0]);
double r = xinit; double r = xinit;
double al, br; double al, br;
double phi = acos(kappa/norm(tmp)); double phi = acos(kappa / norm(tmp));
al=xinit-phi; br=xinit+phi; al = xinit - phi;
br = xinit + phi;
double x0; double x0;
double ffa=fct_f_DIFF_2d(al, params); double ffa = fct_f_DIFF_2d(al, params);
double ffb=fct_f_DIFF_2d(br, params); double ffb = fct_f_DIFF_2d(br, params);
if (ffa * ffb>0) if(ffa * ffb > 0) {
{ if(::FLAG_WARNING >= FLAG_WARNING_INFO_APPROACH)
if (::FLAG_WARNING>=FLAG_WARNING_INFO_APPROACH) Message::Warning("ff(a)*ff(b) > 0 : ff(a)=%g; ff(b)=%g kappa=%g", ffa,
Message::Warning("ff(a)*ff(b) > 0 : ff(a)=%g; ff(b)=%g kappa=%g",ffa,f ffb, kappa);
fb,kappa); x0 = xinit;
x0=xinit;
} }
else else {
{
gsl_function F; gsl_function F;
F.function = &fct_f_DIFF_2d; F.function = &fct_f_DIFF_2d;
F.params = params; F.params = params;
//T = gsl_root_fsolver_bisection; // T = gsl_root_fsolver_bisection;
T = gsl_root_fsolver_brent; // BEST T = gsl_root_fsolver_brent; // BEST
//T = gsl_root_fsolver_falsepos; // T = gsl_root_fsolver_falsepos;
s = gsl_root_fsolver_alloc (T); s = gsl_root_fsolver_alloc(T);
gsl_root_fsolver_set (s, &F, al, br); gsl_root_fsolver_set(s, &F, al, br);
strcat(solver_type,gsl_root_fsolver_name(s)); strcat(solver_type, gsl_root_fsolver_name(s));
do
{
iterb++;
status = gsl_root_fsolver_iterate (s);
r = gsl_root_fsolver_root (s);
al = gsl_root_fsolver_x_lower (s);
br = gsl_root_fsolver_x_upper (s);
status do {
= gsl_root_test_interval (al, br, TOL, TOL); iterb++;
status = gsl_root_fsolver_iterate(s);
print_state_2d(iterb, solver_type, r = gsl_root_fsolver_root(s);
status, al, br, r, br - al); al = gsl_root_fsolver_x_lower(s);
} br = gsl_root_fsolver_x_upper(s);
while (status == GSL_CONTINUE && iterb < max_iterb);
status = gsl_root_test_interval(al, br, TOL, TOL);
gsl_root_fsolver_free (s); print_state_2d(iterb, solver_type, status, al, br, r, br - al);
x0=r; } while(status == GSL_CONTINUE && iterb < max_iterb);
gsl_root_fsolver_free(s);
x0 = r;
} }
double hi[3]; double hi[3];
Vector_hirr_DIFF_2d(x0, kappa, hi); Vector_hirr_DIFF_2d(x0, kappa, hi);
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) hr[n] = h[n] - hi[n];
hr[n]=h[n]-hi[n];
} }
else else {
{ for(int n = 0; n < 3; n++) hr[n] = hrp[n];
for (int n=0; n<3; n++)
hr[n]=hrp[n];
} }
} }
#endif #endif
} }
void Vector_Update_hrk_DIFF( const double h[3], void Vector_Update_hrk_DIFF(const double h[3], double hr[3], double hr0[3],
double hr[3], void *params)
double hr0[3],
void * params)
{ {
// Full Differential Case // Full Differential Case
switch(::FLAG_DIM) switch(::FLAG_DIM) {
{ case 2: // 2D case
case 2: // 2D case Vector_Update_hrk_DIFF_2d(h, hr, params);
Vector_Update_hrk_DIFF_2d(h,hr,params);
break; break;
case 3: // 3D case case 3: // 3D case
Vector_Update_hrk_DIFF_3d(h,hr,params); Vector_Update_hrk_DIFF_3d(h, hr, params);
break; break;
default: default:
Message::Error("Invalid parameter (dimension = 2 or 3)" Message::Error("Invalid parameter (dimension = 2 or 3)"
"for function 'Vector_Update_hrk_DIFF'."); "for function 'Vector_Update_hrk_DIFF'.");
break; break;
} }
} }
void Vector_Update_hrk_VPM( const double h[3], void Vector_Update_hrk_VPM(const double h[3], double hr[3], double hr0[3],
double hr[3], void *params)
double hr0[3],
void * params)
{ {
// Vector Play Model Approach // Vector Play Model Approach
struct params_Cells_EB *p = (struct params_Cells_EB *) params; struct params_Cells_EB *p = (struct params_Cells_EB *)params;
double hrp[3]; double hrp[3];
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) hrp[n] = p->Xp[n + 3 * p->idcell];
hrp[n] = p->Xp[n+3*p->idcell]; double kappa = p->kappa[p->idcell];
double kappa = p->kappa[p->idcell];
Vector_Update_hrk_VPM_( h, hr, hrp, kappa); Vector_Update_hrk_VPM_(h, hr, hrp, kappa);
} }
void Vector_Update_hrk_VPM_ ( const double h[3], void Vector_Update_hrk_VPM_(const double h[3], double hr[3],
double hr[3], const double hrp[3], const double kappa)
const double hrp[3],
const double kappa)
{ {
// Vector Play Model Approach // Vector Play Model Approach
double dhr[3]; double dhr[3];
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) dhr[n] = h[n] - hrp[n];
dhr[n] = h[n]-hrp[n];
double ndhr = norm(dhr); double ndhr = norm(dhr);
if (ndhr >= kappa) { if(ndhr >= kappa) {
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++)
hr[n]=(ndhr>0)? h[n]-kappa*(dhr[n]/ndhr) : h[n]; hr[n] = (ndhr > 0) ? h[n] - kappa * (dhr[n] / ndhr) : h[n];
} }
else { else {
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) hr[n] = hrp[n];
hr[n]=hrp[n];
} }
} }
void Vector_b_EB (const double h[3], void Vector_b_EB(const double h[3], double b[3], double *Xk_all, void *params)
double b[3],
double *Xk_all,
void * params)
{ {
struct params_Cells_EB *p = (struct params_Cells_EB *)params;
struct params_Cells_EB *p = (struct params_Cells_EB *) params;
double hrtot[3], hrk[3]; double hrtot[3], hrk[3];
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) {
{ hrtot[n] = 0.;
hrtot[n]=0.; hrk[n] = 0.;
hrk[n]=0.; b[n] = ::SLOPE_FACTOR * MU0 * h[n]; // Slope forcing
b[n] = ::SLOPE_FACTOR* MU0 * h[n]; // Slope forcing
} }
double wk, Xk[3]; double wk, Xk[3];
for (int k=0; k<p->N; k++) { for(int k = 0; k < p->N; k++) {
p->idcell = k; p->idcell = k;
wk = p->w[k]; wk = p->w[k];
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) Xk[n] = Xk_all[n + 3 * k];
Xk[n] = Xk_all[n+3*k];
switch(::FLAG_APPROACH) { switch(::FLAG_APPROACH) {
case 1: // Variationnal Case case 1: // Variationnal Case
{ {
Vector_Update_Jk_VAR(h,Xk,Xk, params); Vector_Update_Jk_VAR(h, Xk, Xk, params);
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) Xk_all[n + 3 * k] = Xk[n]; // up Xk_all
Xk_all[n+3*k] = Xk[n]; // up Xk_all switch(::FLAG_HOMO) {
switch (::FLAG_HOMO) { case 0: {
case 0: for(int n = 0; n < 3; n++) b[n] += Xk[n];
{ } break;
for (int n=0; n<3; n++) case 1: {
b[n] += Xk[n]; // Find hrk
} Vector_hrk_From_Jk(Xk, params, hrk);
break; // hrtot = sum hrk
case 1: for(int n = 0; n < 3; n++) hrtot[n] += wk * hrk[n];
{ } break;
// Find hrk default:
Vector_hrk_From_Jk(Xk,params, hrk); Message::Error("Flag_Homo not defined (1 or 0)"
// hrtot = sum hrk "for function 'Vector_b_EB'.");
for (int n=0; n<3; n++) break;
hrtot[n] += wk*hrk[n];
}
break;
default:
Message::Error("Flag_Homo not defined (1 or 0)"
"for function 'Vector_b_EB'.");
break;
}
}
break;
case 2: // VPM Approach
case 3: // Full Differential Approach
{
switch(::FLAG_APPROACH) {
case 2:
Vector_Update_hrk_VPM(h,Xk,Xk, params);
break;
case 3:
Vector_Update_hrk_DIFF(h,Xk,Xk, params);
break;
}
for (int n=0; n<3; n++)
Xk_all[n+3*k] = Xk[n]; // up Xk_all
switch (::FLAG_HOMO) {
case 0:
{
double Jk[3];
Vector_Jk_From_hrk(Xk,params,Jk);
for (int n=0; n<3; n++)
b[n] += Jk[n];
}
break;
case 1:
{
// hrtot = sum hrk
for (int n=0; n<3; n++)
hrtot[n] += wk* Xk[n];
}
break;
default:
Message::Error("Flag_Homo not defined (1 or 0)"
"for function 'Vector_b_EB'.");
break;
}
} }
break;
} break;
case 2: // VPM Approach
case 3: // Full Differential Approach
{
switch(::FLAG_APPROACH) {
case 2: Vector_Update_hrk_VPM(h, Xk, Xk, params); break;
case 3: Vector_Update_hrk_DIFF(h, Xk, Xk, params); break;
}
for(int n = 0; n < 3; n++) Xk_all[n + 3 * k] = Xk[n]; // up Xk_all
switch(::FLAG_HOMO) {
case 0: {
double Jk[3];
Vector_Jk_From_hrk(Xk, params, Jk);
for(int n = 0; n < 3; n++) b[n] += Jk[n];
} break;
case 1: {
// hrtot = sum hrk
for(int n = 0; n < 3; n++) hrtot[n] += wk * Xk[n];
} break;
default: default:
Message::Error("Invalid parameter (FLAG_APPROACH = 1,2 or 3) for functio Message::Error("Flag_Homo not defined (1 or 0)"
n 'Vector_b_EB'.\n" "for function 'Vector_b_EB'.");
"FLAG_APPROACH = 1 --> Variational Approach\n" break;
"FLAG_APPROACH = 2 --> Vector Play Model approach\n" }
"FLAG_APPROACH = 3 --> Full Differential Approach (gsl)"); } break;
default:
Message::Error("Invalid parameter (FLAG_APPROACH = 1,2 or 3) for "
"function 'Vector_b_EB'.\n"
"FLAG_APPROACH = 1 --> Variational Approach\n"
"FLAG_APPROACH = 2 --> Vector Play Model approach\n"
"FLAG_APPROACH = 3 --> Full Differential Approach (gsl)");
break; break;
} }
} }
if (::FLAG_HOMO==1) if(::FLAG_HOMO == 1) {
{
double Jtot[3]; double Jtot[3];
p->idcell=-1; // due to the need to take global Ja, Jb (not Jak=wk*Ja, Jbk=w int old = p->idcell;
k*Jb) ! p->idcell =
Vector_Jk_From_hrk(hrtot,params,Jtot); -1; // due to the need to take global Ja, Jb (not Jak=wk*Ja, Jbk=wk*Jb) !
for (int n=0; n<3; n++) Vector_Jk_From_hrk(hrtot, params, Jtot);
b[n] += Jtot[n]; p->idcell = old;
for(int n = 0; n < 3; n++) b[n] += Jtot[n];
} }
} }
void Vector_h_EB ( const double b[3], void Vector_h_EB(const double b[3], double bc[3], double h[3], double *Xk_all,
double bc[3], void *params)
double h[3],
double *Xk_all,
void * params )
{ {
// Use an Inversion Method to deduce the h associated to b. // Use an Inversion Method to deduce the h associated to b.
// First, update bc and Xk_all: // First, update bc and Xk_all:
Vector_b_EB(h, bc, Xk_all, params); Vector_b_EB(h, bc, Xk_all, params);
// * This recompute the bc (and Jkall) from h - which is a hinit - to start th // * This recompute the bc (and Jkall) from h - which is a hinit - to start
e NR // the NR (instead of taking the bc (and Jkall) given in argument... thus, the
// (instead of taking the bc (and Jkall) given in argument... // bc and Jkall given in argument are not necessary now.)
// thus, the bc and Jkall given in argument are not necessary now.)
// * h can be {h}[1], ie. the h found at the last timestep. (original
// * h can be {h}[1], ie. the h found at the last timestep. (original approach // approach) in this case, bc={b}[1] could be used also in order to avoid the
) // re-evaluation of Vector_b_EB. However, this is not totally correct because
// in this case, bc={b}[1] could be used also
// in order to avoid the re-evaluation of Vector_b_EB.
// However, this is not totally correct because
// bc=b_EB({h[1]}) and {b}[1] are not exactly the same // bc=b_EB({h[1]}) and {b}[1] are not exactly the same
// but are as close as the stopping criterion defined for // but are as close as the stopping criterion defined for
// the NR process allows to tolerate. // the NR process allows to tolerate.
// * h can be {h}, ie. the h from the last iteration, (new since 2/3/2018) // * h can be {h}, ie. the h from the last iteration, (new since 2/3/2018)
// Note: this works because there is a small lag through iterations // Note: this works because there is a small lag through iterations
// between the dof{h} that depends on {b} and dof{b} that depends on dof{h} // between the dof{h} that depends on {b} and dof{b} that depends on dof{h}
// as can be seen in the formulation in magstadyna.pro (a-v formulation). // as can be seen in the formulation in magstadyna.pro (a-v formulation).
// Therefore the arguments b={b} and bc=b_EB({h}) are different, // Therefore the arguments b={b} and bc=b_EB({h}) are different,
// otherwise the NR stop criterion would be directly satisfied. // otherwise the NR stop criterion would be directly satisfied.
// * This is even more recommended when ExtrapolatePolynomial // * This is even more recommended when ExtrapolatePolynomial
// is activated to init the next generated Timestep, because // is activated to init the next generated Timestep, because
// bc=b_EB({h}) has not yet been computed with the new predicted {h} // bc=b_EB({h}) has not yet been computed with the new predicted {h}
double TOL = ::TOLERANCE_NR; double TOL = ::TOLERANCE_NR;
const int MAX_ITER = ::MAX_ITER_NR; const int MAX_ITER = ::MAX_ITER_NR;
double dh[3], dx[3], df[3],res[3], b_bc[3] ; double dx[3] = {0, 0, 0}, df[3] = {0, 0, 0}, res[3] = {0, 0, 0},
double Ib_bcI; b_bc[3] = {0, 0, 0};
int ncomp = ::NCOMP; int ncomp = ::NCOMP;
double *dbdh; dbdh = new double[ncomp]; double *dbdh;
double *dhdb; dhdb = new double[ncomp]; dbdh = new double[ncomp];
for (int n=0; n<ncomp; n++) {dbdh[n]=0.; dhdb[n]=0.;} double *dhdb;
dhdb = new double[ncomp];
for (int n=0; n<3; n++) dh[n]=10.*::DELTA_0; for(int n = 0; n < ncomp; n++) {
double ndh=norm(dh); dbdh[n] = 0.;
dhdb[n] = 0.;
int iter = 0 ; }
while( iter < MAX_ITER &&
((fabs(bc[0]-b[0])/(1+fabs(b[0]))) > TOL || double dh[3];
(fabs(bc[1]-b[1])/(1+fabs(b[1]))) > TOL || for(int n = 0; n < 3; n++) dh[n] = 10. * ::DELTA_0;
(fabs(bc[2]-b[2])/(1+fabs(b[2]))) > TOL )) double ndh = norm(dh);
{
int iter = 0;
::DELTA_0=norm(dh)/10; //DELTA_00 +++ while(iter < MAX_ITER && ((fabs(bc[0] - b[0]) / (1 + fabs(b[0]))) > TOL ||
(fabs(bc[1] - b[1]) / (1 + fabs(b[1]))) > TOL ||
(fabs(bc[2] - b[2]) / (1 + fabs(b[2]))) > TOL)) {
::DELTA_0 = norm(dh) / 10; // DELTA_00 +++
switch(::FLAG_INVMETHOD) { switch(::FLAG_INVMETHOD) {
//--------------------------------------------- //---------------------------------------------
// CASE 1 : NR // CASE 1 : NR
//--------------------------------------------- //---------------------------------------------
case 1: // NR case 1: // NR
{ {
Tensor_dbdh_ana(h, Xk_all, params , dbdh); // eval dbdh Tensor_dbdh_ana(h, Xk_all, params, dbdh); // eval dbdh
switch(::FLAG_SYM) switch(::FLAG_SYM) {
{ case 1: Inv_TensorSym3x3(dbdh, dhdb); break;
case 1: case 0: Inv_Tensor3x3(dbdh, dhdb); break;
Inv_TensorSym3x3(dbdh, dhdb); default:
break; Message::Error("Invalid parameter (FLAG_SYM = 0 or 1)"
case 0: "for function 'Vector_h_EB'.\n");
Inv_Tensor3x3(dbdh, dhdb); break;
break;
default:
Message::Error("Invalid parameter (FLAG_SYM = 0 or 1)"
"for function 'Vector_h_EB'.\n");
break;
}
} }
break; } break;
//--------------------------------------------- //---------------------------------------------
// CASE 2 : NR_num // CASE 2 : NR_num
//--------------------------------------------- //---------------------------------------------
case 2: // NR_num case 2: // NR_num
{ {
Tensor_num(Vector_b_EB, h, ::DELTA_0, Xk_all, params, dbdh); Tensor_num(Vector_b_EB, h, ::DELTA_0, Xk_all, params, dbdh);
switch(::FLAG_SYM) switch(::FLAG_SYM) {
{ case 1: Inv_TensorSym3x3(dbdh, dhdb); break;
case 1: case 0: Inv_Tensor3x3(dbdh, dhdb); break;
Inv_TensorSym3x3(dbdh, dhdb); default:
break; Message::Error("Invalid parameter (FLAG_SYM = 0 or 1)"
case 0: "for function 'Vector_h_EB'.\n");
Inv_Tensor3x3(dbdh, dhdb); break;
break;
default:
Message::Error("Invalid parameter (FLAG_SYM = 0 or 1)"
"for function 'Vector_h_EB'.\n");
break;
}
} }
break; } break;
//--------------------------------------------- //---------------------------------------------
// CASE 3 : Good_BFGS // CASE 3 : Good_BFGS
//--------------------------------------------- //---------------------------------------------
case 3: // Good_BFGS case 3: // Good_BFGS
{ {
if (iter>0 ) if(iter > 0)
Tensor_dhdb_GoodBFGS(dx,df,dhdb); Tensor_dhdb_GoodBFGS(dx, df, dhdb);
else else {
{ Tensor_dbdh_ana(h, Xk_all, params, dbdh); // eval dbdh analytically
Tensor_dbdh_ana(h, Xk_all, params, dbdh ); // eval dbdh analytically // Tensor_num(Vector_b_EB, h, ::DELTA_0, Xk_all, params, dbdh); // eval
//Tensor_num(Vector_b_EB, h, ::DELTA_0, Xk_all, params, dbdh); // eval // dbdh numerically
dbdh numerically switch(::FLAG_SYM) {
switch(::FLAG_SYM) case 1: Inv_TensorSym3x3(dbdh, dhdb); break;
{ case 0: Inv_Tensor3x3(dbdh, dhdb); break;
case 1: default:
Inv_TensorSym3x3(dbdh, dhdb); Message::Error("Invalid parameter (FLAG_SYM = 0 or 1)"
break; "for function 'Vector_h_EB'.\n");
case 0: break;
Inv_Tensor3x3(dbdh, dhdb);
break;
default:
Message::Error("Invalid parameter (FLAG_SYM = 0 or 1)"
"for function 'Vector_h_EB'.\n");
break;
}
} }
} }
break; } break;
default: default:
Message::Error("Invalid parameter (FLAG_INVMETHOD = 1,2,3) for function 'V Message::Error("Invalid parameter (FLAG_INVMETHOD = 1,2,3) for function "
ector_h_EB'.\n" "'Vector_h_EB'.\n"
"FLAG_INVMETHOD = 1 --> NR_ana (homemade)\n" "FLAG_INVMETHOD = 1 --> NR_ana (homemade)\n"
"FLAG_INVMETHOD = 2 --> NR_num (homemade)\n" "FLAG_INVMETHOD = 2 --> NR_num (homemade)\n"
"FLAG_INVMETHOD = 3 --> Good_BFGS (homemade)"); "FLAG_INVMETHOD = 3 --> Good_BFGS (homemade)");
break; break;
} }
for (int n=0; n<3; n++) b_bc[n]=b[n]-bc[n]; for(int n = 0; n < 3; n++) b_bc[n] = b[n] - bc[n];
Ib_bcI=norm(b_bc); double Ib_bcI = norm(b_bc);
Mul_TensorVec(dhdb, b_bc, dh, 0); Mul_TensorVec(dhdb, b_bc, dh, 0);
//............................................... (WHILE LOOP) // dh/2 //............................................... (WHILE LOOP) // dh/2
double b_btest[3], htest[3]; double b_btest[3], htest[3];
for (int n=0 ; n<3 ; n++) for(int n = 0; n < 3; n++) {
{
df[n] = -bc[n]; df[n] = -bc[n];
dh[n] = 2*dh[n]; dh[n] = 2 * dh[n];
} }
int counter=0; int counter = 0;
ndh=norm(dh); ndh = norm(dh);
do do {
{ ndh = ndh / 2;
ndh=ndh/2; for(int n = 0; n < 3; n++) {
for (int n=0 ; n<3 ; n++) dh[n] = dh[n] / 2;
{ htest[n] = h[n] + dh[n];
dh[n]=dh[n]/2;
htest[n] = h[n]+dh[n];
} }
Vector_b_EB(htest, bc, Xk_all, params); // Update bc, Jk_all Vector_b_EB(htest, bc, Xk_all, params); // Update bc, Jk_all
for (int n=0 ; n<3 ; n++){ for(int n = 0; n < 3; n++) { b_btest[n] = b[n] - bc[n]; }
b_btest[n]=b[n]-bc[n];
}
counter++; counter++;
if (::FLAG_WARNING>=FLAG_WARNING_INFO_INV && counter>1) if(::FLAG_WARNING >= FLAG_WARNING_INFO_INV && counter > 1)
Message::Warning("activated dh/2 in inversion process %d",counter); Message::Warning("activated dh/2 in inversion process %d", counter);
} } while((norm(b_btest) > Ib_bcI) && counter < 10 && ndh > ::TOLERANCE_NR);
while ( (norm(b_btest) > Ib_bcI) &&
counter<10 && ndh>::TOLERANCE_NR);
for (int n=0 ; n<3 ; n++){ for(int n = 0; n < 3; n++) {
dx[n]= dh[n]; dx[n] = dh[n];
h[n] = htest[n]; h[n] = htest[n];
df[n] += bc[n]; df[n] += bc[n];
} }
//............................................... //...............................................
if(::FLAG_WARNING>=FLAG_WARNING_INFO_INV && iter>=FLAG_WARNING_DISPABOVEITER if(::FLAG_WARNING >= FLAG_WARNING_INFO_INV &&
){ iter >= FLAG_WARNING_DISPABOVEITER) {
//printf("dh(%d)=[%.8g,%.8g,%.8g];\t",iter,dh[0],dh[1],dh[2] ); // printf("dh(%d)=[%.8g,%.8g,%.8g];\t",iter,dh[0],dh[1],dh[2] );
printf("h(%d)=[%.8g,%.8g,%.8g];\t",iter,h[0],h[1],h[2] ); printf("h(%d)=[%.8g,%.8g,%.8g];\t", iter, h[0], h[1], h[2]);
printf("b(%d)=[%.8g,%.8g,%.8g];\t",iter,bc[0],bc[1],bc[2] ); printf("b(%d)=[%.8g,%.8g,%.8g];\t", iter, bc[0], bc[1], bc[2]);
for (int n=0 ; n<3 ; n++) for(int n = 0; n < 3; n++)
res[n]=(fabs(bc[n]-b[n])/(1+fabs(b[n]))); res[n] = (fabs(bc[n] - b[n]) / (1 + fabs(b[n])));
printf("residu(%d) = %.8g ([%.8g,%.8g,%.8g])\n", iter, norm(res), res[0],r printf("residu(%d) = %.8g ([%.8g,%.8g,%.8g])\n", iter, norm(res), res[0],
es[1],res[2]); res[1], res[2]);
} }
iter++; iter++;
} }
if (::FLAG_WARNING>=FLAG_WARNING_STOP_INV) if(::FLAG_WARNING >= FLAG_WARNING_STOP_INV)
Message::Warning("Inversion status = %d iteration(s) needed",iter); Message::Warning("Inversion status = %d iteration(s) needed", iter);
// Show b et h obtained at the end of the NR loop : // Show b et h obtained at the end of the NR loop :
if (::FLAG_WARNING>=FLAG_WARNING_INFO_INV && iter==MAX_ITER){ if(::FLAG_WARNING >= FLAG_WARNING_INFO_INV && iter == MAX_ITER) {
Message::Warning("Inversion status = the inversion has not converged yet, af Message::Warning("Inversion status = the inversion has not converged yet, "
ter %d iteration(s)",iter); "after %d iteration(s)",
if (::FLAG_WARNING>=FLAG_WARNING_INFO_INV){ iter);
Message::Warning("b_desired : [%.10g, %.10g, %.10g]", b[0],b[1],b[2]); if(::FLAG_WARNING >= FLAG_WARNING_INFO_INV) {
Message::Warning("b_get : [%.10g, %.10g, %.10g]", bc[0],bc[1],bc[2]); Message::Warning("b_desired : [%.10g, %.10g, %.10g]", b[0], b[1], b[2]);
Message::Warning("h_get : [%.10g, %.10g, %.10g]", h[0],h[1],h[2]); Message::Warning("b_get : [%.10g, %.10g, %.10g]", bc[0], bc[1],
if (::FLAG_WARNING >= FLAG_WARNING_STOP_INV){ bc[2]);
if(getchar()){ Message::Warning("h_get : [%.10g, %.10g, %.10g]", h[0], h[1], h[2]);
} if(::FLAG_WARNING >= FLAG_WARNING_STOP_INV) {
if(getchar()) {}
} }
} }
} }
delete [] dbdh; delete[] dbdh;
delete [] dhdb; delete[] dhdb;
} }
//************************************************ //************************************************
// Energy-Based Model - Tensor Construction // Energy-Based Model - Tensor Construction
//************************************************ //************************************************
void Tensor_dJkdh_VAR ( const double h[3], void Tensor_dJkdh_VAR(const double h[3], const double Jk[3], void *params,
const double Jk[3], double *dJkdh)
void * params,
double *dJkdh)
{ {
struct params_Cells_EB *p = (struct params_Cells_EB *)params;
struct params_Cells_EB *p = (struct params_Cells_EB *) params;
double Jkp[3]; double Jkp[3];
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) Jkp[n] = p->Xp[n + 3 * p->idcell];
Jkp[n] = p->Xp[n+3*p->idcell];
double dJk[3]; double dJk[3];
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) dJk[n] = Jk[n] - Jkp[n];
dJk[n] = Jk[n]-Jkp[n];
double nJk = norm(Jk); double nJk = norm(Jk);
double ndJk = norm(dJk); double ndJk = norm(dJk);
if ((::FLAG_ANA) && (nJk>(::TOLERANCE_NJ) && ndJk>(::TOLERANCE_NJ))){ if((::FLAG_ANA) && (nJk > (::TOLERANCE_NJ) && ndJk > (::TOLERANCE_NJ))) {
Message::Debug("--- Tensor_dJkdh_VAR: Analytical Jacobian ---"); Message::Debug("--- Tensor_dJkdh_VAR: Analytical Jacobian ---");
int ncomp = ::NCOMP; int ncomp = ::NCOMP;
double *idJkdh; idJkdh = new double[ncomp]; double *idJkdh;
fct_dd_omega_VAR(h,Jk,params,idJkdh); idJkdh = new double[ncomp];
switch(::FLAG_SYM) fct_dd_omega_VAR(h, Jk, params, idJkdh);
{ switch(::FLAG_SYM) {
case 1: // Symmetric tensor case 1: // Symmetric tensor
Inv_TensorSym3x3(idJkdh, dJkdh); // T, invT Inv_TensorSym3x3(idJkdh, dJkdh); // T, invT
break; break;
case 0: // Non Symmetric Tensor case 0: // Non Symmetric Tensor
Inv_Tensor3x3(idJkdh, dJkdh); // T, invT Inv_Tensor3x3(idJkdh, dJkdh); // T, invT
break; break;
default: default:
Message::Error("Invalid parameter (FLAG_SYM = 0 or 1)" Message::Error("Invalid parameter (FLAG_SYM = 0 or 1)"
"for function 'Tensor_dJkdh_VAR'.\n"); "for function 'Tensor_dJkdh_VAR'.\n");
break; break;
} }
delete [] idJkdh; delete[] idJkdh;
} }
else{ else {
Message::Debug("--- Tensor_dJkdh_VAR: Numerical Jacobian ---"); Message::Debug("--- Tensor_dJkdh_VAR: Numerical Jacobian ---");
double Jkdummy[3]={0,0,0}; double Jkdummy[3] = {0, 0, 0};
Tensor_num(Vector_Update_Jk_VAR, h, ::DELTA_0, Jkdummy, params, dJkdh); Tensor_num(Vector_Update_Jk_VAR, h, ::DELTA_0, Jkdummy, params, dJkdh);
} }
} }
void Tensor_dJkdh_VPMorDIFF ( const double h[3], void Tensor_dJkdh_VPMorDIFF(const double h[3], const double hrk[3],
const double hrk[3], void *params, double *dJkdh)
void * params,
double *dJkdh)
{ {
// dJkdhrk ------------------------------------------------------------------- // dJkdhrk
---------------- // ---------------------------------------------------------------------------
--------
// -> dJkdhrk is always symmetric // -> dJkdhrk is always symmetric
double dJkdhrk[6]; double dJkdhrk[6];
Tensor_dJkdhrk(hrk , params, dJkdhrk); Tensor_dJkdhrk(hrk, params, dJkdhrk);
// dhrkdh -------------------------------------------------------------------- // dhrkdh
--------------- // ---------------------------------------------------------------------------
--------
// -> dhrkdh is symmetric in that case but still stored with non-syn (9 comp) // -> dhrkdh is symmetric in that case but still stored with non-syn (9 comp)
double dhrkdh[9]; double dhrkdh[9];
switch(::FLAG_APPROACH) switch(::FLAG_APPROACH) {
{ case 2: // VPM
case 2: // VPM Tensor_dhrkdh_VPM_ana(h, hrk, params, dhrkdh);
Tensor_dhrkdh_VPM_ana(h,hrk,params,dhrkdh);
break; break;
case 3: // FULL DIFF case 3: // FULL DIFF
Tensor_dhrkdh_DIFF_ana(h,hrk,dJkdhrk,params,dhrkdh); Tensor_dhrkdh_DIFF_ana(h, hrk, dJkdhrk, params, dhrkdh);
break; break;
default: default:
Message::Error("Invalid parameter (FLAG_APPROACH = 2 or 3) for function 'T Message::Error("Invalid parameter (FLAG_APPROACH = 2 or 3) for function "
ensor_dJkdh_VPMorDIFF'.\n" "'Tensor_dJkdh_VPMorDIFF'.\n"
"FLAG_APPROACH = 2 --> Vector Play Model approach\n" "FLAG_APPROACH = 2 --> Vector Play Model approach\n"
"FLAG_APPROACH = 3 --> Full Differential Approach (gsl)"); "FLAG_APPROACH = 3 --> Full Differential Approach (gsl)");
break; break;
} }
// Product dJkdh = dJkdhrk * dhrkdh ------------------------------------------ // Product dJkdh = dJkdhrk * dhrkdh
------------------ // ------------------------------------------------------------
Mul_TensorSymTensorNonSym(dJkdhrk,dhrkdh,dJkdh); Mul_TensorSymTensorNonSym(dJkdhrk, dhrkdh, dJkdh);
} }
void Tensor_dhrkdh_DIFF_ana ( const double h[3], void Tensor_dhrkdh_DIFF_ana(const double h[3], const double hrk[3],
const double hrk[3], const double dJkdhrk[6], void *params,
const double dJkdhrk[6], double *dhrkdh)
void * params,
double *dhrkdh)
{ {
struct params_Cells_EB *p = (struct params_Cells_EB *) params; struct params_Cells_EB *p = (struct params_Cells_EB *)params;
double hrkp[3]; double hrkp[3];
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) hrkp[n] = p->Xp[n + 3 * p->idcell];
hrkp[n] = p->Xp[n+3*p->idcell];
double kappa = p->kappa[p->idcell]; double kappa = p->kappa[p->idcell];
double h_hrkp[3]; double h_hrkp[3];
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) h_hrkp[n] = h[n] - hrkp[n];
h_hrkp[n] = h[n]-hrkp[n];
double Ih_hrkpI = norm(h_hrkp); double Ih_hrkpI = norm(h_hrkp);
if (Ih_hrkpI>kappa) if(Ih_hrkpI > kappa) {
{
double dJ[3], mutgu[6]; double dJ[3], mutgu[6];
for (int n=0; n<6; n++) for(int n = 0; n < 6; n++) mutgu[n] = dJkdhrk[n];
mutgu[n] = dJkdhrk[n];
double Jkp[3]; double Jkp[3];
Vector_Jk_From_hrk( hrkp,params,Jkp); Vector_Jk_From_hrk(hrkp, params, Jkp);
Vector_Jk_From_hrk( hrk,params,dJ); Vector_Jk_From_hrk(hrk, params, dJ);
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) dJ[n] -= Jkp[n];
dJ[n] -= Jkp[n];
double ndJ = norm(dJ); double ndJ = norm(dJ);
if (kappa>0 && ndJ>(::TOLERANCE_0)) if(kappa > 0 && ndJ > (::TOLERANCE_0)) {
{
double temp[6], temp2[9]; double temp[6], temp2[9];
temp[0]=1. - (dJ[0]*dJ[0])/SQU(ndJ); temp[0] = 1. - (dJ[0] * dJ[0]) / SQU(ndJ);
temp[1]= - (dJ[0]*dJ[1])/SQU(ndJ); temp[1] = -(dJ[0] * dJ[1]) / SQU(ndJ);
temp[2]= - (dJ[0]*dJ[2])/SQU(ndJ); temp[2] = -(dJ[0] * dJ[2]) / SQU(ndJ);
temp[3]=1. - (dJ[1]*dJ[1])/SQU(ndJ); temp[3] = 1. - (dJ[1] * dJ[1]) / SQU(ndJ);
temp[4]= - (dJ[1]*dJ[2])/SQU(ndJ); temp[4] = -(dJ[1] * dJ[2]) / SQU(ndJ);
temp[5]=1. - (dJ[2]*dJ[2])/SQU(ndJ); temp[5] = 1. - (dJ[2] * dJ[2]) / SQU(ndJ);
Mul_TensorSymTensorSym(temp,mutgu,temp2); Mul_TensorSymTensorSym(temp, mutgu, temp2);
temp2[0]=1. + (kappa/ndJ) * temp2[0]; temp2[0] = 1. + (kappa / ndJ) * temp2[0];
temp2[1]= (kappa/ndJ) * temp2[1]; temp2[1] = (kappa / ndJ) * temp2[1];
temp2[2]= (kappa/ndJ) * temp2[2]; temp2[2] = (kappa / ndJ) * temp2[2];
temp2[3]= (kappa/ndJ) * temp2[3]; temp2[3] = (kappa / ndJ) * temp2[3];
temp2[4]=1. + (kappa/ndJ) * temp2[4]; temp2[4] = 1. + (kappa / ndJ) * temp2[4];
temp2[5]= (kappa/ndJ) * temp2[5]; temp2[5] = (kappa / ndJ) * temp2[5];
temp2[6]= (kappa/ndJ) * temp2[6]; temp2[6] = (kappa / ndJ) * temp2[6];
temp2[7]= (kappa/ndJ) * temp2[7]; temp2[7] = (kappa / ndJ) * temp2[7];
temp2[8]=1. + (kappa/ndJ) * temp2[8]; temp2[8] = 1. + (kappa / ndJ) * temp2[8];
Inv_Tensor3x3(temp2,dhrkdh); Inv_Tensor3x3(temp2, dhrkdh);
// OR one can use a numerical approximation for dhrkdh: // OR one can use a numerical approximation for dhrkdh:
// double hrkdummy[3]={0,0,0}; // double hrkdummy[3]={0,0,0};
// Tensor_num(Vector_Update_hrk_DIFF, h, ::DELTA_0, hrkdummy, params, dhrk // Tensor_num(Vector_Update_hrk_DIFF, h, ::DELTA_0, hrkdummy, params,
dh); // dhrkdh);
} }
else // IF kappa==0 or ndJ<=(::TOLERANCE_0) else // IF kappa==0 or ndJ<=(::TOLERANCE_0)
{ {
dhrkdh[0] = dhrkdh[4] = dhrkdh[8] = 1.; //xx //yy //zz dhrkdh[0] = dhrkdh[4] = dhrkdh[8] = 1.; // xx //yy //zz
dhrkdh[1] = dhrkdh[2] = dhrkdh[3] = dhrkdh[5] = dhrkdh[6] = dhrkdh[7] = 0. dhrkdh[1] = dhrkdh[2] = dhrkdh[3] = dhrkdh[5] = dhrkdh[6] = dhrkdh[7] =
; //xy //xz //yx //yz //zx //zy 0.; // xy //xz //yx //yz //zx //zy
} }
} }
else // IF Ih_hrkpI<=kappa : else // IF Ih_hrkpI<=kappa :
{ {
// should be zero always in practice but may induce convergence issue. // should be zero always in practice but may induce convergence issue.
double hrkdummy[3]={0,0,0}; double hrkdummy[3] = {0, 0, 0};
Tensor_num(Vector_Update_hrk_DIFF, h, ::DELTA_0, hrkdummy, params, dhrkdh); Tensor_num(Vector_Update_hrk_DIFF, h, ::DELTA_0, hrkdummy, params, dhrkdh);
} }
} }
void Tensor_dhrkdh_VPM_ana ( const double h[3], void Tensor_dhrkdh_VPM_ana(const double h[3], const double hrk[3], void *params,
const double hrk[3], double *dhrkdh)
void * params,
double *dhrkdh)
{ {
struct params_Cells_EB *p = (struct params_Cells_EB *) params; struct params_Cells_EB *p = (struct params_Cells_EB *)params;
double hrkp[3]; double hrkp[3];
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) hrkp[n] = p->Xp[n + 3 * p->idcell];
hrkp[n] = p->Xp[n+3*p->idcell];
double kappa = p->kappa[p->idcell]; double kappa = p->kappa[p->idcell];
double dhrk[3]; double dhrk[3];
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) dhrk[n] = h[n] - hrkp[n];
dhrk[n] = h[n]-hrkp[n];
double Ih_hrkpI = norm(dhrk); double Ih_hrkpI = norm(dhrk);
if (Ih_hrkpI>kappa) if(Ih_hrkpI > kappa) {
{ if(kappa > 0.) {
if (kappa>0.) dhrkdh[0] = (1 - kappa / Ih_hrkpI) +
{ (kappa / CUB(Ih_hrkpI)) * (dhrk[0] * dhrk[0]); // xx
dhrkdh[0] = (1-kappa/Ih_hrkpI) dhrkdh[4] = (1 - kappa / Ih_hrkpI) +
+ (kappa/CUB(Ih_hrkpI)) * (dhrk[0]*dhrk[0]) ; //xx (kappa / CUB(Ih_hrkpI)) * (dhrk[1] * dhrk[1]); // yy
dhrkdh[4] = (1-kappa/Ih_hrkpI) dhrkdh[1] = (kappa / CUB(Ih_hrkpI)) * (dhrk[1] * dhrk[0]); // xy
+ (kappa/CUB(Ih_hrkpI)) * (dhrk[1]*dhrk[1]) ; //yy dhrkdh[3] = dhrkdh[1]; // yx
dhrkdh[1] = (kappa/CUB(Ih_hrkpI)) * (dhrk[1]*dhrk[0]) ; //xy
dhrkdh[3] = dhrkdh[1]; //yx
switch(::FLAG_DIM) { switch(::FLAG_DIM) {
case 2: // 2D case case 2: // 2D case
dhrkdh[8] = 1.; dhrkdh[8] = 1.;
dhrkdh[2] = dhrkdh[5] = dhrkdh[6] = dhrkdh[7] = 0.; dhrkdh[2] = dhrkdh[5] = dhrkdh[6] = dhrkdh[7] = 0.;
break; break;
case 3: // 3D case case 3: // 3D case
dhrkdh[8] = (1-kappa/Ih_hrkpI) dhrkdh[8] = (1 - kappa / Ih_hrkpI) +
+ (kappa/CUB(Ih_hrkpI))*(dhrk[2]*dhrk[2]) ; //zz (kappa / CUB(Ih_hrkpI)) * (dhrk[2] * dhrk[2]); // zz
dhrkdh[2] = (kappa/CUB(Ih_hrkpI))*(dhrk[2]*dhrk[0]) ; //xz dhrkdh[2] = (kappa / CUB(Ih_hrkpI)) * (dhrk[2] * dhrk[0]); // xz
dhrkdh[6] = dhrkdh[2]; //zx dhrkdh[6] = dhrkdh[2]; // zx
dhrkdh[5] = (kappa/CUB(Ih_hrkpI))*(dhrk[2]*dhrk[1]) ; //yz dhrkdh[5] = (kappa / CUB(Ih_hrkpI)) * (dhrk[2] * dhrk[1]); // yz
dhrkdh[7] = dhrkdh[5]; //zy dhrkdh[7] = dhrkdh[5]; // zy
break; break;
default: default:
Message::Error("Invalid parameter (dimension = 2 or 3)" Message::Error("Invalid parameter (dimension = 2 or 3)"
"for function 'Tensor_dhrkdh_VPM_ana'. Analytic Jacobian computation "for function 'Tensor_dhrkdh_VPM_ana'. Analytic "
."); "Jacobian computation.");
break; break;
} }
} }
else // IF kappa==0 else // IF kappa==0
{ {
dhrkdh[0] = dhrkdh[4] = dhrkdh[8] = 1.; //xx //yy //zz dhrkdh[0] = dhrkdh[4] = dhrkdh[8] = 1.; // xx //yy //zz
dhrkdh[1] = dhrkdh[2] = dhrkdh[3] = dhrkdh[5] = dhrkdh[6] = dhrkdh[7] = 0. dhrkdh[1] = dhrkdh[2] = dhrkdh[3] = dhrkdh[5] = dhrkdh[6] = dhrkdh[7] =
; //xy //xz //yx //yz //zx //zy 0.; // xy //xz //yx //yz //zx //zy
} }
} }
else // IF Ih_hrkpI<=kappa : else // IF Ih_hrkpI<=kappa :
{ {
// should be zero always in practice but may induce convergence issue. // should be zero always in practice but may induce convergence issue.
double hrkdummy[3]={0,0,0}; double hrkdummy[3] = {0, 0, 0};
Tensor_num(Vector_Update_hrk_VPM, h, ::DELTA_0, hrkdummy, params, dhrkdh); Tensor_num(Vector_Update_hrk_VPM, h, ::DELTA_0, hrkdummy, params, dhrkdh);
} }
} }
void Tensor_dbdh_ana ( const double h[3], void Tensor_dbdh_ana(const double h[3], const double *Xk_all, void *params,
const double *Xk_all, double *dbdh)
void * params,
double *dbdh)
{ {
struct params_Cells_EB *p = (struct params_Cells_EB *)params;
struct params_Cells_EB *p = (struct params_Cells_EB *) params; int N = p->N;
int N = p->N ;
double hrtot[3], hrk[3]; double hrtot[3], hrk[3];
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) {
{ hrtot[n] = 0.;
hrtot[n]=0.; hrk[n] = 0.;
hrk[n]=0.; }
}
switch(::FLAG_SYM) {
switch(::FLAG_SYM) case 1:
{ dbdh[0] = dbdh[3] = dbdh[5] = ::SLOPE_FACTOR * MU0; // Slope forcing
case 1: dbdh[1] = dbdh[2] = dbdh[4] = 0.;
dbdh[0] = dbdh[3] = dbdh[5] = ::SLOPE_FACTOR*MU0 ; //Slope forcing break;
dbdh[1] = dbdh[2] = dbdh[4] = 0. ; case 0:
break; dbdh[0] = dbdh[4] = dbdh[8] = ::SLOPE_FACTOR * MU0; // Slope forcing
case 0: dbdh[1] = dbdh[2] = dbdh[3] = dbdh[5] = dbdh[6] = dbdh[7] = 0.;
dbdh[0] = dbdh[4] = dbdh[8] = ::SLOPE_FACTOR*MU0 ; //Slope forcing break;
dbdh[1] = dbdh[2] = dbdh[3] = dbdh[5] = dbdh[6] = dbdh[7] = 0. ; default:
break; Message::Error("Invalid parameter (sym = 0 or 1)"
default: "for function 'Tensor_dbdh_ana'.");
Message::Error("Invalid parameter (sym = 0 or 1)"
"for function 'Tensor_dbdh_ana'.");
break; break;
} }
int ncomp=::NCOMP; int ncomp = ::NCOMP;
double *dJkdh; dJkdh = new double[ncomp]; double *dJkdh;
double *dJtotdh; dJtotdh = new double[ncomp]; dJkdh = new double[ncomp];
for (int n=0; n<ncomp; n++) { double *dJtotdh;
dJkdh[n]=0.; dJtotdh = new double[ncomp];
dJtotdh[n]=0.; for(int n = 0; n < ncomp; n++) {
dJkdh[n] = 0.;
dJtotdh[n] = 0.;
} }
double mutgtot[6], mutg[6], dhrkdJk[6]; double mutgtot[6], mutg[6], dhrkdJk[6];
double dhrkdh[9], dhrtotdh[9]; double dhrkdh[9], dhrtotdh[9];
for (int n=0; n<9; n++) for(int n = 0; n < 9; n++) dhrtotdh[n] = 0.;
dhrtotdh[n]=0.;
double wk, Xk[3] ; double wk, Xk[3];
for (int k=0; k<N; k++) { for(int k = 0; k < N; k++) {
p->idcell = k; p->idcell = k;
wk = p->w[k]; wk = p->w[k];
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) Xk[n] = Xk_all[n + 3 * k];
Xk[n] = Xk_all[n+3*k]; switch(::FLAG_HOMO) {
switch(::FLAG_HOMO) case 0: {
{ switch(::FLAG_APPROACH) {
case 0: case 1: // Variationnal Case
{ Tensor_dJkdh_VAR(h, Xk, params, dJkdh);
switch(::FLAG_APPROACH) { break;
case 1: // Variationnal Case case 2: // Differential Case
Tensor_dJkdh_VAR(h, Xk, params, dJkdh); case 3: Tensor_dJkdh_VPMorDIFF(h, Xk, params, dJkdh); break;
break; default:
case 2: // Differential Case Message::Error(
case 3: "Invalid parameter (FLAG_APPROACH = 1,2 or 3) for function "
Tensor_dJkdh_VPMorDIFF(h, Xk, params, dJkdh); "'Tensor_dbdh_ana'.\n"
break; "FLAG_APPROACH = 1 --> Variational Approach\n"
default: "FLAG_APPROACH = 2 --> Vector Play Model approach\n"
Message::Error("Invalid parameter (FLAG_APPROACH = 1,2 or 3) for fun "FLAG_APPROACH = 3 --> Full Differential Approach (gsl)");
ction 'Tensor_dbdh_ana'.\n" break;
"FLAG_APPROACH = 1 --> Variational Approach\n"
"FLAG_APPROACH = 2 --> Vector Play Model approach\n"
"FLAG_APPROACH = 3 --> Full Differential Approach (gsl
)");
break;
}
for (int n=0; n<ncomp; n++)
dbdh[n] += dJkdh[n] ;
} }
break; for(int n = 0; n < ncomp; n++) dbdh[n] += dJkdh[n];
case 1: } break;
{ case 1: {
switch(::FLAG_APPROACH) { switch(::FLAG_APPROACH) {
case 1: // Variationnal Case case 1: // Variationnal Case
// Find hrk // Find hrk
Vector_hrk_From_Jk(Xk,params, hrk); Vector_hrk_From_Jk(Xk, params, hrk);
// hrtot = sum wk hrk // hrtot = sum wk hrk
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) hrtot[n] += wk * hrk[n];
hrtot[n] += wk*hrk[n];
// Build dhrkdh
// Build dhrkdh Tensor_dJkdh_VAR(h, Xk, params, dJkdh);
Tensor_dJkdh_VAR(h, Xk, params, dJkdh); Tensor_dJkdhrk(hrk, params, mutg);
Tensor_dJkdhrk(hrk , params, mutg); Inv_TensorSym3x3(mutg, dhrkdJk);
Inv_TensorSym3x3(mutg, dhrkdJk); Mul_TensorSymTensorNonSym(dhrkdJk, dJkdh, dhrkdh);
Mul_TensorSymTensorNonSym(dhrkdJk, dJkdh, dhrkdh);
// dhrtotdh = sum wk * dhrkdh
//dhrtotdh = sum wk * dhrkdh for(int n = 0; n < 9; n++) dhrtotdh[n] += wk * dhrkdh[n];
for (int n=0; n<9; n++)
dhrtotdh[n] += wk*dhrkdh[n]; break;
case 2: // Differential Case
case 3: {
// hrtot = sum wk hrk
for(int n = 0; n < 3; n++) hrtot[n] += wk * Xk[n];
// Build dhrkdh
// -> dhrkdh is symmetric in that case but still stored with non-syn
switch(::FLAG_APPROACH) {
case 2: // VPM
Tensor_dhrkdh_VPM_ana(h, Xk, params, dhrkdh);
break; break;
case 2: // Differential Case case 3: // FULL DIFF
case 3: Tensor_dJkdhrk(Xk, params, mutg);
{ Tensor_dhrkdh_DIFF_ana(h, Xk, mutg, params, dhrkdh);
// hrtot = sum wk hrk
for (int n=0; n<3; n++)
hrtot[n] += wk*Xk[n];
// Build dhrkdh
// -> dhrkdh is symmetric in that case but still stored with non-syn
switch(::FLAG_APPROACH)
{
case 2: // VPM
Tensor_dhrkdh_VPM_ana(h, Xk, params, dhrkdh);
break;
case 3: // FULL DIFF
Tensor_dJkdhrk(Xk, params, mutg);
Tensor_dhrkdh_DIFF_ana(h,Xk,mutg,params,dhrkdh);
break;
}
//dhrtotdh = sum wk * dhrkdh
for (int n=0; n<9; n++)
dhrtotdh[n] += wk*dhrkdh[n];
}
break;
default:
Message::Error("Invalid parameter (FLAG_APPROACH = 1,2 or 3) for fun
ction 'Tensor_dbdh_ana'.\n"
"FLAG_APPROACH = 1 --> Variational Approach\n"
"FLAG_APPROACH = 2 --> Vector Play Model approach\n"
"FLAG_APPROACH = 3 --> Full Differential Approach (gsl
)");
break; break;
} }
}
break; // dhrtotdh = sum wk * dhrkdh
for(int n = 0; n < 9; n++) dhrtotdh[n] += wk * dhrkdh[n];
} break;
default: default:
Message::Error("Flag_Homo not defined (1 or 0)" Message::Error(
"for function 'Tensor_dbdh_ana'."); "Invalid parameter (FLAG_APPROACH = 1,2 or 3) for function "
"'Tensor_dbdh_ana'.\n"
"FLAG_APPROACH = 1 --> Variational Approach\n"
"FLAG_APPROACH = 2 --> Vector Play Model approach\n"
"FLAG_APPROACH = 3 --> Full Differential Approach (gsl)");
break;
}
} break;
default:
Message::Error("Flag_Homo not defined (1 or 0)"
"for function 'Tensor_dbdh_ana'.");
break; break;
} }
} }
if (::FLAG_HOMO==1) if(::FLAG_HOMO == 1) {
{ // Build mutgtot
//Build mutgtot int old = p->idcell;
p->idcell=-1; // due to the need to take global Ja, Jb (not Jak=wk*Ja, Jbk=w p->idcell =
k*Jb) ! -1; // due to the need to take global Ja, Jb (not Jak=wk*Ja, Jbk=wk*Jb) !
Tensor_dJkdhrk(hrtot,params, mutgtot) ; Tensor_dJkdhrk(hrtot, params, mutgtot);
p->idcell = old;
//dJtotdh= mutgtot*dhrtotdh // dJtotdh= mutgtot*dhrtotdh
Mul_TensorSymTensorNonSym(mutgtot,dhrtotdh, dJtotdh) ; Mul_TensorSymTensorNonSym(mutgtot, dhrtotdh, dJtotdh);
//dbdh= dbdh+dJtotdh // dbdh= dbdh+dJtotdh
for (int n=0; n<9; n++) for(int n = 0; n < 9; n++) dbdh[n] += dJtotdh[n];
dbdh[n] += dJtotdh[n];
} }
delete [] dJkdh; delete[] dJkdh;
delete [] dJtotdh; delete[] dJtotdh;
} }
void Tensor_num ( void (*f) (const double*, double*, double*, void *), void Tensor_num(void (*f)(const double *, double *, double *, void *),
const double x[3], const double x[3], const double delta0, double *Xk_all,
const double delta0, void *params, double *dfdx)
double *Xk_all,
void * params,
double *dfdx)
{ {
// int dim = D->Case.Interpolation.x[0] ;
//int dim = D->Case.Interpolation.x[0] ; // double delta0 = ::DELTA_0 ;
// Different following the different directions ??? TO CHECK
//double delta0 = ::DELTA_0 ;
// Different following the different directions ??? TO CHECK
/* /*
double EPSILON = 1 ; // PARAM (1) // 1e-8 // Take this again because Test_Bas double EPSILON = 1 ; // PARAM (1) // 1e-8 // Take this again because
ic_SimpleDiff_Num not working otherwise Test_Basic_SimpleDiff_Num not working otherwise double delta[3] = {
double delta[3] = { (fabs(h[0])>EPSILON) ? (fabs(h[0])) * delta0 : delta0, (fabs(h[0])>EPSILON) ? (fabs(h[0])) * delta0 : delta0, (fabs(h[1])>EPSILON) ?
(fabs(h[1])>EPSILON) ? (fabs(h[1])) * delta0 : delta0, (fabs(h[1])) * delta0 : delta0, (fabs(h[2])>EPSILON) ? (fabs(h[2])) * delta0 :
(fabs(h[2])>EPSILON) ? (fabs(h[2])) * delta0 : delta0 } ; delta0 } ;
//*/ //*/
/* /*
double delta[3] = {((norm(h)>EPSILON) ? (norm(h)+1) * delta0 : delta0), double delta[3] = {((norm(h)>EPSILON) ? (norm(h)+1) * delta0 : delta0),
((norm(h)>EPSILON) ? (norm(h)+1) * delta0 : delta0), ((norm(h)>EPSILON) ? (norm(h)+1) * delta0 : delta0),
((norm(h)>EPSILON) ? (norm(h)+1) * delta0 : delta0) } ; ((norm(h)>EPSILON) ? (norm(h)+1) * delta0 : delta0) } ;
*/ */
/* /*
double delta[3] = {((norm(h)>EPSILON) ? norm(h) * delta0 : delta0), double delta[3] = {((norm(h)>EPSILON) ? norm(h) * delta0 : delta0),
((norm(h)>EPSILON) ? norm(h) * delta0 : delta0), ((norm(h)>EPSILON) ? norm(h) * delta0 : delta0),
((norm(h)>EPSILON) ? norm(h) * delta0 : delta0) } ; ((norm(h)>EPSILON) ? norm(h) * delta0 : delta0) } ;
*/ */
double delta[3]={delta0,delta0,delta0}; double delta[3] = {delta0, delta0, delta0};
double fxr[3]={0.,0.,0.}; double fxr[3] = {0., 0., 0.};
double fxl[3]={0.,0.,0.}; double fxl[3] = {0., 0., 0.};
double fyr[3]={0.,0.,0.}; double fyr[3] = {0., 0., 0.};
double fyl[3]={0.,0.,0.}; double fyl[3] = {0., 0., 0.};
double fzr[3]={0.,0.,0.}; double fzr[3] = {0., 0., 0.};
double fzl[3]={0.,0.,0.}; double fzl[3] = {0., 0., 0.};
double xxr[3]={x[0]+delta[0], x[1] ,x[2]}; double xxr[3] = {x[0] + delta[0], x[1], x[2]};
double xyr[3]={x[0], x[1]+delta[1] ,x[2]}; double xyr[3] = {x[0], x[1] + delta[1], x[2]};
double xzr[3]={x[0], x[1] ,x[2]+delta[2]}; double xzr[3] = {x[0], x[1], x[2] + delta[2]};
f(xxr, fxr, Xk_all, params ); f(xxr, fxr, Xk_all, params);
f(xyr, fyr, Xk_all, params); f(xyr, fyr, Xk_all, params);
double xxl[3],xyl[3],xzl[3]; double xxl[3], xyl[3], xzl[3];
for (int n=0; n<3; n++) {xxl[n]=x[n]; xyl[n]=x[n]; xzl[n]=x[n];} for(int n = 0; n < 3; n++) {
switch(::FLAG_CENTRAL_DIFF) xxl[n] = x[n];
{ xyl[n] = x[n];
case 1: // Central Differences xzl[n] = x[n];
xxl[0]=x[0]-delta[0]; }
xyl[1]=x[1]-delta[1]; switch(::FLAG_CENTRAL_DIFF) {
xzl[2]=x[2]-delta[2]; case 1: // Central Differences
f(xxl, fxl, Xk_all, params); xxl[0] = x[0] - delta[0];
f(xyl, fyl, Xk_all, params); xyl[1] = x[1] - delta[1];
break; xzl[2] = x[2] - delta[2];
case 0: // Forward Differences f(xxl, fxl, Xk_all, params);
f(x, fxl, Xk_all, params ); f(xyl, fyl, Xk_all, params);
for (int n=0; n<3; n++) fyl[n] = fxl[n] ; break;
break; case 0: // Forward Differences
default: f(x, fxl, Xk_all, params);
Message::Error("Invalid parameter (central diff = 0 or 1)" for(int n = 0; n < 3; n++) fyl[n] = fxl[n];
"for function 'Tensor_num'."); break;
default:
Message::Error("Invalid parameter (central diff = 0 or 1)"
"for function 'Tensor_num'.");
break; break;
} }
dfdx[0]= (fxr[0]-fxl[0])/(xxr[0]-xxl[0]); //xx dfdx[0] = (fxr[0] - fxl[0]) / (xxr[0] - xxl[0]); // xx
//dfdx[1]= (fxr[1]-fxl[1])/(xxr[0]-xxl[0]);//yx // This one was used originall // dfdx[1]= (fxr[1]-fxl[1])/(xxr[0]-xxl[0]);//yx // This one was used
y // originally
dfdx[1]= (fyr[0]-fyl[0])/(xyr[1]-xyl[1]); //xy // other possibility (more nat dfdx[1] = (fyr[0] - fyl[0]) /
ural) (xyr[1] - xyl[1]); // xy // other possibility (more natural)
// ------ // ------
switch(::FLAG_SYM) switch(::FLAG_SYM) {
{ case 1: // Symmetric tensor
case 1:// Symmetric tensor dfdx[3] = (fyr[1] - fyl[1]) / (xyr[1] - xyl[1]); // yy
dfdx[3]= (fyr[1]-fyl[1])/(xyr[1]-xyl[1]); //yy switch(::FLAG_DIM) {
switch(::FLAG_DIM) case 2: // 2D case
{ dfdx[5] = 1.; // zz
case 2: // 2D case dfdx[2] = dfdx[4] = 0.; // xz // yz
dfdx[5] = 1.; //zz break;
dfdx[2] = dfdx[4]= 0.; //xz // yz case 3: // 3D case
break; f(xzr, fzr, Xk_all, params);
case 3: // 3D case switch(::FLAG_CENTRAL_DIFF) {
f(xzr, fzr, Xk_all, params); case 1: // Central Differences
switch(::FLAG_CENTRAL_DIFF) f(xzl, fzl, Xk_all, params);
{
case 1: // Central Differences
f(xzl, fzl, Xk_all, params);
break;
case 0: // Forward Differences
for (int n=0; n<3; n++) fzl[n] = fxl[n] ;
break;
default:
Message::Error("Invalid parameter (central diff = 0 or 1)"
"for function 'Tensor_num'.");
break;
}
dfdx[5]= (fzr[2]-fzl[2])/(xzr[2]-xzl[2]); //zz
//dfdx[2]= (fxr[2]-fxl[2])/(xxr[0]-xxl[0]); //zx // This one was used
originally
dfdx[2]= (fzr[0]-fzl[0])/(xzr[2]-xzl[2]); //xz //other possibility (mo
re natural)
//dfdx[4]= (fyr[2]-fyl[2])/(xyr[1]-xyl[1]); //zy // This one was used
originally
dfdx[4]= (fzr[1]-fzl[1])/(xzr[2]-xzl[2]); //yz //other possibility (mo
re natural)
break; break;
default: case 0: // Forward Differences
Message::Error("Invalid parameter (dimension = 2 or 3)" for(int n = 0; n < 3; n++) fzl[n] = fxl[n];
"for function 'Tensor_num'."); break;
default:
Message::Error("Invalid parameter (central diff = 0 or 1)"
"for function 'Tensor_num'.");
break; break;
} }
dfdx[5] = (fzr[2] - fzl[2]) / (xzr[2] - xzl[2]); // zz
// dfdx[2]= (fxr[2]-fxl[2])/(xxr[0]-xxl[0]); //zx // This one was used
// originally
dfdx[2] = (fzr[0] - fzl[0]) /
(xzr[2] - xzl[2]); // xz //other possibility (more natural)
// dfdx[4]= (fyr[2]-fyl[2])/(xyr[1]-xyl[1]); //zy // This one was used
// originally
dfdx[4] = (fzr[1] - fzl[1]) /
(xzr[2] - xzl[2]); // yz //other possibility (more natural)
break;
default:
Message::Error("Invalid parameter (dimension = 2 or 3)"
"for function 'Tensor_num'.");
break;
}
break; break;
case 0:// Non Symmetric tensor case 0: // Non Symmetric tensor
dfdx[3]= (fxr[1]-fxl[1])/(xxr[0]-xxl[0]); //yx dfdx[3] = (fxr[1] - fxl[1]) / (xxr[0] - xxl[0]); // yx
dfdx[4]= (fyr[1]-fyl[1])/(xyr[1]-xyl[1]); //yy dfdx[4] = (fyr[1] - fyl[1]) / (xyr[1] - xyl[1]); // yy
switch(::FLAG_DIM) switch(::FLAG_DIM) {
{ case 2: // 2D case
case 2: // 2D case dfdx[8] = 1.; // zz
dfdx[8] = 1.; //zz dfdx[2] = dfdx[5] = dfdx[6] = dfdx[7] = 0.; // xz //yz //zx //zy
dfdx[2] = dfdx[5] = dfdx[6] = dfdx[7] = 0.; //xz //yz //zx //zy break;
break; case 3: // 3D case
case 3: // 3D case f(xzr, fzr, Xk_all, params);
f(xzr, fzr, Xk_all, params ); switch(::FLAG_CENTRAL_DIFF) {
switch(::FLAG_CENTRAL_DIFF) case 1: // Central Differences
{ f(xzl, fzl, Xk_all, params);
case 1: // Central Differences
f(xzl, fzl , Xk_all, params );
break;
case 0: // Forward Differences
for (int n=0; n<3; n++) fzl[n] = fxl[n] ;
break;
default:
Message::Error("Invalid parameter (central diff = 0 or 1)"
"for function 'Tensor_num'.");
break;
}
dfdx[8] = (fzr[2]-fzl[2])/(xzr[2]-xzl[2]);//zz
dfdx[2] = (fzr[0]-fzl[0])/(xzr[2]-xzl[2]);//xz
dfdx[5] = (fzr[1]-fzl[1])/(xzr[2]-xzl[2]);//yz
dfdx[6] = (fxr[2]-fxl[2])/(xxr[0]-xxl[0]); //zx
dfdx[7] = (fyr[2]-fyl[2])/(xyr[1]-xyl[1]); //zy
break; break;
default: case 0: // Forward Differences
Message::Error("Invalid parameter (dimension = 2 or 3)" for(int n = 0; n < 3; n++) fzl[n] = fxl[n];
"for function 'Tensor_num'."); break;
default:
Message::Error("Invalid parameter (central diff = 0 or 1)"
"for function 'Tensor_num'.");
break; break;
} }
break; dfdx[8] = (fzr[2] - fzl[2]) / (xzr[2] - xzl[2]); // zz
dfdx[2] = (fzr[0] - fzl[0]) / (xzr[2] - xzl[2]); // xz
dfdx[5] = (fzr[1] - fzl[1]) / (xzr[2] - xzl[2]); // yz
dfdx[6] = (fxr[2] - fxl[2]) / (xxr[0] - xxl[0]); // zx
dfdx[7] = (fyr[2] - fyl[2]) / (xyr[1] - xyl[1]); // zy
break;
default: default:
Message::Error("Invalid parameter (sym = 0 or 1)" Message::Error("Invalid parameter (dimension = 2 or 3)"
"for function 'Tensor_num'."); "for function 'Tensor_num'.");
break;
}
break;
default:
Message::Error("Invalid parameter (sym = 0 or 1)"
"for function 'Tensor_num'.");
break; break;
} }
} }
void Tensor_dhdb_GoodBFGS(const double dx[3],const double df[3], double *dhdb) void Tensor_dhdb_GoodBFGS(const double dx[3], const double df[3], double *dhdb)
{ {
double iJn_1df[3], dfiJn_1[3]; double iJn_1df[3], dfiJn_1[3];
double dxdf, dfiJn_1df ; double dxdf, dfiJn_1df;
///* New: Deal with Symmetrical or Asymmetrical Tensor consideration (13/06/20 ///* New: Deal with Symmetrical or Asymmetrical Tensor consideration
16)------------- ///(13/06/2016)-------------
Mul_TensorVec(dhdb,df, iJn_1df, 0); Mul_TensorVec(dhdb, df, iJn_1df, 0);
Mul_TensorVec(dhdb,df, dfiJn_1, 1); Mul_TensorVec(dhdb, df, dfiJn_1, 1);
dxdf=Mul_VecVec(dx,df); dxdf = Mul_VecVec(dx, df);
dfiJn_1df=Mul_VecVec(df,iJn_1df); dfiJn_1df = Mul_VecVec(df, iJn_1df);
switch(::FLAG_SYM) switch(::FLAG_SYM) {
{ case 1: // Symmetric tensor
case 1: // Symmetric tensor dhdb[0] = dhdb[0] + ((dxdf + dfiJn_1df) / (SQU(dxdf))) * (dx[0] * dx[0]) -
dhdb[0] = dhdb[0]+ ((dxdf + dfiJn_1df)/(SQU(dxdf)))*(dx[0]*dx[0]) - ( iJn (iJn_1df[0] * dx[0] + dx[0] * dfiJn_1[0]) / dxdf; // xx
_1df[0]*dx[0] + dx[0]*dfiJn_1[0] )/dxdf ; //xx dhdb[3] = dhdb[3] + ((dxdf + dfiJn_1df) / (SQU(dxdf))) * (dx[1] * dx[1]) -
dhdb[3] = dhdb[3]+ ((dxdf + dfiJn_1df)/(SQU(dxdf)))*(dx[1]*dx[1]) - ( iJn (iJn_1df[1] * dx[1] + dx[1] * dfiJn_1[1]) / dxdf; // yy
_1df[1]*dx[1] + dx[1]*dfiJn_1[1] )/dxdf ; //yy dhdb[1] = dhdb[1] + ((dxdf + dfiJn_1df) / (SQU(dxdf))) * (dx[0] * dx[1]) -
dhdb[1] = dhdb[1]+ ((dxdf + dfiJn_1df)/(SQU(dxdf)))*(dx[0]*dx[1]) - ( iJn (iJn_1df[0] * dx[1] + dx[0] * dfiJn_1[1]) / dxdf; // xy
_1df[0]*dx[1] + dx[0]*dfiJn_1[1] )/dxdf ; //xy switch(::FLAG_DIM) {
switch(::FLAG_DIM) case 2: // 2D case
{ dhdb[5] = 1.; // zz
case 2: // 2D case dhdb[2] = dhdb[4] = 0.; // xz //yz
dhdb[5] = 1.; //zz break;
dhdb[2] = dhdb[4] = 0.; //xz //yz case 3: // 3D case
break; dhdb[5] = dhdb[5] + ((dxdf + dfiJn_1df) / (SQU(dxdf))) * (dx[2] * dx[2]) -
case 3: // 3D case (iJn_1df[2] * dx[2] + dx[2] * dfiJn_1[2]) / dxdf; // zz
dhdb[5] = dhdb[5]+ ((dxdf + dfiJn_1df)/(SQU(dxdf)))*(dx[2]*dx[2]) - ( dhdb[2] = dhdb[2] + ((dxdf + dfiJn_1df) / (SQU(dxdf))) * (dx[0] * dx[2]) -
iJn_1df[2]*dx[2] + dx[2]*dfiJn_1[2] )/dxdf ; //zz (iJn_1df[0] * dx[2] + dx[0] * dfiJn_1[2]) / dxdf; // xz
dhdb[2] = dhdb[2]+ ((dxdf + dfiJn_1df)/(SQU(dxdf)))*(dx[0]*dx[2]) - ( dhdb[4] = dhdb[4] + ((dxdf + dfiJn_1df) / (SQU(dxdf))) * (dx[1] * dx[2]) -
iJn_1df[0]*dx[2] + dx[0]*dfiJn_1[2] )/dxdf ; //xz (iJn_1df[1] * dx[2] + dx[1] * dfiJn_1[2]) / dxdf; // yz
dhdb[4] = dhdb[4]+ ((dxdf + dfiJn_1df)/(SQU(dxdf)))*(dx[1]*dx[2]) - ( break;
iJn_1df[1]*dx[2] + dx[1]*dfiJn_1[2] )/dxdf ; //yz default:
break; Message::Error("Invalid parameter (dimension = 2 or 3)"
default: "for function 'Tensor_dhdb_GoodBFGS'.");
Message::Error("Invalid parameter (dimension = 2 or 3)" break;
"for function 'Tensor_dhdb_GoodBFGS'."); }
break;
}
break;
case 0: // Non Symmetric tensor
dhdb[0] = dhdb[0]+ ((dxdf + dfiJn_1df)/(SQU(dxdf)))*(dx[0]*dx[0]) - ( iJn
_1df[0]*dx[0] + dx[0]*dfiJn_1[0] )/dxdf ; //xx
dhdb[4] = dhdb[4]+ ((dxdf + dfiJn_1df)/(SQU(dxdf)))*(dx[1]*dx[1]) - ( iJn
_1df[1]*dx[1] + dx[1]*dfiJn_1[1] )/dxdf ; //yy
dhdb[1] = dhdb[1]+ ((dxdf + dfiJn_1df)/(SQU(dxdf)))*(dx[0]*dx[1]) - ( iJn
_1df[0]*dx[1] + dx[0]*dfiJn_1[1] )/dxdf ; //xy
dhdb[3] = dhdb[3]+ ((dxdf + dfiJn_1df)/(SQU(dxdf)))*(dx[1]*dx[0]) - ( iJn
_1df[1]*dx[0] + dx[1]*dfiJn_1[0] )/dxdf ; //yx
switch(::FLAG_DIM)
{
case 2: // 2D case
dhdb[8] = 1.; //zz
dhdb[2] = dhdb[5] = dhdb[6] = dhdb[7] = 0.; //xz //yz //zx //zy
break;
case 3: // 3D case
dhdb[8] = dhdb[8]+ ((dxdf + dfiJn_1df)/(SQU(dxdf)))*(dx[2]*dx[2]) - (
iJn_1df[2]*dx[2] + dx[2]*dfiJn_1[2] )/dxdf ; //zz
dhdb[2] = dhdb[2]+ ((dxdf + dfiJn_1df)/(SQU(dxdf)))*(dx[0]*dx[2]) - (
iJn_1df[0]*dx[2] + dx[0]*dfiJn_1[2] )/dxdf ; //xz
dhdb[5] = dhdb[5]+ ((dxdf + dfiJn_1df)/(SQU(dxdf)))*(dx[1]*dx[2]) - (
iJn_1df[1]*dx[2] + dx[1]*dfiJn_1[2] )/dxdf ; //yz
dhdb[6] = dhdb[6]+ ((dxdf + dfiJn_1df)/(SQU(dxdf)))*(dx[2]*dx[0]) - (
iJn_1df[2]*dx[0] + dx[2]*dfiJn_1[0] )/dxdf ; //zx
dhdb[7] = dhdb[7]+ ((dxdf + dfiJn_1df)/(SQU(dxdf)))*(dx[2]*dx[1]) - (
iJn_1df[2]*dx[1] + dx[2]*dfiJn_1[1] )/dxdf ; //zy
break;
default:
Message::Error("Invalid parameter (dimension = 2 or 3)"
"for function 'Tensor_dhdb_GoodBFGS'.");
break;
}
break; break;
case 0: // Non Symmetric tensor
dhdb[0] = dhdb[0] + ((dxdf + dfiJn_1df) / (SQU(dxdf))) * (dx[0] * dx[0]) -
(iJn_1df[0] * dx[0] + dx[0] * dfiJn_1[0]) / dxdf; // xx
dhdb[4] = dhdb[4] + ((dxdf + dfiJn_1df) / (SQU(dxdf))) * (dx[1] * dx[1]) -
(iJn_1df[1] * dx[1] + dx[1] * dfiJn_1[1]) / dxdf; // yy
dhdb[1] = dhdb[1] + ((dxdf + dfiJn_1df) / (SQU(dxdf))) * (dx[0] * dx[1]) -
(iJn_1df[0] * dx[1] + dx[0] * dfiJn_1[1]) / dxdf; // xy
dhdb[3] = dhdb[3] + ((dxdf + dfiJn_1df) / (SQU(dxdf))) * (dx[1] * dx[0]) -
(iJn_1df[1] * dx[0] + dx[1] * dfiJn_1[0]) / dxdf; // yx
switch(::FLAG_DIM) {
case 2: // 2D case
dhdb[8] = 1.; // zz
dhdb[2] = dhdb[5] = dhdb[6] = dhdb[7] = 0.; // xz //yz //zx //zy
break;
case 3: // 3D case
dhdb[8] = dhdb[8] + ((dxdf + dfiJn_1df) / (SQU(dxdf))) * (dx[2] * dx[2]) -
(iJn_1df[2] * dx[2] + dx[2] * dfiJn_1[2]) / dxdf; // zz
dhdb[2] = dhdb[2] + ((dxdf + dfiJn_1df) / (SQU(dxdf))) * (dx[0] * dx[2]) -
(iJn_1df[0] * dx[2] + dx[0] * dfiJn_1[2]) / dxdf; // xz
dhdb[5] = dhdb[5] + ((dxdf + dfiJn_1df) / (SQU(dxdf))) * (dx[1] * dx[2]) -
(iJn_1df[1] * dx[2] + dx[1] * dfiJn_1[2]) / dxdf; // yz
dhdb[6] = dhdb[6] + ((dxdf + dfiJn_1df) / (SQU(dxdf))) * (dx[2] * dx[0]) -
(iJn_1df[2] * dx[0] + dx[2] * dfiJn_1[0]) / dxdf; // zx
dhdb[7] = dhdb[7] + ((dxdf + dfiJn_1df) / (SQU(dxdf))) * (dx[2] * dx[1]) -
(iJn_1df[2] * dx[1] + dx[2] * dfiJn_1[1]) / dxdf; // zy
break;
default: default:
Message::Error("Invalid parameter (sym = 0 or 1)" Message::Error("Invalid parameter (dimension = 2 or 3)"
"for function 'Tensor_dhdb_GoodBFGS'."); "for function 'Tensor_dhdb_GoodBFGS'.");
break;
}
break;
default:
Message::Error("Invalid parameter (sym = 0 or 1)"
"for function 'Tensor_dhdb_GoodBFGS'.");
break; break;
} }
//*///------------------------------------------------------------------------ ------------------- //*///------------------------------------------------------------------------ -------------------
} }
//*///-------------------------------------------------------------------------- ----------------- //*///-------------------------------------------------------------------------- -----------------
//************************************************ //************************************************
// Functions usable in a .pro file // Functions usable in a .pro file
//************************************************ //************************************************
void F_Cell_EB(F_ARG) { void F_Cell_EB(F_ARG)
{
// Updating the Cell variable : Jk (for variationnal approach) or hrk (for dif // Updating the Cell variable : Jk (for variationnal approach) or hrk (for
ferential approach) // differential approach)
// --------------------------------------------- // ---------------------------------------------
// input: // input:
// (A+0)->Val = number corresponding to the cell studied -- k // (A+0)->Val = number corresponding to the cell studied -- k
// (A+1)->Val = magnetic field -- h // (A+1)->Val = magnetic field -- h
// (A+2)->Val = material magnetization (var) or reversible magnetic field (dif // (A+2)->Val = material magnetization (var) or reversible magnetic field
f) at previous time step -- xkp // (diff) at previous time step -- xkp Material parameters: e.g.
// Material parameters: e.g. param_EnergHyst = { dim, N, Ja, ha, w_1, kappa_1, // param_EnergHyst = { dim, N, Ja, ha, w_1, kappa_1, ..., w_N, kappa_N};==>
..., w_N, kappa_N};==> struct FunctionActive *D // struct FunctionActive *D
// --------------------------------------------- // ---------------------------------------------
// output: updated Jk // output: updated Jk
struct FunctionActive * D ; struct FunctionActive *D;
if (!Fct->Active) Fi_InitListX (Fct, A, V) ; if(!Fct->Active) Fi_InitListX(Fct, A, V);
D = Fct->Active ; D = Fct->Active;
set_sensi_param(D); set_sensi_param(D);
if( (A+0)->Type != SCALAR || if((A + 0)->Type != SCALAR || (A + 1)->Type != VECTOR ||
(A+1)->Type != VECTOR || (A + 2)->Type != VECTOR)
(A+2)->Type != VECTOR )
Message::Error("Function 'Cell_EB' requires one scalar argument (n)" Message::Error("Function 'Cell_EB' requires one scalar argument (n)"
"and two vector arguments (h, Jkp)"); "and two vector arguments (h, Jkp)");
///* //Init Creation of EB parameters structure ///* //Init Creation of EB parameters structure
struct params_Cells_EB params; struct params_Cells_EB params;
params.idcell = ((A+0)->Val[0])-1; params.idcell = ((A + 0)->Val[0]) - 1;
params.N = D->Case.Interpolation.x[1] ; params.N = D->Case.Interpolation.x[1];
params.Ja= D->Case.Interpolation.x[2] ; params.Ja = D->Case.Interpolation.x[2];
params.ha= D->Case.Interpolation.x[3] ; params.ha = D->Case.Interpolation.x[3];
params.Jb= D->Case.Interpolation.x[4] ; params.Jb = D->Case.Interpolation.x[4];
params.hb= D->Case.Interpolation.x[5] ; params.hb = D->Case.Interpolation.x[5];
params.kappa=new double[params.N]; params.kappa = new double[params.N];
params.w=new double[params.N]; params.w = new double[params.N];
params.w[params.idcell] = D->Case.Interpolation.x[6+2*params.idcell]; params.w[params.idcell] = D->Case.Interpolation.x[6 + 2 * params.idcell];
params.kappa[params.idcell] = D->Case.Interpolation.x[7+2*params.idcell]; params.kappa[params.idcell] = D->Case.Interpolation.x[7 + 2 * params.idcell];
double h[3]; double h[3];
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) h[n] = (A + 1)->Val[n];
h[n] = (A+1)->Val[n];
params.Xp=new double[3*params.N]; params.Xp = new double[3 * params.N];
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) params.Xp[n + 3 * params.idcell] = (A + 2)->Val[n];
params.Xp[n+3*params.idcell] = (A+2)->Val[n];
//End Creation of EB parameters structure // End Creation of EB parameters structure
double Xk[3]; double Xk[3];
switch(::FLAG_APPROACH) switch(::FLAG_APPROACH) {
{ case 1: // Variationnal Case
case 1: // Variationnal Case Vector_Update_Jk_VAR(h, Xk, Xk, &params);
Vector_Update_Jk_VAR(h,Xk,Xk,&params);
break; break;
case 2: // Vector Play Model Case case 2: // Vector Play Model Case
Vector_Update_hrk_VPM(h,Xk,Xk,&params); Vector_Update_hrk_VPM(h, Xk, Xk, &params);
break; break;
case 3: // Full Differential Case case 3: // Full Differential Case
Vector_Update_hrk_DIFF(h,Xk,Xk,&params); Vector_Update_hrk_DIFF(h, Xk, Xk, &params);
break; break;
default: default:
Message::Error("Invalid parameter (FLAG_APPROACH = 1,2 or 3) for function Message::Error("Invalid parameter (FLAG_APPROACH = 1,2 or 3) for function "
'Update_Cell'.\n" "'Update_Cell'.\n"
"FLAG_APPROACH = 1 --> Variational Approach\n" "FLAG_APPROACH = 1 --> Variational Approach\n"
"FLAG_APPROACH = 2 --> Vector Play Model approach\n" "FLAG_APPROACH = 2 --> Vector Play Model approach\n"
"FLAG_APPROACH = 3 --> Full Differential Approach (gsl)"); "FLAG_APPROACH = 3 --> Full Differential Approach (gsl)");
break; break;
} }
V->Type = VECTOR ; V->Type = VECTOR;
for (int n=0 ; n<3 ; n++) V->Val[n] = Xk[n]; for(int n = 0; n < 3; n++) V->Val[n] = Xk[n];
} }
void F_h_EB(F_ARG) void F_h_EB(F_ARG)
{ {
// #define F_ARG struct Function * Fct, struct Value * A, struct Value * V // #define F_ARG struct Function * Fct, struct Value * A, struct Value * V
// input : // input :
// (A+0) ->Val = last computed magnetic field (for example at previous time // (A+0) ->Val = last computed magnetic field (for example at previous time
step -- hp) // usefull for initialization // step -- hp) // usefull for initialization (A+1) ->Val = magnetic
// (A+1) ->Val = magnetic induction -- b // induction -- b (A+2+1*k)->Val = material magnetization at previous time
// (A+2+1*k)->Val = material magnetization at previous time step -- Jkp // step -- Jkp Material parameters: e.g. param_EnergHyst = { dim, N, Ja, ha,
// Material parameters: e.g. param_EnergHyst = { dim, N, Ja, ha, w_1, kappa_1, // w_1, kappa_1, ..., w_N, kappa_N};==> struct FunctionActive *D
..., w_N, kappa_N};==> struct FunctionActive *D
// --------------------------------------------- // ---------------------------------------------
// output: magnetic field -- h // output: magnetic field -- h
struct FunctionActive * D ; struct FunctionActive *D;
if (!Fct->Active) Fi_InitListX (Fct, A, V) ; if(!Fct->Active) Fi_InitListX(Fct, A, V);
D = Fct->Active ; D = Fct->Active;
set_sensi_param(D); set_sensi_param(D);
///* //Init Creation of EB parameters structure ///* //Init Creation of EB parameters structure
struct params_Cells_EB params; struct params_Cells_EB params;
params.N = D->Case.Interpolation.x[1] ; params.N = D->Case.Interpolation.x[1];
params.Ja= D->Case.Interpolation.x[2] ; params.Ja = D->Case.Interpolation.x[2];
params.ha= D->Case.Interpolation.x[3] ; params.ha = D->Case.Interpolation.x[3];
params.Jb= D->Case.Interpolation.x[4] ; params.Jb = D->Case.Interpolation.x[4];
params.hb= D->Case.Interpolation.x[5] ; params.hb = D->Case.Interpolation.x[5];
params.kappa=new double[params.N]; params.kappa = new double[params.N];
params.w=new double[params.N]; params.w = new double[params.N];
for (int k=0; k<params.N; k++){ for(int k = 0; k < params.N; k++) {
params.w[k] = D->Case.Interpolation.x[6+2*k]; params.w[k] = D->Case.Interpolation.x[6 + 2 * k];
params.kappa[k] = D->Case.Interpolation.x[7+2*k]; params.kappa[k] = D->Case.Interpolation.x[7 + 2 * k];
} }
params.Xp=new double[3*params.N]; params.Xp = new double[3 * params.N];
for (int k=0; k<params.N; k++) { for(int k = 0; k < params.N; k++) {
for (int n=0; n<3; n++) { for(int n = 0; n < 3; n++) {
params.Xp[n+3*k] = (A+2+1*k)->Val[n]; params.Xp[n + 3 * k] = (A + 2 + 1 * k)->Val[n];
} }
} }
//End Creation of EB parameters structure // End Creation of EB parameters structure
double Xk_all[3*params.N]; double *Xk_all = new double[3 * params.N];
double h[3], b[3], bc[3] ; for(int n = 0; n < 3 * params.N; n++) Xk_all[n] = 0.;
for (int n=0; n<3; n++) { double h[3], b[3], bc[3];
h[n] = (A+0)->Val[n]; // h is initialized at hp for(int n = 0; n < 3; n++) {
b[n] = (A+1)->Val[n]; h[n] = (A + 0)->Val[n]; // h is initialized at hp
bc[n] =0.; b[n] = (A + 1)->Val[n];
bc[n] = 0.;
} }
Vector_h_EB(b, bc, h, Xk_all, &params); // Update h Vector_h_EB(b, bc, h, Xk_all, &params); // Update h
V->Type = VECTOR ; V->Type = VECTOR;
for (int n=0 ; n<3 ; n++) V->Val[n] = h[n]; for(int n = 0; n < 3; n++) V->Val[n] = h[n];
delete [] params.kappa; delete[] Xk_all;
delete [] params.w; delete[] params.kappa;
delete [] params.Xp; delete[] params.w;
delete[] params.Xp;
} }
void F_b_EB(F_ARG) void F_b_EB(F_ARG)
{ {
// #define F_ARG struct Function * Fct, struct Value * A, struct Value * V // #define F_ARG struct Function * Fct, struct Value * A, struct Value * V
// input : // input :
// (A+0) ->Val = magnetic field -- h // (A+0) ->Val = magnetic field -- h
// (A+1+1*k)->Val = material magnetization at previous time step -- Jkp // (A+1+1*k)->Val = material magnetization at previous time step -- Jkp
// Material parameters: e.g. param_EnergHyst = { dim, N, Ja, ha, w_1, kappa_1, // Material parameters: e.g. param_EnergHyst = { dim, N, Ja, ha, w_1, kappa_1,
..., w_N, kappa_N};==> struct FunctionActive *D // ..., w_N, kappa_N};==> struct FunctionActive *D
// --------------------------------------------- // ---------------------------------------------
// output: magnetic induction -- b // output: magnetic induction -- b
struct FunctionActive * D ; struct FunctionActive *D;
if (!Fct->Active) Fi_InitListX (Fct, A, V) ; if(!Fct->Active) Fi_InitListX(Fct, A, V);
D = Fct->Active ; D = Fct->Active;
set_sensi_param(D); set_sensi_param(D);
///* //Init Creation of EB parameters structure ///* //Init Creation of EB parameters structure
struct params_Cells_EB params; struct params_Cells_EB params;
params.N = D->Case.Interpolation.x[1] ; params.N = D->Case.Interpolation.x[1];
params.Ja= D->Case.Interpolation.x[2] ; params.Ja = D->Case.Interpolation.x[2];
params.ha= D->Case.Interpolation.x[3] ; params.ha = D->Case.Interpolation.x[3];
params.Jb= D->Case.Interpolation.x[4] ; params.Jb = D->Case.Interpolation.x[4];
params.hb= D->Case.Interpolation.x[5] ; params.hb = D->Case.Interpolation.x[5];
params.kappa=new double[params.N]; params.kappa = new double[params.N];
params.w=new double[params.N]; params.w = new double[params.N];
for (int k=0; k<params.N; k++){ for(int k = 0; k < params.N; k++) {
params.w[k] = D->Case.Interpolation.x[6+2*k]; params.w[k] = D->Case.Interpolation.x[6 + 2 * k];
params.kappa[k] = D->Case.Interpolation.x[7+2*k]; params.kappa[k] = D->Case.Interpolation.x[7 + 2 * k];
} }
params.Xp=new double[3*params.N]; params.Xp = new double[3 * params.N];
for (int k=0; k<params.N; k++) { for(int k = 0; k < params.N; k++) {
for (int n=0; n<3; n++) { for(int n = 0; n < 3; n++) {
params.Xp[n+3*k] = (A+1+1*k)->Val[n]; params.Xp[n + 3 * k] = (A + 1 + 1 * k)->Val[n];
} }
} }
//End Creation of EB parameters structure // End Creation of EB parameters structure
double *Xk_all = new double[3 * params.N];
for(int n = 0; n < 3 * params.N; n++) Xk_all[n] = 0.;
double Xk_all[3*params.N];
double h[3], b[3]; double h[3], b[3];
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) h[n] = (A + 0)->Val[n];
h[n] = (A+0)->Val[n];
Vector_b_EB(h, b, Xk_all, &params); Vector_b_EB(h, b, Xk_all, &params);
V->Type = VECTOR ; V->Type = VECTOR;
for (int n=0 ; n<3 ; n++) V->Val[n] = b[n]; for(int n = 0; n < 3; n++) V->Val[n] = b[n];
delete [] params.kappa; delete[] Xk_all;
delete [] params.w; delete[] params.kappa;
delete [] params.Xp; delete[] params.w;
delete[] params.Xp;
} }
void F_hrev_EB(F_ARG) void F_hrev_EB(F_ARG)
{ {
// #define F_ARG struct Function * Fct, struct Value * A, struct Value * V // #define F_ARG struct Function * Fct, struct Value * A, struct Value * V
// input : // input :
// (A+0)->Val = number corresponding to the cell studied -- k // (A+0)->Val = number corresponding to the cell studied -- k
// (A+1+1*k)->Val = magnetic material field variable xk (either J if Var appro // (A+1+1*k)->Val = magnetic material field variable xk (either J if Var
ach or hr if Diff approach) // approach or hr if Diff approach) Material parameters: e.g. param_EnergHyst
// Material parameters: e.g. param_EnergHyst = { dim, N, Ja, ha, w_1, kappa_1, // = { dim, N, Ja, ha, w_1, kappa_1, ..., w_N, kappa_N};==> struct
..., w_N, kappa_N};==> struct FunctionActive *D // FunctionActive *D
// --------------------------------------------- // ---------------------------------------------
// output: reversible magnetic field -- hr // output: reversible magnetic field -- hr
struct FunctionActive * D ; struct FunctionActive *D;
if (!Fct->Active) Fi_InitListX (Fct, A, V) ; if(!Fct->Active) Fi_InitListX(Fct, A, V);
D = Fct->Active ; D = Fct->Active;
set_sensi_param(D); set_sensi_param(D);
///* //Init Creation of EB parameters structure ///* //Init Creation of EB parameters structure
struct params_Cells_EB params; struct params_Cells_EB params;
params.idcell = ((A+0)->Val[0])-1; params.idcell = ((A + 0)->Val[0]) - 1;
params.N = D->Case.Interpolation.x[1] ; params.N = D->Case.Interpolation.x[1];
params.Ja= D->Case.Interpolation.x[2] ; params.Ja = D->Case.Interpolation.x[2];
params.ha= D->Case.Interpolation.x[3] ; params.ha = D->Case.Interpolation.x[3];
params.Jb= D->Case.Interpolation.x[4] ; params.Jb = D->Case.Interpolation.x[4];
params.hb= D->Case.Interpolation.x[5] ; params.hb = D->Case.Interpolation.x[5];
params.w=new double[params.N]; params.w = new double[params.N];
params.w[params.idcell] = D->Case.Interpolation.x[6+2*params.idcell]; params.w[params.idcell] = D->Case.Interpolation.x[6 + 2 * params.idcell];
//End Creation of EB parameters structure // End Creation of EB parameters structure
double hrk[3], xk[3]; double hrk[3], xk[3];
switch(::FLAG_APPROACH) { switch(::FLAG_APPROACH) {
case 1: case 1:
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) xk[n] = (A + 1)->Val[n];
xk[n] = (A+1)->Val[n]; Vector_hrk_From_Jk(xk, &params, hrk);
Vector_hrk_From_Jk(xk,&params, hrk);
break;
case 2:
case 3:
for (int n=0; n<3; n++)
hrk[n] = (A+1)->Val[n];
break; break;
default: case 2:
Message::Error("Invalid parameter (FLAG_APPROACH = 1,2 or 3) for function case 3:
'F_hr_EB'.\n" for(int n = 0; n < 3; n++) hrk[n] = (A + 1)->Val[n];
"FLAG_APPROACH = 1 --> Variational Approach\n" break;
"FLAG_APPROACH = 2 --> Vector Play Model approach\n" default:
"FLAG_APPROACH = 3 --> Full Differential Approach (gsl)"); Message::Error(
"Invalid parameter (FLAG_APPROACH = 1,2 or 3) for function 'F_hr_EB'.\n"
"FLAG_APPROACH = 1 --> Variational Approach\n"
"FLAG_APPROACH = 2 --> Vector Play Model approach\n"
"FLAG_APPROACH = 3 --> Full Differential Approach (gsl)");
break; break;
} }
V->Type = VECTOR ; V->Type = VECTOR;
for (int n=0 ; n<3 ; n++) V->Val[n] = hrk[n]; for(int n = 0; n < 3; n++) V->Val[n] = hrk[n];
delete [] params.w;
delete[] params.w;
} }
void F_Jrev_EB(F_ARG) void F_Jrev_EB(F_ARG)
{ {
// #define F_ARG struct Function * Fct, struct Value * A, struct Value * V // #define F_ARG struct Function * Fct, struct Value * A, struct Value * V
// input : // input :
// (A+0)->Val = number corresponding to the cell studied -- k // (A+0)->Val = number corresponding to the cell studied -- k
// (A+1+1*k)->Val = magnetic material field variable xk (either J if Var appro // (A+1+1*k)->Val = magnetic material field variable xk (either J if Var
ach or hr if Diff approach) // approach or hr if Diff approach) Material parameters: e.g. param_EnergHyst
// Material parameters: e.g. param_EnergHyst = { dim, N, Ja, ha, w_1, kappa_1, // = { dim, N, Ja, ha, w_1, kappa_1, ..., w_N, kappa_N};==> struct
..., w_N, kappa_N};==> struct FunctionActive *D // FunctionActive *D
// --------------------------------------------- // ---------------------------------------------
// output: magnetic magnetization -- J // output: magnetic magnetization -- J
struct FunctionActive * D ; struct FunctionActive *D;
if (!Fct->Active) Fi_InitListX (Fct, A, V) ; if(!Fct->Active) Fi_InitListX(Fct, A, V);
D = Fct->Active ; D = Fct->Active;
set_sensi_param(D); set_sensi_param(D);
///* //Init Creation of EB parameters structure ///* //Init Creation of EB parameters structure
struct params_Cells_EB params; struct params_Cells_EB params;
params.idcell = ((A+0)->Val[0])-1; params.idcell = ((A + 0)->Val[0]) - 1;
params.N = D->Case.Interpolation.x[1] ; params.N = D->Case.Interpolation.x[1];
params.Ja= D->Case.Interpolation.x[2] ; params.Ja = D->Case.Interpolation.x[2];
params.ha= D->Case.Interpolation.x[3] ; params.ha = D->Case.Interpolation.x[3];
params.Jb= D->Case.Interpolation.x[4] ; params.Jb = D->Case.Interpolation.x[4];
params.hb= D->Case.Interpolation.x[5] ; params.hb = D->Case.Interpolation.x[5];
params.w=new double[params.N]; params.w = new double[params.N];
params.w[params.idcell] = D->Case.Interpolation.x[6+2*params.idcell]; params.w[params.idcell] = D->Case.Interpolation.x[6 + 2 * params.idcell];
//End Creation of EB parameters structure // End Creation of EB parameters structure
double Jk[3], xk[3]; double Jk[3], xk[3];
switch(::FLAG_APPROACH) { switch(::FLAG_APPROACH) {
case 1: case 1:
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) Jk[n] = (A + 1)->Val[n];
Jk[n] = (A+1)->Val[n];
break;
case 2:
case 3:
for (int n=0; n<3; n++)
xk[n] = (A+1)->Val[n];
Vector_Jk_From_hrk(xk,&params, Jk);
break; break;
default: case 2:
Message::Error("Invalid parameter (FLAG_APPROACH = 1,2 or 3) for function case 3:
'F_Jr_EB'.\n" for(int n = 0; n < 3; n++) xk[n] = (A + 1)->Val[n];
"FLAG_APPROACH = 1 --> Variational Approach\n" Vector_Jk_From_hrk(xk, &params, Jk);
"FLAG_APPROACH = 2 --> Vector Play Model approach\n" break;
"FLAG_APPROACH = 3 --> Full Differential Approach (gsl)"); default:
Message::Error(
"Invalid parameter (FLAG_APPROACH = 1,2 or 3) for function 'F_Jr_EB'.\n"
"FLAG_APPROACH = 1 --> Variational Approach\n"
"FLAG_APPROACH = 2 --> Vector Play Model approach\n"
"FLAG_APPROACH = 3 --> Full Differential Approach (gsl)");
break; break;
} }
V->Type = VECTOR ; V->Type = VECTOR;
for (int n=0 ; n<3 ; n++) V->Val[n] = Jk[n]; for(int n = 0; n < 3; n++) V->Val[n] = Jk[n];
} }
void F_dbdh_EB(F_ARG) void F_dbdh_EB(F_ARG)
{ {
// #define F_ARG struct Function * Fct, struct Value * A, struct Value * V // #define F_ARG struct Function * Fct, struct Value * A, struct Value * V
// input : // input :
// (A+0) ->Val = magnetic field -- h // (A+0) ->Val = magnetic field -- h
// (A+1+1*k)->Val = material magnetization at previous time step -- Jkp // (A+1+1*k)->Val = material magnetization at previous time step -- Jkp
// Material parameters: e.g. param_EnergHyst = { dim, N, Ja, ha, w_1, kappa_1, // Material parameters: e.g. param_EnergHyst = { dim, N, Ja, ha, w_1, kappa_1,
..., w_N, kappa_N};==> struct FunctionActive *D // ..., w_N, kappa_N};==> struct FunctionActive *D
// --------------------------------------------- // ---------------------------------------------
// output: differential reluctivity -- dbdh // output: differential reluctivity -- dbdh
struct FunctionActive * D ; struct FunctionActive *D;
if (!Fct->Active) Fi_InitListX (Fct, A, V) ; if(!Fct->Active) Fi_InitListX(Fct, A, V);
D = Fct->Active ; D = Fct->Active;
set_sensi_param(D); set_sensi_param(D);
///* //Init Creation of EB parameters structure ///* //Init Creation of EB parameters structure
struct params_Cells_EB params; struct params_Cells_EB params;
params.N = D->Case.Interpolation.x[1] ; params.N = D->Case.Interpolation.x[1];
params.Ja= D->Case.Interpolation.x[2] ; params.Ja = D->Case.Interpolation.x[2];
params.ha= D->Case.Interpolation.x[3] ; params.ha = D->Case.Interpolation.x[3];
params.Jb= D->Case.Interpolation.x[4] ; params.Jb = D->Case.Interpolation.x[4];
params.hb= D->Case.Interpolation.x[5] ; params.hb = D->Case.Interpolation.x[5];
params.kappa=new double[params.N]; params.kappa = new double[params.N];
params.w=new double[params.N]; params.w = new double[params.N];
for (int k=0; k<params.N; k++){ for(int k = 0; k < params.N; k++) {
params.w[k] = D->Case.Interpolation.x[6+2*k]; params.w[k] = D->Case.Interpolation.x[6 + 2 * k];
params.kappa[k] = D->Case.Interpolation.x[7+2*k]; params.kappa[k] = D->Case.Interpolation.x[7 + 2 * k];
} }
params.Xp=new double[3*params.N]; params.Xp = new double[3 * params.N];
for (int k=0; k<params.N; k++) { for(int k = 0; k < params.N; k++) {
for (int n=0; n<3; n++) { for(int n = 0; n < 3; n++) {
params.Xp[n+3*k] = (A+1+1*k)->Val[n]; params.Xp[n + 3 * k] = (A + 1 + 1 * k)->Val[n];
} }
} }
//End Creation of EB parameters structure // End Creation of EB parameters structure
double h[3]; double h[3];
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) h[n] = (A + 0)->Val[n];
h[n] = (A+0)->Val[n];
double bdummy[3] = {0., 0., 0.};
double *Xk_all = new double[3 * params.N];
for(int n = 0; n < 3 * params.N; n++) Xk_all[n] = 0.;
double Xk_all[3*params.N], bdummy[3];
Vector_b_EB(h, bdummy, Xk_all, &params); // to update Xk_all Vector_b_EB(h, bdummy, Xk_all, &params); // to update Xk_all
// Init dbdh // Init dbdh
int ncomp = ::NCOMP; int ncomp = ::NCOMP;
switch(::FLAG_SYM) switch(::FLAG_SYM) {
{ case 1: V->Type = TENSOR_SYM; break;
case 1: case 0: V->Type = TENSOR; break;
V->Type = TENSOR_SYM ; default:
break; Message::Error("Invalid parameter (FLAG_SYM = 0 or 1)"
case 0: "for function 'F_dhdb_EB'.\n");
V->Type = TENSOR ;
break;
default:
Message::Error("Invalid parameter (FLAG_SYM = 0 or 1)"
"for function 'F_dhdb_EB'.\n");
break; break;
} }
double *dbdh; dbdh = new double[ncomp]; double *dbdh;
for (int n=0; n<ncomp; n++) dbdh[n]=0.; dbdh = new double[ncomp];
for(int n = 0; n < ncomp; n++) dbdh[n] = 0.;
switch(::FLAG_JACEVAL) { switch(::FLAG_JACEVAL) {
case 1: case 1:
Tensor_dbdh_ana(h, Xk_all, &params, dbdh); // eval dbdh Tensor_dbdh_ana(h, Xk_all, &params, dbdh); // eval dbdh
break; break;
case 2: case 2:
Tensor_num(Vector_b_EB, h, ::DELTA_0, Xk_all, &params, dbdh); // eval db Tensor_num(Vector_b_EB, h, ::DELTA_0, Xk_all, &params,
dh numerically dbdh); // eval dbdh numerically
break; break;
default: default:
Message::Error("Invalid parameter (FLAG_JACEVAL = 1,2) for function 'F_d Message::Error(
hdb_EB'.\n" "Invalid parameter (FLAG_JACEVAL = 1,2) for function 'F_dhdb_EB'.\n"
"FLAG_JACEVAL = 1 --> analytical Jacobian dbdh\n" "FLAG_JACEVAL = 1 --> analytical Jacobian dbdh\n"
"FLAG_JACEVAL = 2 --> numerical Jacobian dbdh"); "FLAG_JACEVAL = 2 --> numerical Jacobian dbdh");
break; break;
} }
for (int k=0 ; k<ncomp ; k++) for(int k = 0; k < ncomp; k++) V->Val[k] = dbdh[k];
V->Val[k] = dbdh[k] ;
delete [] dbdh; delete[] Xk_all;
delete [] params.kappa; delete[] dbdh;
delete [] params.w; delete[] params.kappa;
delete [] params.Xp; delete[] params.w;
delete[] params.Xp;
} }
void F_dhdb_EB(F_ARG) void F_dhdb_EB(F_ARG)
{ {
// #define F_ARG struct Function * Fct, struct Value * A, struct Value * V // #define F_ARG struct Function * Fct, struct Value * A, struct Value * V
// input : // input :
// (A+0) ->Val = magnetic field -- h // (A+0) ->Val = magnetic field -- h
// (A+1+1*k)->Val = material magnetization at previous time step -- Jkp // (A+1+1*k)->Val = material magnetization at previous time step -- Jkp
// Material parameters: e.g. param_EnergHyst = { dim, N, Ja, ha, w_1, kappa_1, // Material parameters: e.g. param_EnergHyst = { dim, N, Ja, ha, w_1, kappa_1,
..., w_N, kappa_N};==> struct FunctionActive *D // ..., w_N, kappa_N};==> struct FunctionActive *D
// --------------------------------------------- // ---------------------------------------------
// output: differential reluctivity -- dhdb // output: differential reluctivity -- dhdb
struct FunctionActive * D ; struct FunctionActive *D;
if (!Fct->Active) Fi_InitListX (Fct, A, V) ; if(!Fct->Active) Fi_InitListX(Fct, A, V);
D = Fct->Active ; D = Fct->Active;
set_sensi_param(D); set_sensi_param(D);
///* //Init Creation of EB parameters structure ///* //Init Creation of EB parameters structure
struct params_Cells_EB params; struct params_Cells_EB params;
params.N = D->Case.Interpolation.x[1] ; params.N = D->Case.Interpolation.x[1];
params.Ja= D->Case.Interpolation.x[2] ; params.Ja = D->Case.Interpolation.x[2];
params.ha= D->Case.Interpolation.x[3] ; params.ha = D->Case.Interpolation.x[3];
params.Jb= D->Case.Interpolation.x[4] ; params.Jb = D->Case.Interpolation.x[4];
params.hb= D->Case.Interpolation.x[5] ; params.hb = D->Case.Interpolation.x[5];
params.kappa=new double[params.N]; params.kappa = new double[params.N];
params.w=new double[params.N]; params.w = new double[params.N];
for (int k=0; k<params.N; k++){ for(int k = 0; k < params.N; k++) {
params.w[k] = D->Case.Interpolation.x[6+2*k]; params.w[k] = D->Case.Interpolation.x[6 + 2 * k];
params.kappa[k] = D->Case.Interpolation.x[7+2*k]; params.kappa[k] = D->Case.Interpolation.x[7 + 2 * k];
} }
params.Xp=new double[3*params.N]; params.Xp = new double[3 * params.N];
for (int k=0; k<params.N; k++) { for(int k = 0; k < params.N; k++) {
for (int n=0; n<3; n++) { for(int n = 0; n < 3; n++) {
params.Xp[n+3*k] = (A+1+1*k)->Val[n]; params.Xp[n + 3 * k] = (A + 1 + 1 * k)->Val[n];
} }
} }
//End Creation of EB parameters structure // End Creation of EB parameters structure
double h[3]; double h[3];
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++) h[n] = (A + 0)->Val[n];
h[n] = (A+0)->Val[n];
double Xk_all[3*params.N],bdummy[3]; double bdummy[3] = {0., 0., 0.};
double *Xk_all = new double[3 * params.N];
for(int n = 0; n < 3 * params.N; n++) Xk_all[n] = 0.;
Vector_b_EB(h, bdummy, Xk_all, &params); // to update Xk_all Vector_b_EB(h, bdummy, Xk_all, &params); // to update Xk_all
// Init dbdh // Init dbdh
int ncomp = ::NCOMP; int ncomp = ::NCOMP;
switch(::FLAG_SYM) switch(::FLAG_SYM) {
{ case 1: V->Type = TENSOR_SYM; break;
case 1: case 0: V->Type = TENSOR; break;
V->Type = TENSOR_SYM ; default:
break; Message::Error("Invalid parameter (FLAG_SYM = 0 or 1)"
case 0: "for function 'F_dhdb_EB'.\n");
V->Type = TENSOR ;
break;
default:
Message::Error("Invalid parameter (FLAG_SYM = 0 or 1)"
"for function 'F_dhdb_EB'.\n");
break; break;
} }
double *dbdh; dbdh = new double[ncomp]; double *dbdh;
double *dhdb; dhdb = new double[ncomp]; dbdh = new double[ncomp];
for (int n=0; n<ncomp; n++) {dbdh[n]=0.; dhdb[n]=0.;} double *dhdb;
dhdb = new double[ncomp];
for(int n = 0; n < ncomp; n++) {
dbdh[n] = 0.;
dhdb[n] = 0.;
}
switch(::FLAG_JACEVAL) { switch(::FLAG_JACEVAL) {
case 1: case 1:
Tensor_dbdh_ana(h, Xk_all, &params, dbdh); // eval dbdh Tensor_dbdh_ana(h, Xk_all, &params, dbdh); // eval dbdh
break; break;
case 2: case 2:
Tensor_num(Vector_b_EB, h, ::DELTA_0, Xk_all, &params, dbdh); // eval dbdh Tensor_num(Vector_b_EB, h, ::DELTA_0, Xk_all, &params,
numerically dbdh); // eval dbdh numerically
break; break;
default: default:
Message::Error("Invalid parameter (FLAG_JACEVAL = 1,2) for function 'F_dhd Message::Error(
b_EB'.\n" "Invalid parameter (FLAG_JACEVAL = 1,2) for function 'F_dhdb_EB'.\n"
"FLAG_JACEVAL = 1 --> analytical Jacobian dhdb\n" "FLAG_JACEVAL = 1 --> analytical Jacobian dhdb\n"
"FLAG_JACEVAL = 2 --> numerical Jacobian dhdb"); "FLAG_JACEVAL = 2 --> numerical Jacobian dhdb");
break; break;
} }
switch(::FLAG_SYM) switch(::FLAG_SYM) {
{ case 1:
case 1: Inv_TensorSym3x3(dbdh, dhdb); // dimension, T, invT
Inv_TensorSym3x3(dbdh, dhdb); // dimension, T, invT
break; break;
case 0: case 0:
Inv_Tensor3x3(dbdh, dhdb); // dimension, T, invT Inv_Tensor3x3(dbdh, dhdb); // dimension, T, invT
break; break;
default: default:
Message::Error("Invalid parameter (FLAG_SYM = 0 or 1)" Message::Error("Invalid parameter (FLAG_SYM = 0 or 1)"
"for function 'F_dhdb_EB'.\n"); "for function 'F_dhdb_EB'.\n");
break; break;
} }
for (int k=0 ; k<ncomp ; k++) for(int k = 0; k < ncomp; k++) V->Val[k] = dhdb[k];
V->Val[k] = dhdb[k] ;
delete [] dhdb; delete[] Xk_all;
delete [] dbdh; delete[] dhdb;
delete [] params.kappa; delete[] dbdh;
delete [] params.w; delete[] params.kappa;
delete [] params.Xp; delete[] params.w;
delete[] params.Xp;
} }
//************************************************ //************************************************
// Energy-Based Model - GetDP Functions (DEPRECIATED): // Energy-Based Model - GetDP Functions (DEPRECIATED):
//************************************************ //************************************************
void F_Update_Cell_K(F_ARG) { void F_Update_Cell_K(F_ARG)
// Updating the Cell variable : Jk (for variationnal approach) or hrk (for dif {
ferential approach) // Updating the Cell variable : Jk (for variationnal approach) or hrk (for
// differential approach)
// --------------------------------------------- // ---------------------------------------------
// input: // input:
// (A+0)->Val = number corresponding to the cell studied -- k // (A+0)->Val = number corresponding to the cell studied -- k
// (A+1)->Val = magnetic field -- h // (A+1)->Val = magnetic field -- h
// (A+2)->Val = material magnetization (var) or reversible magnetic field (dif // (A+2)->Val = material magnetization (var) or reversible magnetic field
f) -- xk // USELESS recomputed inside // (diff) -- xk // USELESS recomputed inside (A+3)->Val = material
// (A+3)->Val = material magnetization (var) or reversible magnetic field (dif // magnetization (var) or reversible magnetic field (diff) at previous time
f) at previous time step -- xkp // step -- xkp Material parameters: e.g. param_EnergHyst = { dim, N, Ja, ha,
// Material parameters: e.g. param_EnergHyst = { dim, N, Ja, ha, w_1, kappa_1, // w_1, kappa_1, ..., w_N, kappa_N};==> struct FunctionActive *D
..., w_N, kappa_N};==> struct FunctionActive *D
// --------------------------------------------- // ---------------------------------------------
// output: updated Jk // output: updated Jk
//Message::Warning("Function 'Update_Cell_K[k, {h}, {xk}, {xk}[1] ]' will be d // Message::Warning("Function 'Update_Cell_K[k, {h}, {xk}, {xk}[1] ]' will be
epecriated, please replace by 'Cell_EB[k, {h}, {xk}[1]]'"); // depecriated, please replace by 'Cell_EB[k, {h}, {xk}[1]]'");
for (int n=0; n<3; n++) { for(int n = 0; n < 3; n++) { (A + 2)->Val[n] = (A + 3)->Val[n]; }
(A+2)->Val[n]=(A+3)->Val[n]; F_Cell_EB(Fct, A, V);
}
F_Cell_EB(Fct,A,V);
} }
void F_h_Vinch_K(F_ARG){ void F_h_Vinch_K(F_ARG)
{
// #define F_ARG struct Function * Fct, struct Value * A, struct Value * V // #define F_ARG struct Function * Fct, struct Value * A, struct Value * V
// input : // input :
// (A+0) ->Val = last computed magnetic field (for example at previous time // (A+0) ->Val = last computed magnetic field (for example at previous time
step -- hp) // usefull for initialization // step -- hp) // usefull for initialization (A+1) ->Val = magnetic
// (A+1) ->Val = magnetic induction -- b // induction -- b (A+2) ->Val = magnetic induction corresponding to the
// (A+2) ->Val = magnetic induction corresponding to the last computed magn // last computed magnetic field (for example at previous time step -- bp) //
etic field (for example at previous time step -- bp) // USELESS hp is enhough // USELESS hp is enhough (A+3+2*k)->Val = material magnetization -- Jk //
// (A+3+2*k)->Val = material magnetization -- Jk // USELESS because recomputed // USELESS because recomputed (A+4+2*k)->Val = material magnetization at
// (A+4+2*k)->Val = material magnetization at previous time step -- Jkp // previous time step -- Jkp Material parameters: e.g. param_EnergHyst = {
// Material parameters: e.g. param_EnergHyst = { dim, N, Ja, ha, w_1, kappa_1, // dim, N, Ja, ha, w_1, kappa_1, ..., w_N, kappa_N};==> struct FunctionActive
..., w_N, kappa_N};==> struct FunctionActive *D // *D
// --------------------------------------------- // ---------------------------------------------
// output: magnetic field -- h // output: magnetic field -- h
//Message::Warning("Function 'h_Vinch_K[{h},{b},{b}[1], {xk}, {xk}[1], ...]' w // Message::Warning("Function 'h_Vinch_K[{h},{b},{b}[1], {xk}, {xk}[1], ...]'
ill be depecriated, please replace by 'h_EB[{h},{b}, {xk}[1], ...]'"); // will be depecriated, please replace by 'h_EB[{h},{b}, {xk}[1], ...]'");
struct FunctionActive * D ; struct FunctionActive *D;
if (!Fct->Active) Fi_InitListX (Fct, A, V) ; if(!Fct->Active) Fi_InitListX(Fct, A, V);
D = Fct->Active ; D = Fct->Active;
int N = D->Case.Interpolation.x[1] ; int N = D->Case.Interpolation.x[1];
for (int k=0; k<N; k++) { for(int k = 0; k < N; k++) {
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++)
(A+2+1*k)->Val[n]=(A+4+2*k)->Val[n]; (A + 2 + 1 * k)->Val[n] = (A + 4 + 2 * k)->Val[n];
} }
F_h_EB(Fct,A,V); F_h_EB(Fct, A, V);
} }
void F_b_Vinch_K(F_ARG){ void F_b_Vinch_K(F_ARG)
{
// #define F_ARG struct Function * Fct, struct Value * A, struct Value * V // #define F_ARG struct Function * Fct, struct Value * A, struct Value * V
// input : // input :
// (A+0) ->Val = magnetic field -- h // (A+0) ->Val = magnetic field -- h
// (A+1+2*k)->Val = material magnetization -- Jk // USELESS because recompute // (A+1+2*k)->Val = material magnetization -- Jk // USELESS because
d // recomputed (A+2+2*k)->Val = material magnetization at previous time step --
// (A+2+2*k)->Val = material magnetization at previous time step -- Jkp // Jkp Material parameters: e.g. param_EnergHyst = { dim, N, Ja, ha, w_1,
// Material parameters: e.g. param_EnergHyst = { dim, N, Ja, ha, w_1, kappa_1, // kappa_1, ..., w_N, kappa_N};==> struct FunctionActive *D
..., w_N, kappa_N};==> struct FunctionActive *D
// --------------------------------------------- // ---------------------------------------------
// output: magnetic induction -- b // output: magnetic induction -- b
//Message::Warning("Function 'b_Vinch_K[{h}, {xk}, {xk}[1], ...]' will be depe // Message::Warning("Function 'b_Vinch_K[{h}, {xk}, {xk}[1], ...]' will be
criated, please replace by 'b_EB[{h}, {xk}[1]]'"); // depecriated, please replace by 'b_EB[{h}, {xk}[1]]'");
struct FunctionActive * D ; struct FunctionActive *D;
if (!Fct->Active) Fi_InitListX (Fct, A, V) ; if(!Fct->Active) Fi_InitListX(Fct, A, V);
D = Fct->Active ; D = Fct->Active;
int N = D->Case.Interpolation.x[1] ; int N = D->Case.Interpolation.x[1];
for (int k=0; k<N; k++) { for(int k = 0; k < N; k++) {
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++)
(A+1+1*k)->Val[n]=(A+2+2*k)->Val[n]; (A + 1 + 1 * k)->Val[n] = (A + 2 + 2 * k)->Val[n];
} }
F_b_EB(Fct,A,V); F_b_EB(Fct, A, V);
} }
void F_hr_Vinch_K(F_ARG){ void F_hr_Vinch_K(F_ARG)
//Message::Warning("Function 'hr_Vinch_K[...]' will be depecriated, please rep {
lace by 'hr_EB[...]'"); // Message::Warning("Function 'hr_Vinch_K[...]' will be depecriated, please
F_hrev_EB(Fct,A,V); // replace by 'hr_EB[...]'");
F_hrev_EB(Fct, A, V);
} }
void F_Jr_Vinch_K(F_ARG){ void F_Jr_Vinch_K(F_ARG)
//Message::Warning("Function 'Jr_Vinch_K[...]' will be depecriated, please rep {
lace by 'Jrev_EB[...]'"); // Message::Warning("Function 'Jr_Vinch_K[...]' will be depecriated, please
F_Jrev_EB(Fct,A,V); // replace by 'Jrev_EB[...]'");
F_Jrev_EB(Fct, A, V);
} }
void F_dbdh_Vinch_K(F_ARG){ void F_dbdh_Vinch_K(F_ARG)
{
// #define F_ARG struct Function * Fct, struct Value * A, struct Value * V // #define F_ARG struct Function * Fct, struct Value * A, struct Value * V
// input : // input :
// (A+0) ->Val = magnetic field -- h // (A+0) ->Val = magnetic field -- h
// (A+1+2*k)->Val = material magnetization -- Jk // USELESS if recomputed with // (A+1+2*k)->Val = material magnetization -- Jk // USELESS if recomputed with
Vector_b_EB here after // Vector_b_EB here after (A+2+2*k)->Val = material magnetization at previous
// (A+2+2*k)->Val = material magnetization at previous time step -- Jkp // time step -- Jkp Material parameters: e.g. param_EnergHyst = { dim, N, Ja,
// Material parameters: e.g. param_EnergHyst = { dim, N, Ja, ha, w_1, kappa_1, // ha, w_1, kappa_1, ..., w_N, kappa_N};==> struct FunctionActive *D
..., w_N, kappa_N};==> struct FunctionActive *D
// --------------------------------------------- // ---------------------------------------------
// output: differential reluctivity -- dbdh // output: differential reluctivity -- dbdh
//Message::Warning("Function 'dbdh_Vinch_K[{h}, {xk}, {xk}[1], ...]' will be d // Message::Warning("Function 'dbdh_Vinch_K[{h}, {xk}, {xk}[1], ...]' will be
epecriated, please replace by 'dbdh_EB[{h}, {xk}[1], ...]'"); // depecriated, please replace by 'dbdh_EB[{h}, {xk}[1], ...]'");
struct FunctionActive * D ; struct FunctionActive *D;
if (!Fct->Active) Fi_InitListX (Fct, A, V) ; if(!Fct->Active) Fi_InitListX(Fct, A, V);
D = Fct->Active ; D = Fct->Active;
int N = D->Case.Interpolation.x[1] ; int N = D->Case.Interpolation.x[1];
for (int k=0; k<N; k++) { for(int k = 0; k < N; k++) {
for (int n=0; n<3; n++) for(int n = 0; n < 3; n++)
(A+1+1*k)->Val[n]=(A+2+2*k)->Val[n]; (A + 1 + 1 * k)->Val[n] = (A + 2 + 2 * k)->Val[n];
} }
F_dbdh_EB(Fct,A,V); F_dbdh_EB(Fct, A, V);
} }
void F_dhdb_Vinch_K(F_ARG){ void F_dhdb_Vinch_K(F_ARG)
{
// #define F_ARG struct Function * Fct, struct Value * A, struct Value * V // #define F_ARG struct Function * Fct, struct Value * A, struct Value * V
// input : // input :
// (A+0) ->Val = magnetic field -- h // (A+0) ->Val = magnetic field -- h
// (A+1+2*k)->Val = material magnetization -- Jk // USELESS if recomputed with // (A+1+2*k)->Val = material magnetization -- Jk // USELESS if recomputed with
Vector_b_EB here after // Vector_b_EB here after (A+2+2*k)->Val = material magnetization at previous
// (A+2+2*k)->Val = material magnetization at previous time step -- Jkp // time step -- Jkp Material parameters: e.g. param_EnergHyst = { dim, N, Ja,
// Material parameters: e.g. param_EnergHyst = { dim, N, Ja, ha, w_1, kappa_1, // ha, w_1, kappa_1, ..., w_N, kappa_N};==> struct FunctionActive *D
..., w_N, kappa_N};==> struct FunctionActive *D
// --------------------------------------------- // ---------------------------------------------
// output: differential reluctivity -- dhdb // output: differential reluctivity -- dhdb
//Message::Warning("Function 'dhdb_Vinch_K[{h}, {xk}, {xk}[1], ...]' will be d // Message::Warning("Function 'dhdb_Vinch_K[{h}, {xk}, {xk}[1], ...]' will be
epecriated, please replace by 'dhdb_EB[{h}, {xk}[1], ...]'"); // depecriated, please replace by 'dhdb_EB[{h}, {xk}[1], ...]'");
struct FunctionActive *D;
if(!Fct->Active) Fi_InitListX(Fct, A, V);
D = Fct->Active;
struct FunctionActive * D ; int N = D->Case.Interpolation.x[1];
if (!Fct->Active) Fi_InitListX (Fct, A, V) ; for(int k = 0; k < N; k++) {
D = Fct->Active ; for(int n = 0; n < 3; n++)
(A + 1 + 1 * k)->Val[n] = (A + 2 + 2 * k)->Val[n];
int N = D->Case.Interpolation.x[1] ;
for (int k=0; k<N; k++) {
for (int n=0; n<3; n++)
(A+1+1*k)->Val[n]=(A+2+2*k)->Val[n];
} }
F_dhdb_EB(Fct,A,V); F_dhdb_EB(Fct, A, V);
} }
 End of changes. 575 change blocks. 
2753 lines changed or deleted 2476 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)