├── .DS_Store ├── .gitignore ├── .vscode ├── c_cpp_properties.json ├── eigen_fix.h ├── launch.json ├── settings.json └── tasks.json ├── CMakeLists.txt ├── Debuginput ├── .DS_Store ├── Al.sx ├── test_loading.txt └── test_texture.tex ├── EVPSC_CPP.cpp ├── EVPSC_CPP.in ├── Grains.cpp ├── Grains.h ├── Input.h ├── Modes.cpp ├── Modes.h ├── PNGs ├── .DS_Store ├── Eq1-5.png └── F=FeFp.png ├── Polycrystals.cpp ├── Polycrystals.h ├── Processes.cpp ├── Processes.h ├── README.md ├── Systems_Voce.cpp ├── Systems_Voce.h ├── Toolbox.cpp ├── Toolbox.h ├── global.cpp ├── global.h └── workspace.code-workspace /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kecheng96/EVPSC_CPP/af3fdbff5186436687d7dee56c9cab374f07c83b/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.exe 2 | *.out 3 | build/* 4 | CMake_macOS.txt 5 | .gitignore 6 | debug/* 7 | .cache/* 8 | -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Mac", 5 | "includePath": [ 6 | "${workspaceFolder}/**", 7 | "/opt/homebrew/Cellar/eigen/3.4.0_1/include/eigen3/", 8 | "/opt/homebrew/Cellar/libomp/14.0.6/include" 9 | ], 10 | "defines": [], 11 | "macFrameworkPath": [ 12 | "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks" 13 | ], 14 | "compilerPath": "/usr/bin/clang", 15 | "cStandard": "gnu17", 16 | "cppStandard": "gnu++17", 17 | "intelliSenseMode": "macos-clang-arm64", 18 | "forcedInclude": ["${workspaceFolder}/.vscode/eigen_fix.h"], 19 | "compileCommands": "${workspaceFolder}/build/compile_commands.json", 20 | "configurationProvider": "ms-vscode.cmake-tools" 21 | } 22 | ], 23 | "version": 4 24 | } -------------------------------------------------------------------------------- /.vscode/eigen_fix.h: -------------------------------------------------------------------------------- 1 | #if __INTELLISENSE__ 2 | #define EIGEN_ARM64_USE_SVE 3 | #endif 4 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "(lldb) Launch", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "${workspaceFolder}/build/EVPSC_CPP", 12 | "args": [], 13 | "stopAtEntry": true, 14 | "cwd": "${workspaceFolder}", 15 | "environment": [], 16 | "externalConsole": false, 17 | "MIMode": "lldb" 18 | } 19 | 20 | 21 | ] 22 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "C_Cpp.errorSquiggles": "Enabled", 3 | "files.associations": { 4 | "iostream": "cpp", 5 | "istream": "cpp" 6 | } 7 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "cmake", 6 | "label": "CMake: build", 7 | "command": "build", 8 | "targets": [ 9 | "all" 10 | ], 11 | "group": "build", 12 | "problemMatcher": [], 13 | "detail": "CMake template build task" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0.0) 2 | 3 | #set(CMAKE_CXX_COMPILER "/usr/bin/gcc") 4 | set(CMAKE_CXX_FLAGS_DEBUG "-O3") 5 | 6 | project(EVPSC_CPP) 7 | set(CMAKE_CXX_STANDARD 17) 8 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 9 | set(CMAKE_BUILD_TYPE Debug) 10 | 11 | set( EIGEN3_INCLUDE_DIR "/opt/homebrew/Cellar/eigen/3.4.0_1/include/eigen3") 12 | set( OMP_INCLUDE_DIR "/opt/homebrew/Cellar/libomp/14.0.6/include") 13 | 14 | include_directories( ${EIGEN3_INCLUDE_DIR} ${OMP_INCLUDE_DIR} ) 15 | 16 | add_executable(EVPSC EVPSC_CPP.cpp Toolbox.cpp Processes.cpp Polycrystals.cpp Grains.cpp Modes.cpp Systems_Voce.cpp global.cpp) 17 | -------------------------------------------------------------------------------- /Debuginput/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kecheng96/EVPSC_CPP/af3fdbff5186436687d7dee56c9cab374f07c83b/Debuginput/.DS_Store -------------------------------------------------------------------------------- /Debuginput/Al.sx: -------------------------------------------------------------------------------- 1 | *Material: Aluminum 2 | CUBIC crysym 3 | 1. 1. 1. 90. 90. 90. cdim(i),cang(i) 4 | *Elastic stiffness of single crystal [MPa] 5 | 206e3 118e3 118e3 0.0 0.0 0.0 6 | 118e3 206e3 118e3 0.0 0.0 0.0 7 | 118e3 118e3 206e3 0.0 0.0 0.0 8 | 0.0 0.0 0.0 54e3 0.0e5 0.0e5 9 | 0.0 0.0 0.0 0.0e5 54e3 0.0e5 10 | 0.0 0.0 0.0 0.0e5 0.0e5 54e3 11 | *Thermal expansion coefficients of single crystal[K^(-1)] 12 | 5.7e-6 5.7e-6 10.3e-6 0.0e0 0.0e0 0.0e0 13 | SLIP AND TWINNING MODES 14 | 2 nmodesx 15 | 1 nmodes 16 | 1 mode(i) 17 | <111>{110} SLIP 18 | 1 12 1 0 modex,nsmx,nrsx,iopsysx 19 | 1 1 1 0 1 -1 20 | 1 1 1 1 0 -1 21 | 1 1 1 1 -1 0 22 | -1 1 1 0 1 -1 23 | -1 1 1 1 0 1 24 | -1 1 1 1 1 0 25 | -1 -1 1 0 1 1 26 | -1 -1 1 1 0 1 27 | -1 -1 1 1 -1 0 28 | 1 -1 1 0 1 1 29 | 1 -1 1 1 0 -1 30 | 1 -1 1 1 1 0 31 | <111>{112} TWIN 32 | 2 12 0 1 modex,nsmx,nrsx,iopsysx 33 | 0.707 twshx 34 | 1 1 1 -2 1 1 35 | 1 1 1 1 -2 1 36 | 1 1 1 1 1 -2 37 | -1 1 1 2 1 1 38 | -1 1 1 -1 -2 1 39 | -1 1 1 -1 1 -2 40 | -1 -1 1 2 -1 1 41 | -1 -1 1 -1 2 1 42 | -1 -1 1 -1 -1 -2 43 | 1 -1 1 -2 -1 1 44 | 1 -1 1 1 2 1 45 | 1 -1 1 1 -1 -2 46 | CONSTITUTIVE LAW 47 | 3 Voce=0, MTS=1, DD=2, CG=3 48 | 1 iratesens (0:rate insensitive, 1:rate sensitive) 49 | 70. GRAIN SIZE 50 | {10-10}<11-20> 51 | 10 NRSX 52 | 120. 90. 300.0 20. 0. 0. tau0x,tau1x,thet0,thet1, Hhp,Hgnd 53 | 1.0 hlatx(1,im,iph),im=1,nmodes 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /Debuginput/test_loading.txt: -------------------------------------------------------------------------------- 1 | 100 2 0.0001 298. nsteps ictrl eqincr temp 2 | * boundary conditions 3 | 0 0 0 iudot | flag for vel.grad. 4 | 1 1 0 | (0:unknown-1:known) 5 | 1 1 0 | 6 | | 7 | -1.E-4 0. 0. udot | vel.grad 8 | 0. 2.E-4 0. | 9 | 0. 0. -1.E-4 | 10 | | 11 | 1 1 1 iscau | flag for Cauchy 12 | 0 1 | 13 | 1 | 14 | | 15 | 0. 0. 0. scauchy | Cauchy stress 16 | 0. 0. | 17 | 0. @ -------------------------------------------------------------------------------- /Debuginput/test_texture.tex: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | B 2 5 | 12.991400 44.190000 2.676700 1.000000 6 | 12.991400 44.190000 2.676700 1.000000 7 | 7.578400 137.460000 17.440000 1.000000 8 | 7.578400 137.460000 17.440000 1.000000 9 | 176.760000 50.424000 59.432000 1.000000 10 | 1.886600 139.400000 23.879000 1.000000 11 | 176.760000 50.424000 59.432000 1.000000 12 | 7.578400 137.460000 17.440000 1.000000 13 | 12.991400 44.190000 2.676700 1.00000 14 | 7.578400 137.460000 17.440000 1.000000 15 | 179.370000 42.080000 55.788000 1.000000 16 | 4.027700 130.780000 16.733000 1.000000 17 | 12.899000 137.900000 3.580300 1.000000 18 | 1.076900 137.780000 5.664100 1.000000 19 | 179.270000 34.321000 41.337000 1.000000 20 | 178.240000 41.687000 53.599000 1.000000 21 | 173.010000 49.841000 16.970000 1.000000 22 | 177.480000 45.013000 18.700000 1.000000 23 | 20.288000 142.820000 39.275000 1.000000 24 | 176.600000 50.881000 17.332000 1.000000 25 | 171.730000 48.742000 25.984000 1.000000 26 | 7.578400 137.460000 17.440000 1.000000 27 | 156.360000 40.596000 48.209000 1.000000 28 | 0.923100 135.600000 27.391000 1.000000 29 | 174.420000 29.034000 17.153000 1.000000 30 | 179.460000 50.332000 45.668000 1.000000 31 | 0.006700 135.460000 33.539000 1.000000 32 | 165.180000 51.556000 35.093000 1.000000 33 | 179.180000 52.103000 59.698000 1.000000 34 | 175.970000 47.926000 11.358000 1.000000 35 | 172.760000 47.807000 24.399000 1.000000 36 | 169.230000 44.742000 49.700000 1.000000 37 | 1.097900 127.660000 57.707000 1.000000 38 | 178.670000 55.204000 35.948000 1.000000 39 | 176.380000 37.139000 56.430000 1.000000 40 | 169.790000 44.575000 25.711000 1.000000 41 | 178.010000 53.489000 55.851000 1.000000 42 | 174.040000 55.479000 25.514000 1.000000 43 | 9.190600 113.480000 36.343000 1.000000 44 | 0.455800 136.060000 32.335000 1.000000 45 | 175.350000 52.916000 46.539000 1.000000 46 | 172.590000 54.158000 52.311000 1.000000 47 | 161.500000 50.521000 5.438200 1.000000 48 | 178.840000 50.459000 2.715800 1.000000 49 | 167.440000 53.697000 1.564900 1.000000 50 | 5.430100 130.610000 46.245000 1.000000 51 | 178.450000 55.175000 44.171000 1.000000 52 | 175.510000 52.855000 16.123000 1.000000 53 | 19.857000 122.410000 14.906000 1.000000 54 | 10.598000 142.600000 4.276300 1.000000 55 | 177.160000 47.708000 49.513000 1.000000 56 | 179.820000 48.586000 26.186000 1.000000 57 | 169.370000 51.314000 2.708700 1.000000 58 | 4.328500 132.700000 19.803000 1.000000 59 | 176.270000 44.042000 44.782000 1.000000 60 | 172.580000 41.397000 33.806000 1.000000 61 | 172.920000 40.510000 30.147000 1.000000 62 | 2.962200 135.190000 22.042000 1.000000 63 | 5.536800 123.430000 4.096300 1.000000 64 | 11.984000 134.600000 4.392700 1.000000 65 | 1.377200 121.830000 28.840000 1.000000 66 | 177.600000 47.798000 55.118000 1.000000 67 | 176.520000 49.523000 41.353000 1.000000 68 | 160.800000 42.746000 33.481000 1.000000 69 | 178.470000 39.207000 22.905000 1.000000 70 | 178.870000 54.266000 4.846500 1.000000 71 | 173.380000 42.865000 37.968000 1.000000 72 | 163.910000 43.084000 42.836000 1.000000 73 | 168.890000 45.080000 31.716000 1.000000 74 | 1.872500 132.360000 12.458000 1.000000 75 | 163.870000 48.102000 34.177000 1.000000 76 | 9.456200 127.620000 49.365000 1.000000 77 | 176.880000 57.232000 40.706000 1.000000 78 | 175.790000 54.502000 8.338200 1.000000 79 | 165.640000 36.952000 40.873000 1.000000 80 | 3.506500 141.360000 39.895000 1.000000 81 | 176.160000 55.102000 49.366000 1.000000 82 | 170.350000 47.094000 53.065000 1.000000 83 | 173.470000 47.169000 35.698000 1.000000 84 | 8.283500 130.390000 1.483000 1.000000 85 | 176.180000 48.833000 19.427000 1.000000 86 | 8.484800 140.710000 51.136000 1.000000 87 | 179.660000 38.802000 4.559500 1.000000 88 | 168.680000 46.831000 12.249000 1.000000 89 | 167.520000 44.413000 38.504000 1.000000 90 | 175.530000 48.309000 37.526000 1.000000 91 | 0.118000 127.030000 9.239200 1.000000 92 | 168.560000 47.733000 18.656000 1.000000 93 | 1.883300 144.500000 45.683000 1.000000 94 | 1.408800 135.540000 6.065400 1.000000 95 | 173.230000 42.886000 37.542000 1.000000 96 | 176.610000 44.958000 25.683000 1.000000 97 | 2.332100 126.890000 38.201000 1.000000 98 | 17.014000 123.930000 25.002000 1.000000 99 | 1.311500 129.220000 9.078400 1.000000 100 | 179.370000 44.052000 52.772000 1.000000 101 | 169.580000 44.575000 25.808000 1.000000 102 | 37.820000 122.700000 13.643000 1.000000 103 | 12.554000 123.700000 49.314000 1.000000 104 | 178.030000 57.544000 50.954000 1.000000 -------------------------------------------------------------------------------- /EVPSC_CPP.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "Input.h" 9 | #include "Processes.h" 10 | #include "Polycrystals.h" 11 | #include "global.h" 12 | 13 | int main() 14 | { 15 | Polycs::polycrystal metal; //declare object 16 | Procs::Process Proc1; 17 | 18 | string ftex, fsx, fload; 19 | if(EVPSCinput(ftex, fsx, fload, Proc1)) exit(0); 20 | if(texinput(ftex, metal)) exit(0); 21 | if(sxinput(fsx, metal)) exit(0); 22 | if(loadinput(fload, Proc1)) exit(0); 23 | 24 | logger.info("EVPSC Start"); 25 | double Start = clock(); 26 | Proc1.loading(metal); 27 | double End = clock(); 28 | double run_time = (double)(End - Start) / CLOCKS_PER_SEC; 29 | cout << "The run time is: " << run_time << " sec" << std::endl; 30 | logger.info("The run time is: " + to_string(run_time) + " sec"); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /EVPSC_CPP.in: -------------------------------------------------------------------------------- 1 | --The path of initial texture: 2 | ./Debuginput/test_texture.tex 3 | --The path of single crystal: 4 | ./Debuginput/Al.sx 5 | --The path of process file: 6 | ./Debuginput/test_loading.txt 7 | 8 | ----Update control---- 9 | update: orientaion, ellipsoid shape, CRSS 10 | 1,0,1 11 | 12 | ----Output control---- 13 | *print the texture every n steps: (0 means only print at the end) 14 | 0 15 | -------------------------------------------------------------------------------- /Grains.cpp: -------------------------------------------------------------------------------- 1 | #include "Grains.h" 2 | using namespace Grains; 3 | 4 | grain::grain(){ 5 | //initial the grain stress&strain 6 | eps_g = Matrix3d::Zero(); 7 | sig_g = Matrix3d::Zero(); 8 | Dije_g = Matrix3d::Zero(); 9 | Dijp_g = Matrix3d::Zero(); 10 | 11 | //initial the shape of ellipsoid 12 | ell_axis_g = Vector3d::Ones(); 13 | ell_axisb_g = Matrix3d::Identity(); 14 | Fij_g = Matrix3d::Identity(); 15 | d0_g = Vector5d::Zero(); 16 | 17 | //initial the VP consistent 18 | Mpij6_g = 1e-8 * Matrix5d::Identity(); 19 | 20 | } 21 | 22 | Vector3d grain::get_ell_axis_g(){return ell_axis_g;} 23 | 24 | Matrix3d grain::get_ell_axisb_g(){return ell_axisb_g;} 25 | 26 | void grain::ini_euler_g(Vector4d vin) 27 | { 28 | Vector3d euler = vin(seq(0,2)); 29 | Euler_M = Euler_trans(euler); 30 | weight = vin(3); 31 | } 32 | 33 | Vector3d grain::get_euler_g(){return Euler_trans(Euler_M);} 34 | 35 | Matrix3d grain::get_Euler_M_g(){return Euler_M;} 36 | 37 | double grain::get_weight_g(){return weight;} 38 | 39 | void grain::set_weight_g(double w){weight = w;} 40 | 41 | int grain::ini_gmode_g(int n) 42 | { 43 | modes_num = n; 44 | gmode = new Modes::mode[n]; 45 | gamma_delta_gmode = new double[n]; 46 | return 1; 47 | } 48 | 49 | int grain::check_gmode_g(){return modes_num;} 50 | 51 | int grain::ini_sn_g(MatrixXd Min, int flag, int system_n, int modei) 52 | { 53 | gmode[modei].ini_sn_mode(Min, flag, system_n); 54 | return 0; 55 | } 56 | 57 | int grain::check_sn_g() 58 | { 59 | for(int i = 0; i < modes_num; i++) 60 | { 61 | cout << "Mode " << i << ":\n"; 62 | gmode[i].check_sn_mode(); 63 | } 64 | return 0; 65 | } 66 | 67 | int grain::ini_hardening_g(double nrsx_in, VectorXd CRSS_p_in, VectorXd hst_in, int modei) 68 | { 69 | 70 | gmode[modei].ini_hardening_mode(nrsx_in, CRSS_p_in, hst_in); 71 | return 0; 72 | } 73 | 74 | int grain::check_hardening_g() 75 | { 76 | for(int i = 0; i < modes_num; i++) 77 | { 78 | cout << "Mode " << i << ":\n"; 79 | gmode[i].check_hardening_mode(); 80 | } 81 | return 0; 82 | } 83 | 84 | void grain::Eshelby_E(double ESIM[3][3][3][3], double ESCR[3][3][3][3], \ 85 | Vector3d axis_t, Matrix6d C66,Integralpoint6 aa6, Integralpoint6 aaww6, Integralpoint3 alpha) 86 | { 87 | int npoints = Intn * Intn; 88 | 89 | double aixabc = axis_t(0)*axis_t(1)*axis_t(2); 90 | //double ratio1 = axis_t(1)/axis_t(2); 91 | //double ratio2 = axis_t(0)/axis_t(2); 92 | 93 | 94 | Matrix6d T66; //Tijkl 95 | T66 = Matrix6d::Zero(); 96 | 97 | Vector6d aa2, aaww2, a1; 98 | Vector6d a1_inv; 99 | Matrix3d a1m; 100 | 101 | double Ro3; 102 | double abcoro3; 103 | for(int ny = 0; ny < npoints; ny++) 104 | { 105 | aa2 = aa6.col(ny); //Take out the Alpha*Alpha 106 | a1 = Mult_voigt(C66,aa2); 107 | //C66(i,j,k,l)*aa2(j,l) 108 | //If solving an elastic inclusion invert the system 109 | //A(3,3) x X(3,3) = C(3,3) 110 | a1m = voigt(a1).inverse(); 111 | a1_inv = voigt(a1m); 112 | 113 | Ro3 =0; 114 | for(int i = 0; i < 3; i++) 115 | Ro3 += pow(alpha(i,ny)*axis_t(i), 2); 116 | Ro3 = pow(Ro3, 1.5); 117 | abcoro3 = aixabc/Ro3; 118 | 119 | //T(M,N,I,J)=A(M)*A(J)*G(N,I) 120 | for(int i = 0; i < 6; i++) 121 | for(int j = 0; j < 6; j++) 122 | T66(i,j) += aaww6(i,ny)*a1_inv(j)*abcoro3; 123 | } 124 | double Tijkl[3][3][3][3]; 125 | voigt(T66, Tijkl); 126 | 127 | // COMPUTE SYMMETRIC (DISTORTION) ESHELBY TENSOR FROM EQ.B9. 128 | // ESIM(N,M,K,L)=0.5*(T(M,J,N,I)+T(N,J,M,I))*C4(I,J,K,L) 129 | // COMPUTE ANTI-SYMMETRIC (ROTATION) ESHELBY TENSOR FROM EQ.B9. 130 | // ESCR(N,M,K,L)=0.5*(T(M,J,N,I)-T(N,J,M,I))*C4(I,J,K,L) 131 | double C4[3][3][3][3]; 132 | voigt(C66, C4); 133 | 134 | double dumsim, dumscr; 135 | for(int l = 0; l < 3; l++) 136 | for(int k = 0; k < 3; k++) 137 | for(int m = 0; m < 3; m++) 138 | for(int n = 0; n < 3; n++) 139 | { 140 | dumsim = 0; 141 | dumscr = 0; 142 | for(int j = 0; j < 3; j++) 143 | for(int i = 0; i < 3; i++) 144 | { 145 | dumsim=dumsim+(Tijkl[m][j][n][i]+Tijkl[n][j][m][i])*C4[i][j][k][l]; 146 | dumscr=dumscr+(Tijkl[m][j][n][i]-Tijkl[n][j][m][i])*C4[i][j][k][l]; 147 | } 148 | ESIM[n][m][k][l]=0.5*dumsim; 149 | ESCR[n][m][k][l]=0.5*dumscr; 150 | } 151 | } 152 | 153 | void grain::Eshelby_P(double ESIM[3][3][3][3],double ESCR[3][3][3][3],\ 154 | Vector3d axis_t, Matrix6d C66,Integralpoint6 aa6, Integralpoint6 aaww6, Integralpoint3 alpha, Integralpoint3 aww, Integralpoint1 ww) 155 | { 156 | int npoints = Intn * Intn; 157 | 158 | double aixabc = axis_t(0)*axis_t(1)*axis_t(2); 159 | //double ratio1 = axis_t(1)/axis_t(2); 160 | //double ratio2 = axis_t(0)/axis_t(2); 161 | 162 | Matrix6d T66; //Tijkl 163 | T66 = Matrix6d::Zero(); 164 | 165 | Matrix3d P; 166 | P = Matrix3d::Zero(); 167 | double PDIL = 0; 168 | 169 | Vector6d aa2, aaww2, a1; 170 | Vector6d a1_inv; 171 | Vector10d a1_10; 172 | Vector10d a1_10_inv; 173 | Matrix4d a1m; 174 | 175 | double Ro3; 176 | double abcoro3; 177 | for(int ny = 0; ny < npoints; ny++) 178 | { 179 | aa2 = aa6.col(ny); //Take out the Alpha*Alpha 180 | a1 = Mult_voigt(C66,aa2); //C66(i,j,k,l)*aa2(j,l) 181 | //refer to Equ[5-14b] in manual 7d) 182 | //solving a visco-plastic inclusion defines componets A1(7) TO A1(10). 183 | //solve the system given by A(4,4) X X(4,4) = C(4,4) 184 | a1_10(seq(0,5)) = a1; 185 | a1_10(6) = alpha(0,ny); 186 | a1_10(7) = alpha(1,ny); 187 | a1_10(8) = alpha(2,ny); 188 | a1_10(9) = 0; 189 | a1m = voigt(a1_10).inverse(); 190 | a1_10_inv = voigt(a1m); 191 | 192 | Ro3 =0; 193 | for(int i = 0; i < 3; i++) 194 | Ro3 += pow(alpha(i,ny)*axis_t(i), 2); 195 | Ro3 = pow(Ro3, 1.5); 196 | abcoro3 = aixabc/Ro3; 197 | 198 | //T(M,N,I,J)=A(M)*A(J)*G(N,I) 199 | for(int i = 0; i < 6; i++) 200 | for(int j = 0; j < 6; j++) 201 | T66(i,j) += aaww6(i,ny)*a1_10_inv(j)*abcoro3; 202 | 203 | for(int j = 0; j < 3; j++) 204 | for(int i = 0; i < 3; i++) 205 | P(i,j) += aww(j,ny)*a1_10_inv(i+6)*abcoro3; 206 | PDIL += ww(ny)*a1_10_inv(9)*abcoro3; 207 | 208 | } 209 | double Tijkl[3][3][3][3]; 210 | voigt(T66, Tijkl); 211 | 212 | // COMPUTE SYMMETRIC (DISTORTION) ESHELBY TENSOR FROM EQ.B9. 213 | // ESIM(N,M,K,L)=0.5*(T(M,J,N,I)+T(N,J,M,I))*C4(I,J,K,L) 214 | // COMPUTE ANTI-SYMMETRIC (ROTATION) ESHELBY TENSOR FROM EQ.B9. 215 | // ESCR(N,M,K,L)=0.5*(T(M,J,N,I)-T(N,J,M,I))*C4(I,J,K,L) 216 | double C4[3][3][3][3]; 217 | voigt(C66, C4); 218 | 219 | double dumsim, dumscr; 220 | for(int l = 0; l < 3; l++) 221 | for(int k = 0; k < 3; k++) 222 | for(int m = 0; m < 3; m++) 223 | for(int n = 0; n < 3; n++) 224 | { 225 | dumsim = 0; 226 | dumscr = 0; 227 | for(int j = 0; j < 3; j++) 228 | for(int i = 0; i < 3; i++) 229 | { 230 | dumsim=dumsim+(Tijkl[m][j][n][i]+Tijkl[n][j][m][i])*C4[i][j][k][l]; 231 | dumscr=dumscr+(Tijkl[m][j][n][i]-Tijkl[n][j][m][i])*C4[i][j][k][l]; 232 | } 233 | ESIM[n][m][k][l]=0.5*dumsim; 234 | ESCR[n][m][k][l]=0.5*dumscr; 235 | } 236 | } 237 | 238 | Matrix3d grain::get_stress_g(){return sig_g;} 239 | 240 | void grain::save_sig_g_old(){sig_g_old = sig_g;} 241 | 242 | Matrix3d grain::get_Dije_g(){return Dije_g;} 243 | Matrix3d grain::get_Dijp_g(){return Dijp_g;} 244 | Matrix3d grain::get_Udot_g(){return Udot_g;} 245 | 246 | //elastic consistent 247 | void grain::Update_Cij6_SA_g(Matrix6d Min){Cij6_SA_g = Min;} 248 | void grain::Update_Mij6_J_g(Matrix6d Min){Mij6_J_g = Min;} 249 | void grain::Update_Metilde_g(Matrix6d Min){Metilde_g = Min;} 250 | void grain::Update_RSinv_C_g(double A[3][3][3][3]) 251 | { 252 | for(int i = 0; i < 3; i++) 253 | for(int j = 0; j < 3; j++) 254 | for(int m = 0; m < 3; m++) 255 | for(int n = 0; n < 3; n++) 256 | RSinv_C[i][j][m][n] = A[i][j][m][n]; 257 | } 258 | Matrix6d grain::get_Mij6_J_g(){return Mij6_J_g;} 259 | 260 | 261 | //visco-plastic consistent 262 | void grain::Update_Mptilde_g(Matrix5d Min){Mptilde_g = Min;} 263 | Matrix5d grain::get_Mpij6_g(){return Mpij6_g;} 264 | Vector5d grain::get_d0_g(){return d0_g;} 265 | void grain::Update_RSinv_VP_g(double A[3][3][3][3]) 266 | { 267 | for(int i = 0; i < 3; i++) 268 | for(int j = 0; j < 3; j++) 269 | for(int m = 0; m < 3; m++) 270 | for(int n = 0; n < 3; n++) 271 | RSinv_VP[i][j][m][n] = A[i][j][m][n]; 272 | } 273 | 274 | void grain::Update_Mpij6_g() 275 | { 276 | Mpij6_g = 1e-8 * Matrix5d::Identity() + cal_Fgrad(sig_g) ; 277 | d0_g = Chg_basis5(Dijp_g) - Mpij6_g * Chg_basis5(sig_g); 278 | } 279 | 280 | void grain::Update_shape_g() 281 | { 282 | //-1 F.transpose()*F 283 | //BX = Matrix3d::Zero(); 284 | //for(int i = 0; i < 3; i++) 285 | // for(int j = 0; j < 3; j++) 286 | // BX(i,j) = Fij_g.row(i)*Fij_g.col(j); 287 | Matrix3d BX; 288 | Matrix3d FT = Fij_g.transpose(); 289 | BX = Fij_g*FT; 290 | //-1 F.transpose()*F 291 | 292 | //-2 solve the eigen vector of BX 293 | //and sort the value from largest to smallest 294 | EigenSolver es(BX); 295 | Matrix3d BX_vectors; 296 | Vector3d BX_value; 297 | BX_value = (es.eigenvalues()).real(); 298 | BX_vectors = (es.eigenvectors()).real(); 299 | Eigsrt(BX_vectors, BX_value); 300 | //-2 solve the eigen vector of BX 301 | //and sort the value from largest to smallest 302 | 303 | Matrix3d B = BX_vectors; 304 | Vector3d W = BX_value; 305 | //-3 306 | //redefine Axis(1) (the second) to be the largest 307 | //to improve the accuracy in calculation of Eshelby tensor 308 | //IF DET(B)<0 MEANS THAT THE SYSTEM IS LEFT HANDED. IT IS MADE RIGHT 309 | //HANDED BY EXCHANGING 1 AND 2. 310 | double Sign = -1; 311 | double temp; 312 | if(B.determinant() <= 0) Sign = 1; 313 | for(int i = 0; i < 3; i++) 314 | { 315 | temp = B(i,0); 316 | B(i,0) = B(i,1); 317 | B(i,1) = temp * Sign; 318 | } 319 | temp = W(0); W(0) = W(1); W(1) = temp; 320 | //-3 321 | 322 | //-4 update the stretching of ellipsoid 323 | double Ratmax=sqrt(W(1)/W(2)); 324 | double Ratmin=sqrt(W(0)/W(2)); 325 | 326 | ell_axisb_g = B; 327 | if(!Iflat_g) //if Iflat_g = 0 328 | for(int i = 0; i < 3; i++) 329 | ell_axis_g(i) = sqrt(W(i)); 330 | //if Iflat_g = 1, the axis of ellipsoid keeps unchange 331 | //-4 update the stretching of ellipsoid 332 | 333 | //-5 update the ellipsoid orientation 334 | Matrix3d BT = B.transpose(); 335 | ellip_ang_g = Euler_trans(B); 336 | //-5 337 | 338 | //-6 Update the Iflat_g according to the Max axes ratio of ellipsoid 339 | if((!Iflat_g)&&(Ratmax >= ell_crit_shape_g)) 340 | { 341 | Iflat_g = 1; 342 | } 343 | //-6 344 | 345 | //-7 Iflat_g = 1; recaculates the Fij_g in grain 346 | else if((Iflat_g)&&(Ratmax >= ell_crit_shape_g)) 347 | { 348 | W(1) = W(1)/4; 349 | if(Ratmin >= 0.5 * ell_crit_shape_g) 350 | W(0) = W(0)/4; 351 | for(int i = 0; i < 3; i++) 352 | ell_axis_g(i) = sqrt(W(i)); 353 | 354 | Matrix3d Fijx; 355 | for(int i = 0; i < 3; i++) 356 | for(int j = 0; j < 3; j++) 357 | Fijx(i,j) = Iij(i,j) * ell_axis_g(i); 358 | 359 | for(int i = 0; i < 3; i++) 360 | for(int j = 0; j < 3; j++) 361 | { 362 | Fij_g(i,j) = 0; 363 | for(int k = 0; k < 3; k++) 364 | for(int l = 0; l < 3; l++) 365 | Fij_g(i,j) = Fij_g(i,j) + B(i,k)*B(j,l)*Fijx(k,l); 366 | } 367 | } 368 | } 369 | 370 | void grain::Update_Fij_g(double Tincr) 371 | { 372 | Matrix3d Fnew; 373 | Fnew = Matrix3d::Zero(); 374 | for(int i = 0; i < 3; i++) 375 | for(int j = 0; j < 3; j++) 376 | for(int k = 0; k < 3; k++) 377 | Fnew(i,j) += (Tincr*Udot_g(i,k)+Iij(i,k))*Fij_g(k,j); 378 | Fij_g = Fnew; 379 | } 380 | 381 | Matrix3d grain::cal_Dijp(Matrix3d Min) 382 | { 383 | //transform into the deviatoric tensor 384 | Matrix3d X = devia(Min); 385 | Matrix3d E = Euler_M; 386 | Matrix3d ET = Euler_M.transpose(); 387 | X = E * X * ET; 388 | 389 | Matrix3d Dijp = Matrix3d::Zero(); 390 | for(int i = 0; i < modes_num; i++) 391 | { 392 | Dijp += gmode[i].cal_dijpmode(X); 393 | } 394 | return ET*Dijp*E; 395 | } 396 | 397 | Matrix3d grain::cal_rotslip() 398 | { 399 | Matrix3d E = Euler_M; 400 | Matrix3d ET = E.transpose(); 401 | 402 | Matrix3d Wij = Matrix3d::Zero(); 403 | for(int i = 0; i < modes_num; i++) 404 | { 405 | Wij += gmode[i].cal_rotslip_m(); 406 | } 407 | return ET*Wij*E; 408 | } 409 | 410 | Matrix5d grain::cal_Fgrad(Matrix3d Min) 411 | { 412 | Matrix3d X = devia(Min); 413 | Matrix3d E = Euler_M; 414 | Matrix3d ET = E.transpose(); 415 | X = E * X * ET; 416 | 417 | Matrix6d Fgrad = Matrix6d::Zero(); 418 | for(int i = 0; i < modes_num; i++) 419 | Fgrad += gmode[i].get_Fgradm(X); 420 | 421 | //return Chg_basis5(rotate_C66(Fgrad, E)); 422 | return Chg_basis5(rotate_C66(Fgrad, ET)); 423 | } 424 | 425 | double grain::cal_RSSxmax(Matrix3d Min) 426 | { 427 | Matrix3d X = devia(Min); 428 | Matrix3d E = Euler_M; 429 | Matrix3d ET = Euler_M.transpose(); 430 | X = E * X * ET; 431 | double RSSxmax = 0; 432 | for(int i = 0; i < modes_num; i++) 433 | { 434 | double temp = gmode[i].get_RSSxM(X); 435 | if(RSSxmax < temp) RSSxmax = temp; 436 | } 437 | return RSSxmax; 438 | } 439 | 440 | double grain::cal_RSSxlim(Matrix3d D) 441 | { 442 | double nrsxmin = 0; 443 | for(int i = 0; i < modes_num; i++) 444 | if(nrsxmin > gmode[i].get_nrsx()) 445 | nrsxmin = gmode[i].get_nrsx(); 446 | 447 | double lim = 2* pow(D.norm()/gmode[0].get_gamma0(),1/nrsxmin); 448 | if(lim < 2) lim = 2; 449 | return lim; 450 | } 451 | 452 | void grain::grain_stress(double Tincr, Matrix3d Wij_m, Matrix3d Dij_m,\ 453 | Matrix3d Dije_AV, Matrix3d Dijp_AV, Matrix3d Sig_m, Matrix3d Sig_m_old) 454 | { 455 | Matrix3d X = sig_g; 456 | 457 | //06.31 458 | //double RSSxlim = cal_RSSxlim(Dij_m); 459 | //double RSSxm = cal_RSSxmax(X); 460 | //if(cal_RSSxmax(X) > RSSxlim) X = X/RSSxm; 461 | //06.31 462 | 463 | 464 | 465 | //-1 466 | //according to Equ[5-30] in manual 467 | //calculate the wij~ 468 | //and the Jaumann rate 469 | Matrix3d wg = Wij_m + mult_4th(RSinv_C,Dije_g-Dije_AV) + mult_4th(RSinv_VP,Dijp_g-Dijp_AV); 470 | 471 | Matrix3d Xjau = wg * X - X * wg; 472 | Matrix3d Sjau = Wij_m * Sig_m - Sig_m * Wij_m; 473 | //-1 474 | 475 | //solve the interaction equation of grain 476 | Vector6d DB = Chg_basis6(Dij_m); 477 | Matrix3d Mt = Sig_m - Sig_m_old + sig_g_old; 478 | DB += Metilde_g * Chg_basis6(Mt)/Tincr \ 479 | + Mij6_J_g * Chg_basis6(sig_g_old)/Tincr; 480 | Mt = Xjau-Sjau; 481 | DB += Mij6_J_g *Chg_basis6(Xjau) + Metilde_g * Chg_basis6(Mt); 482 | DB = Bbasisadd(DB, Mptilde_g * Chg_basis5(Sig_m)); 483 | // 484 | 485 | //Newton-Rapthon iteration 486 | // X(i+1) = X(i) - F/Fgrad 487 | double coef=0.2; 488 | Vector6d Xv = Chg_basis6(X); 489 | Vector6d Xold = Xv; 490 | Vector5d dijpgv; 491 | Vector6d F; 492 | Matrix6d Fgrad; 493 | Matrix6d Mtemp = (Metilde_g + Mij6_J_g)/Tincr; 494 | double err; 495 | double Errm = 1e-3; 496 | for(int it = 0; it < 100; it ++ ) 497 | { 498 | //06.31 499 | //if(cal_RSSxmax(voigt(Xv)) > RSSxlim) 500 | //{Xv = Xold + coef*(Xv-Xold);} 501 | //06.31 502 | Xold = Xv; 503 | 504 | F = -DB + Mtemp * Xv; 505 | F = Bbasisadd(F, Mptilde_g * Chg_basis5(Chg_basis(Xv))); 506 | dijpgv = Chg_basis5(cal_Dijp(Chg_basis(Xv))); 507 | F = Bbasisadd(F,dijpgv); 508 | 509 | Fgrad = -Bbasisadd(Mtemp,Mptilde_g+cal_Fgrad(Chg_basis(Xv))); 510 | //Fgrad = -Bbasisadd(Mtemp,Mptilde_g); 511 | //Fgrad = Bbasisadd(Fgrad,-cal_Fgrad(Chg_basis(Xv))); 512 | 513 | Xv = Xold + Fgrad.inverse() * F; 514 | 515 | err = Errorcal(Xv, Xold); 516 | 517 | if(err < Errm) 518 | { break;}; 519 | if(it == 99) 520 | { 521 | cout << "\n grain stress calculation failed !" << endl; 522 | Xv = Chg_basis6(X) + Chg_basis6(Sig_m) - Chg_basis6(Sig_m_old); 523 | } 524 | 525 | } 526 | //Newton-Rapthon iteration 527 | 528 | sig_g = Chg_basis(Xv); 529 | 530 | Vector6d dijegv = Mij6_J_g *((Xv - Chg_basis6(sig_g_old))/Tincr - Chg_basis6(Xjau)); 531 | Dije_g = Chg_basis(dijegv); 532 | Dijp_g = Chg_basis(dijpgv); 533 | Dij_g = Dije_g + Dijp_g; 534 | 535 | Update_Mpij6_g(); 536 | } 537 | 538 | void grain::Update_shear_strain(double Tincr) 539 | { 540 | double temp = 0; 541 | gamma_delta = 0; 542 | for(int i = 0; i < modes_num; i++) 543 | { 544 | temp = Tincr * gmode[i].Update_shear_strain_m(); 545 | gamma_delta_gmode[i] = temp; 546 | gamma_delta += temp; 547 | } 548 | } 549 | 550 | 551 | void grain::Update_orientation(double Tincr, Matrix3d Wij_m, Matrix3d Dije_AV, Matrix3d Dijp_AV) 552 | { 553 | Wij_g = Wij_m + mult_4th(RSinv_C,Dije_g-Dije_AV) + mult_4th(RSinv_VP,Dijp_g-Dijp_AV); 554 | 555 | Udot_g = Wij_g + Dij_g; //update the velocity gradient in grains 556 | 557 | Matrix3d Rot = (Wij_g - cal_rotslip())*Tincr; 558 | Matrix3d Euler_M_new = Euler_M*Rodrigues(Rot).transpose(); 559 | //Matrix3d Euler_M = Rodrigues(Rot)*Euler_trans(euler); 560 | Euler_M = Euler_M_new; 561 | } 562 | 563 | void grain::Update_CRSS(double Tincr) 564 | { 565 | for(int i = 0; i < modes_num; i++) 566 | gmode[i].Update_CRSS_m(Tincr, gamma_total, gamma_delta, gamma_delta_gmode, modes_num); 567 | gamma_total += gamma_delta; 568 | } -------------------------------------------------------------------------------- /Grains.h: -------------------------------------------------------------------------------- 1 | #ifndef GRAINS_H 2 | #define GRAINS_H 3 | 4 | #include "Modes.h" 5 | #include "Toolbox.h" 6 | 7 | namespace Grains{ 8 | 9 | class grain 10 | { 11 | private: 12 | 13 | Matrix6d Cij6_SA_g; //Elastic stiffness in sample Axes 14 | Matrix6d Mij6_J_g; //Elastic compliance invovling Jaumann rate in sample Axes 15 | Matrix6d Metilde_g; //the (Me~)^-1 in elastic consistency 16 | double RSinv_C[3][3][3][3]; 17 | 18 | Matrix5d Mptilde_g;// the (M~) in elastic consistency 19 | Matrix5d Mpij6_g; // M visco-plastic compliance of grain 20 | double RSinv_VP[3][3][3][3]; 21 | 22 | Vector5d d0_g; 23 | 24 | Matrix3d Fij_g; //the deformation tensor in grain 25 | Matrix3d Udot_g; // the velocity gradient in grain 26 | Matrix3d Dij_g; //the strain rate tensor in grain 27 | Matrix3d Dije_g; //the elastic strain rate tensor in grain 28 | Matrix3d Dijp_g; //the vp strain rate tensor in grain 29 | Matrix3d Wij_g; //the rotation rate tensor in grain 30 | // Udot_g = Dij_g + Wij_g 31 | Matrix3d eps_g; //strain of grain 32 | Matrix3d sig_g; //stress of grain 33 | Matrix3d sig_g_old; //stress in last step 34 | 35 | /////// 36 | //the shape of ellipsoid 37 | //Vector3d ell_axis_o_g; 38 | Vector3d ell_axis_g; //axial length of ellipsoid/grain (_o means the original value) 39 | Matrix3d ell_axisb_g; 40 | double ell_crit_shape_g = 25; 41 | Vector3d ellip_ang_g; //the rotate angle of the ellipsoid 42 | bool Iflat_g = 0; //flag of stretch the ellipsoid (0: yes; 1: no) 43 | /////// 44 | 45 | //Vector3d euler; //Euler angles and weight (/degree) 46 | Matrix3d Euler_M; 47 | double weight; 48 | 49 | Modes::mode* gmode = NULL; // deformation modes 50 | int modes_num = 0; 51 | double* gamma_delta_gmode = NULL; 52 | 53 | double gamma_total = 0; 54 | double gamma_delta = 0; //the increment of gamma 55 | 56 | public: 57 | 58 | int grain_i; // The Number 59 | 60 | grain(); 61 | 62 | //input the euler angle and weights 63 | void ini_euler_g(Vector4d); 64 | Vector3d get_euler_g(); 65 | Matrix3d get_Euler_M_g(); 66 | double get_weight_g(); 67 | void set_weight_g(double); 68 | 69 | //input the number of deformation modes 70 | int ini_gmode_g(int); 71 | int check_gmode_g(); 72 | 73 | //input the normal and Burgers vector in ONE mode (several systems) 74 | //(MatrixXd) sn, (int) flag of twin or slip, (int) number of systems,(int) mode label 75 | int ini_sn_g(MatrixXd, int, int, int); 76 | int check_sn_g(); 77 | 78 | //input the hardening parameters 79 | //input parameters: 80 | //double nrsx_in; VectorXd CRSS_p_in; VectorXd hst_in; int modei 81 | int ini_hardening_g(double, VectorXd, VectorXd, int); 82 | int check_hardening_g(); 83 | 84 | //calculate Eshelby tensor in ESC 85 | //Parameters:: 86 | //double 87 | //Vector3d axis_t, Matrix6d C66, //the axis length of ellipsoid 88 | //Integralpoint6 aa6, Integralpoint6 aaww6, Integralpoint3 alpha // integral points and weights 89 | void Eshelby_E(double ESIM[3][3][3][3],double ESCR[3][3][3][3],Vector3d, Matrix6d, Integralpoint6, Integralpoint6, Integralpoint3); 90 | 91 | //calculate Eshelby tensor in VPSC 92 | //Parameters:: 93 | //Vector3d axis_t, Matrix6d C66, //the axis length of ellipsoid 94 | //Integralpoint6 aa6, Integralpoint6 aaww6, Integralpoint3 alpha // integral points and weights 95 | //Integralpoint3 aww, Integralpoint1 ww 96 | void Eshelby_P(double ESIM[3][3][3][3],double ESCR[3][3][3][3],Vector3d, Matrix6d, Integralpoint6, Integralpoint6, Integralpoint3, Integralpoint3, Integralpoint1); 97 | 98 | //get the stress of grain 99 | Matrix3d get_stress_g(); 100 | 101 | Matrix3d get_Dije_g(); 102 | Matrix3d get_Dijp_g(); 103 | Matrix3d get_Udot_g(); 104 | 105 | void save_sig_g_old(); 106 | 107 | //calculate the stress in grains with Newton-Rapthon iteration 108 | //Parameters: 109 | //double Tincr, 110 | //Matrix3d Wij_m, Matrix3d Dij_AV, Matrix3d Dije_AV, Matrix3d Dijp_AV, 111 | //Matrix3d Sig_m, Matrix3d Sig_m_old 112 | void grain_stress(double, Matrix3d, Matrix3d, Matrix3d, Matrix3d, Matrix3d, Matrix3d); 113 | 114 | //calculate the symmetric components 115 | Matrix3d cal_Dijp(Matrix3d); 116 | 117 | //calculate the skew symmetric components 118 | Matrix3d cal_rotslip(); 119 | 120 | Matrix5d cal_Fgrad(Matrix3d); 121 | 122 | double cal_RSSxmax(Matrix3d); //Calculate the maxinum RSS/CRSS 123 | double cal_RSSxlim(Matrix3d); //Calculate the limit of RSS/CRSS 124 | 125 | //Elastic consistent 126 | void Update_Mij6_J_g(Matrix6d); 127 | void Update_Cij6_SA_g(Matrix6d); 128 | void Update_Metilde_g(Matrix6d); 129 | Matrix6d get_Mij6_J_g(); 130 | void Update_RSinv_C_g(double A[3][3][3][3]); 131 | 132 | //Visco-plastic consistent 133 | void Update_Mpij6_g(); 134 | void Update_Mptilde_g(Matrix5d); 135 | Matrix5d get_Mpij6_g(); 136 | Vector5d get_d0_g(); 137 | void Update_RSinv_VP_g(double A[3][3][3][3]); 138 | 139 | Vector3d get_ell_axis_g(); 140 | Matrix3d get_ell_axisb_g(); 141 | 142 | //if the Ishape = 1(in class polycrys) 143 | // activate these function: 144 | 145 | //according the Fij_g to update the shape; 146 | void Update_shape_g(); 147 | 148 | //according the Udot_g to update the Fij_g; 149 | //parameter: 150 | //double Tincr: the time increment 151 | void Update_Fij_g(double); 152 | 153 | //update the accumulate shear strain in all deformation modes 154 | void Update_shear_strain(double); 155 | 156 | //update the grain orientation 157 | //parameters: 158 | //double Tincr, Matrix3d Wij_m 159 | //Matrix3d Dije_AV, Matrix3d Dijp_AV 160 | void Update_orientation(double, Matrix3d, Matrix3d, Matrix3d); 161 | 162 | //update the CRSS in the deformation systems 163 | //parameter: 164 | //double Tincr 165 | void Update_CRSS(double); 166 | 167 | }; 168 | 169 | } 170 | #endif -------------------------------------------------------------------------------- /Input.h: -------------------------------------------------------------------------------- 1 | #ifndef INPUT_H 2 | #define INPUT_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | using namespace std; 10 | using namespace Eigen; 11 | 12 | #include "Polycrystals.h" 13 | #include "Processes.h" 14 | 15 | int EVPSCinput(string &,string &,string &, Procs::Process &); //read .in file 16 | int sxinput(string, Polycs::polycrystal &); //read .sx file 17 | int texinput(string, Polycs::polycrystal &); //read .tex file 18 | int loadinput(string, Procs::Process &Proc); 19 | VectorXd getnum(string, int); 20 | 21 | int EVPSCinput(string &ftex,string &fsx,string &fload, Procs::Process &Proc) 22 | { 23 | fstream ininp; 24 | ininp.open("EVPSC_CPP.in",ios::in); //open EVPSC.in 25 | if (ininp.is_open()) 26 | { 27 | //read the file path 28 | string tp; 29 | getline(ininp, tp); //skip 30 | getline(ininp, ftex); 31 | getline(ininp, tp); //skip 32 | getline(ininp, fsx); 33 | getline(ininp, tp); //skip 34 | getline(ininp, fload); 35 | 36 | //read the update control 37 | getline(ininp, tp); //skip 38 | getline(ininp, tp); //skip 39 | getline(ininp, tp); //skip 40 | getline(ininp, tp); 41 | VectorXd temp1 = getnum(tp, 3); 42 | Vector3i temp2; 43 | for(int i=0; i<3; i++) 44 | temp2(i) = int(temp1(i)); 45 | Proc.Update_ctrl(temp2); 46 | 47 | //read output control 48 | getline(ininp, tp); //skip 49 | getline(ininp, tp); //skip 50 | getline(ininp, tp); //skip 51 | getline(ininp, tp); 52 | VectorXd temp = getnum(tp, 1); 53 | Proc.Out_texset(int(temp(0))); 54 | 55 | ininp.close(); 56 | return 0; 57 | } 58 | else 59 | { 60 | cout << "Error code 0: loading file cannot be opened.\n"; 61 | return 1; 62 | } 63 | } 64 | 65 | int loadinput(string fname, Procs::Process &Proc) 66 | { 67 | fstream loadinp; 68 | loadinp.open(fname,ios::in); //open load 69 | 70 | if (loadinp.is_open()) 71 | { //checking whether the file is open 72 | string tp; 73 | 74 | //1st line is the loading control option 75 | getline(loadinp, tp); 76 | Vector4d Victrl = getnum(tp, 4); 77 | Proc.load_ctrl(Victrl); 78 | 79 | getline(loadinp, tp);//skip one line 80 | //boundary condition 81 | Matrix3i IUdot; 82 | for(int i = 0; i < 3; i++) 83 | { 84 | getline(loadinp, tp); 85 | Vector3d temp = getnum(tp, 3); 86 | for(int j = 0; j < 3; j++) 87 | IUdot(i,j) = int(temp(j)); 88 | } 89 | Proc.get_IUdot(IUdot); 90 | 91 | getline(loadinp, tp);//skip one line 92 | //boundary condition 93 | Matrix3d Udot; 94 | for(int i = 0; i < 3; i++) 95 | { 96 | getline(loadinp, tp); 97 | Udot.row(i) = getnum(tp, 3); 98 | } 99 | Proc.get_Udot(Udot); 100 | 101 | getline(loadinp, tp);//skip one line 102 | //boundary condition 103 | Vector6i ISdot; 104 | getline(loadinp, tp); 105 | VectorXd temp = getnum(tp, 3); 106 | ISdot(0)=int(temp(0));ISdot(5)=int(temp(1));ISdot(4)=int(temp(2)); 107 | getline(loadinp, tp); 108 | temp = getnum(tp, 2); 109 | ISdot(1)=int(temp(0));ISdot(3)=int(temp(1)); 110 | getline(loadinp, tp); 111 | temp = getnum(tp, 1); 112 | ISdot(2)=int(temp(0)); 113 | 114 | Proc.get_ISdot(ISdot); 115 | 116 | getline(loadinp, tp);//skip one line 117 | //boundary condition 118 | Vector6d Sig_m; 119 | getline(loadinp, tp); 120 | temp = getnum(tp, 3); 121 | Sig_m(0)=temp(0);Sig_m(5)=temp(1);Sig_m(4)=temp(2); 122 | getline(loadinp, tp); 123 | temp = getnum(tp, 2); 124 | Sig_m(1)=temp(0);Sig_m(3)=temp(1); 125 | getline(loadinp, tp); 126 | temp = getnum(tp, 1); 127 | Sig_m(2)=temp(0); 128 | 129 | Proc.get_Sdot(voigt(Sig_m)); 130 | 131 | loadinp.close(); //close the file object. 132 | return 0; 133 | } 134 | else 135 | { 136 | cout << "Error code 0: loading file cannot be opened.\n"; 137 | return 1; 138 | } 139 | } 140 | 141 | int sxinput(string fname, Polycs::polycrystal &pcrys) 142 | { 143 | fstream sxinp; 144 | sxinp.open(fname,ios::in); //open .sx 145 | 146 | if (sxinp.is_open()) 147 | { //checking whether the file is open 148 | string tp; 149 | //skip first line; 150 | getline(sxinp, tp); 151 | //second line: crystal symmetry (crysym) 152 | string crysym; 153 | getline(sxinp, crysym); 154 | crysym = crysym.substr(0,5); 155 | //cout << "crystal symmetry:\n" << crysym << "\n"; 156 | //third line: crystal constant (cdim,cang) 157 | getline(sxinp, tp); 158 | VectorXd ccon = getnum(tp, 6); 159 | //cout << "crystal constant:\n" <= num) break; 331 | Vtemp(i)=stof(results[0].str()); 332 | iter_begin = results[0].second; 333 | i++; 334 | } 335 | return Vtemp; 336 | } 337 | 338 | #endif -------------------------------------------------------------------------------- /Modes.cpp: -------------------------------------------------------------------------------- 1 | #include "Modes.h" 2 | 3 | using namespace Modes; 4 | 5 | int mode::ini_sn_mode(MatrixXd Min, int flag, int system_n) 6 | { 7 | mtype = flag; 8 | system_num = system_n; 9 | if(mtype == 1) 10 | { 11 | sl = new DSystems_Voce::slip[system_num]; 12 | for(int i = 0; i < system_num; i++) 13 | sl[i].ini_sn_s(Min.row(i)); 14 | } 15 | if(mtype == 0) 16 | { 17 | tw = new DSystems_Voce::twin[system_num]; 18 | for(int i = 0; i < system_num; i++) 19 | tw[i].ini_sn_s(Min.row(i)); 20 | } 21 | return 0; 22 | } 23 | 24 | int mode::check_sn_mode() 25 | { 26 | if(mtype == 1) 27 | { 28 | cout << "Slip systems\n"; 29 | for(int i = 0; i < system_num; i++) 30 | sl[i].check_sn_s(); 31 | } 32 | if(mtype == 0) 33 | { 34 | cout << "Twinning systems\n"; 35 | for(int i = 0; i < system_num; i++) 36 | tw[i].check_sn_s(); 37 | } 38 | return 0; 39 | } 40 | 41 | int mode::ini_hardening_mode(double nrsx_in, VectorXd CRSS_p_in, VectorXd hst_in) 42 | { 43 | nrsx = nrsx_in; 44 | hst = hst_in; 45 | if(mtype == 1) 46 | { 47 | for(int i = 0; i < system_num; i++) 48 | sl[i].ini_hardening_s(CRSS_p_in); 49 | } 50 | if(mtype == 0) 51 | { 52 | for(int i = 0; i < system_num; i++) 53 | tw[i].ini_hardening_s(CRSS_p_in); 54 | } 55 | return 0; 56 | } 57 | 58 | int mode::check_hardening_mode() 59 | { 60 | if(mtype == 1) 61 | { 62 | cout << "Slip systems\n"; 63 | for(int i = 0; i < system_num; i++) 64 | sl[i].check_hardening_s(); 65 | } 66 | if(mtype == 0) 67 | { 68 | cout << "Twinning systems\n"; 69 | for(int i = 0; i < system_num; i++) 70 | tw[i].check_hardening_s(); 71 | } 72 | return 0; 73 | } 74 | 75 | double mode::get_gamma0(){return gamma0;} 76 | double mode::get_nrsx(){return nrsx;} 77 | 78 | double mode::get_RSSxM(Matrix3d sig) 79 | { 80 | double temp; 81 | double RSSx = 0; 82 | for(int i = 0; i < system_num; i++) 83 | { 84 | if(mtype == 1) temp = abs(sl[i].cal_RSSx(sig)); 85 | if(mtype == 0) temp = abs(tw[i].cal_RSSx(sig)); 86 | if(RSSx < temp) RSSx = temp; 87 | } 88 | return RSSx; 89 | } 90 | 91 | Matrix3d mode::cal_dijpmode(Matrix3d sig) 92 | { 93 | Matrix3d Pij = Matrix3d::Zero(); 94 | for(int i = 0; i < system_num; i++) 95 | { 96 | if(mtype == 1) Pij += sl[i].cal_dijp_a(sig, nrsx); 97 | if(mtype == 0) Pij += tw[i].cal_dijp_a(sig, nrsx); 98 | } 99 | //cout << "Pij total\t" << Pij << endl; 100 | return Pij; 101 | } 102 | 103 | Matrix3d mode::cal_rotslip_m() 104 | { 105 | Matrix3d wij = Matrix3d::Zero(); 106 | for(int i = 0; i < system_num; i++) 107 | { 108 | if(mtype == 1) wij += sl[i].cal_rotslip_a(); 109 | if(mtype == 0) wij += tw[i].cal_rotslip_a(); 110 | } 111 | return wij; 112 | } 113 | 114 | Matrix6d mode::get_Fgradm(Matrix3d sig) 115 | { 116 | Matrix6d Pij = Matrix6d::Zero(); 117 | for(int i = 0; i < system_num; i++) 118 | { 119 | if(mtype == 1) Pij += sl[i].get_Fgrads(sig, nrsx); 120 | if(mtype == 0) Pij += tw[i].get_Fgrads(sig, nrsx); 121 | } 122 | return Pij; 123 | } 124 | 125 | double mode::Update_shear_strain_m() 126 | { 127 | gamma_rate_abs_m = 0; 128 | for(int i = 0; i < system_num; i++) 129 | { 130 | if(mtype == 1) gamma_rate_abs_m += sl[i].get_gammarate(); 131 | if(mtype == 0) gamma_rate_abs_m += tw[i].get_gammarate(); 132 | } 133 | return gamma_rate_abs_m; 134 | } 135 | 136 | void mode::Update_CRSS_m(double Tincr, double gamma_total, double gamma_delta, double gamma_delta_gmode[], int mode_num) 137 | { 138 | //refer to Eq[C-12] 139 | double Hstpart = 0; 140 | for(int i = 0; i < mode_num; i++) 141 | Hstpart += hst(i)*gamma_delta_gmode[i]; 142 | Hstpart = Hstpart/gamma_delta; 143 | for(int i = 0; i < system_num; i++) 144 | { 145 | if(mtype == 1) sl[i].Update_CRSS_a(Hstpart, gamma_delta, gamma_total); 146 | if(mtype == 0) tw[i].Update_CRSS_a(Hstpart, gamma_delta, gamma_total); 147 | } 148 | } -------------------------------------------------------------------------------- /Modes.h: -------------------------------------------------------------------------------- 1 | #ifndef MODES_H 2 | #define MODES_H 3 | 4 | #include "Systems_Voce.h" 5 | #include "Toolbox.h" 6 | 7 | namespace Modes{ 8 | 9 | //machnical system from which slip&twinning system can be derived 10 | class mode 11 | { 12 | private: 13 | int mtype = 1; //type of deformation modes (1: slip; 0: twin) 14 | int system_num = 0; 15 | DSystems_Voce::slip* sl = NULL; 16 | DSystems_Voce::twin* tw = NULL; 17 | 18 | double gamma0 = 1e-3; //reference shear strain rate 19 | 20 | double gamma_rate_abs_m = 0; //shear strain of one mode 21 | 22 | double nrsx; //rate sensitive 23 | 24 | VectorXd hst; //hst 25 | 26 | public: 27 | int ini_sn_mode(MatrixXd, int, int); 28 | //input the normal and Burgers vector in each system 29 | //(MatrixXd) sn, (int) flag of twin or slip, (int) number of systems 30 | //need loop over systems 31 | int check_sn_mode(); 32 | 33 | int ini_hardening_mode(double, VectorXd, VectorXd); 34 | //input the hardening parameters 35 | //input parameters: 36 | //double nrsx_in; VectorXd CRSS_p_in; VectorXd hst_in 37 | int check_hardening_mode(); 38 | 39 | Matrix3d cal_dijpmode(Matrix3d); 40 | 41 | Matrix3d cal_rotslip_m(); 42 | 43 | Matrix6d get_Fgradm(Matrix3d); 44 | 45 | double get_gamma0(); 46 | double get_nrsx(); 47 | double get_RSSxM(Matrix3d); 48 | 49 | double Update_shear_strain_m(); 50 | 51 | //update the CRSS in each mode 52 | //parameters: 53 | //double Tincr, double gamma_total, double gamma_delta, 54 | //double gamma_delta_gmode[], int modes_num 55 | void Update_CRSS_m(double, double, double, double gamma_delta_gmode[], int); 56 | }; 57 | 58 | } 59 | 60 | #endif -------------------------------------------------------------------------------- /PNGs/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kecheng96/EVPSC_CPP/af3fdbff5186436687d7dee56c9cab374f07c83b/PNGs/.DS_Store -------------------------------------------------------------------------------- /PNGs/Eq1-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kecheng96/EVPSC_CPP/af3fdbff5186436687d7dee56c9cab374f07c83b/PNGs/Eq1-5.png -------------------------------------------------------------------------------- /PNGs/F=FeFp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kecheng96/EVPSC_CPP/af3fdbff5186436687d7dee56c9cab374f07c83b/PNGs/F=FeFp.png -------------------------------------------------------------------------------- /Polycrystals.cpp: -------------------------------------------------------------------------------- 1 | #include "Polycrystals.h" 2 | using namespace Polycs; 3 | using namespace std; 4 | 5 | polycrystal::polycrystal() 6 | { 7 | 8 | //initial the macro stress&strain 9 | Eps_m = Matrix3d::Zero(); 10 | Sig_m = Matrix3d::Zero(); 11 | 12 | //initial the shape of ellipsoid 13 | ell_axis = Vector3d::Ones(); 14 | 15 | ellip_ang << 90,90,90; 16 | ell_axisb = Euler_trans(ellip_ang); 17 | 18 | Fij_m = Matrix3d::Identity(); 19 | 20 | 21 | //initial the VP consistent 22 | M_VP_SC = Matrix5d::Identity(); 23 | M_VP_SC = 1e-8 * M_VP_SC; 24 | C_VP_SC = M_VP_SC.inverse(); 25 | D0 = Vector6d::Zero(); 26 | 27 | Msup<<1,0,0,0,0,0, 28 | 0,1,0,0,0,0, 29 | 0,0,1,0,0,0, 30 | 0,0,0,2,0,0, 31 | 0,0,0,0,2,0, 32 | 0,0,0,0,0,2; 33 | 34 | Vector10d xth,xph,wth,wph; 35 | //integral points and weights 36 | Integralpoint3 alpha, aww; 37 | Integralpoint6 aa6, aaww6; //coordinate and weigts in Fourier space 38 | Integralpoint1 ww; 39 | 40 | Gpsets = new Gausspoint[11]; 41 | 42 | for(int Gpcase = 0; Gpcase < 11; Gpcase++ ){ 43 | switch(Gpcase){ 44 | case 0: 45 | xth << 4.71236594e-02,0.241774723e0,0.565131843e0,0.968887568e0,1.37937832e0, 46 | 1.76221442e0,2.17270517e0,2.57646084e0,2.89981818e0,3.09446883e0; 47 | wth << 0.120191820e0,0.264987558e0,0.373805553e0,0.420841277e0,0.390970200e0, 48 | 0.390970260e0,0.420841366e0,0.373805553e0,0.264987499e0,0.120192111e0; 49 | break; 50 | case 1: 51 | xth << 1.57080423e-02,0.144995824e0,0.425559640e0,0.829968274e0,1.31460333e0, 52 | 1.82698941e0,2.31162453e0,2.71603298e0,2.99659705e0,3.12588477e0; 53 | wth << 5.41692823e-02,0.207461149e0,0.348739326e0,0.452716887e0,0.507709801e0, 54 | 0.507709682e0,0.452716798e0,0.348738998e0,0.207461327e0,5.41692935e-02; 55 | break; 56 | case 2: 57 | xth << 3.76990959e-02,0.198626831e0,0.483041346e0,0.871647120e0,1.32964790e0, 58 | 1.81194484e0,2.26994562e0,2.65855122e0,2.94296598e0,3.10389376e0; 59 | wth << 9.68142375e-02,0.224478707e0,0.341134071e0,0.430180043e0,0.478189558e0, 60 | 0.478189170e0, 0.430180043e0, 0.341134191e0, 0.224478647e0, 9.68143344e-02; 61 | break; 62 | case 3: 63 | xth << 3.45576368e-02,0.187556863e0,0.468425453e0,0.859980166e0,1.32527423e0, 64 | 1.81631863e0,2.28161263e0,2.67316723e0,2.95403576e0,3.10703516e0; 65 | wth << 8.95763785e-02,0.217725381e0,0.341026783e0,0.435772508e0,0.486694932e0, 66 | 0.486695170e0,0.435772508e0,0.341026902e0,0.217725128e0,8.95764604e-02; 67 | break; 68 | case 4: 69 | xth << 3.14158052e-02,0.177928671e0,0.457155794e0,0.851592362e0,1.32222414e0, 70 | 1.81936860e0,2.29000044e0,2.68443704e0,2.96366405e0,3.1101768e0; 71 | wth << 8.26927349e-02,0.213228315e0,0.342008322e0,0.440196186e0,0.492670894e0, 72 | 0.492670983e0,0.440195888e0,0.342008322e0, 0.213227972e0, 8.26930404e-02; 73 | break; 74 | case 5: 75 | xth << 2.98452154e-02,0.173592165e0,0.452448040e0,0.848216832e0,1.32101476e0, 76 | 1.82057810e0,2.29337597e0,2.68914461e0,2.96800065e0,3.11174774e0; 77 | wth << 7.93928578e-02,0.211627841e0,0.342669785e0,0.442057431e0,0.495048553e0, 78 | 0.495048642e0,0.442057490e0,0.342670023e0,0.211627468e0,7.93929026e-02; 79 | break; 80 | case 6: 81 | xth << 2.67036632e-02,0.165752888e0,0.444431901e0,0.842614472e0,1.31902647e0, 82 | 1.82256627e0,2.29897833e0,2.69716072e0,2.97583985e0,3.11488938e0; 83 | wth << 7.30879456e-02,0.209402516e0,0.344104946e0,0.445234656e0,0.498966068e0, 84 | 0.498966306e0,0.445234746e0, 0.344104946e0,0.209402665e0,7.30878562e-02; 85 | break; 86 | case 7: 87 | xth << 2.67036632e-02,0.165752888e0,0.444431901e0,0.842614472e0,1.31902647e0, 88 | 1.82256627e0,2.29897833e0,2.69716072e0,2.97583985e0,3.11488938e0; 89 | wth << 7.30879456e-02,0.209402516e0,0.344104946e0,0.445234656e0,0.498966068e0, 90 | 0.498966306e0,0.445234746e0,0.344104946e0,0.209402665e0,7.30878562e-02; 91 | break; 92 | case 8: 93 | xth <<2.43473575e-02,0.160516247e0,0.439386278e0,0.839168847e0,1.31781363e0, 94 | 1.82377899e0,2.30242372e0,2.70220637e0,2.98107672e0,3.11724544e0; 95 | wth << 6.86219111e-02,0.208388865e0,0.345189095e0,0.447236270e0,0.501360059e0, 96 | 0.501359940e0,0.447236151e0,0.345189214e0,0.208388969e0,6.86219335e-02; 97 | break; 98 | case 9: 99 | xth << 2.19910536e-02,0.155757755e0,0.434985727e0,0.836206555e0,1.31677616e0, 100 | 1.82481658e0,2.30538607e0,2.70660710e0,2.98583508e0,3.11960149e0; 101 | wth << 6.43825606e-02,0.207786217e0,0.346235514e0,0.448981822e0,0.503410578e0, 102 | 0.503410578e0,0.448981792e0,0.346235693e0,0.207785636e0,6.43827692e-02; 103 | break; 104 | case 11: 105 | xth << 2.04204638e-02,0.152822554e0,0.432348520e0,0.834448099e0,1.31616223e0, 106 | 1.82543063e0,2.30714464e0,2.70924401e0,2.98877001e0,3.12117243e0; 107 | wth << 6.16818815e-02,0.207559645e0,0.346902698e0,0.450027168e0,0.504624724e0, 108 | 0.504624426e0,0.450027317e0,0.346902847e0,0.207559645e0,6.16819337e-02; 109 | break; 110 | } 111 | wph = wth; 112 | xph = xth; 113 | double sinth, costh, simbtet; 114 | Matrix3d aa, aaww; 115 | int ny; 116 | for (int ith = 0; ith < Intn; ith++){ 117 | sinth = sin(xth(ith)); 118 | costh = cos(xth(ith)); 119 | simbtet = wth(ith) * sinth / (2.0*M_PI); 120 | 121 | for (int iph = 0; iph < Intn; iph++){ 122 | ny = iph + ith * Intn; 123 | ww(ny) = simbtet*wph(iph); 124 | alpha(0,ny) = sinth*cos(xph(iph)); 125 | alpha(1,ny) = sinth*sin(xph(iph)); 126 | alpha(2,ny) = costh; 127 | // 128 | for(int i = 0; i < 3; i++) 129 | for (int j = 0; j < 3; j++){ 130 | aa(i,j) = alpha(i,ny) * alpha(j,ny); 131 | aaww(i,j) = aa(i,j) * ww(ny); 132 | } 133 | aa6.col(ny) = voigt(aa); 134 | aaww6.col(ny) = voigt(aaww); 135 | for(int i = 0; i < 3; i++) 136 | aww(i,ny) = alpha(i,ny) * ww(ny); 137 | } 138 | } 139 | Gpsets[Gpcase].Gpaa6 = aa6; 140 | Gpsets[Gpcase].Gpaaww6 = aaww6; 141 | Gpsets[Gpcase].Gpalpha = alpha; 142 | Gpsets[Gpcase].Gpaww = aww; 143 | Gpsets[Gpcase].Gpww = ww; 144 | } 145 | } 146 | 147 | 148 | void polycrystal::ini_Udot_m(Matrix3d Udot_input) 149 | { 150 | Udot_m = Udot_input; 151 | Dij_m = 0.5*(Udot_m + Udot_m.transpose()); 152 | Wij_m = 0.5*(Udot_m - Udot_m.transpose()); 153 | 154 | Dij_AV = Dij_m; 155 | Dije_AV = Dij_m; 156 | Dijp_AV = Matrix3d::Zero(); 157 | } 158 | 159 | void polycrystal::ini_Sig_m(Matrix3d Min){Sig_m = Min;} 160 | 161 | void polycrystal::set_IUdot(Matrix3i Min) 162 | { 163 | IUdot = Min; 164 | IDdot(0)=IUdot(0,0); 165 | IDdot(1)=IUdot(1,1); 166 | IDdot(2)=IUdot(2,2); 167 | IDdot(3)=IUdot(1,2)*IUdot(2,1); 168 | IDdot(4)=IUdot(0,2)*IUdot(2,0); 169 | IDdot(5)=IUdot(0,1)*IUdot(1,0); 170 | } 171 | void polycrystal::set_ISdot(Vector6i Min){ISdot = Min;} 172 | 173 | 174 | int polycrystal::grains_n(int n) 175 | { 176 | grains_num = n; 177 | g = new Grains::grain[n]; 178 | //change the number of grains 179 | for(int i = 0; i < n; i++) g[i].grain_i = i; 180 | return 0; 181 | } 182 | 183 | int polycrystal::check_grains_n() 184 | { 185 | cout << "the number of grains:\n" << grains_num << endl; 186 | return grains_num; 187 | //print the number of grains 188 | } 189 | 190 | void polycrystal::ini_euler(Vector4d vin, int i){g[i].ini_euler_g(vin);} 191 | 192 | void polycrystal::Norm_weight() 193 | { 194 | double total_w = 0; 195 | for(int i = 0; i < grains_num; i++) 196 | total_w += g[i].get_weight_g(); 197 | 198 | for(int i = 0; i < grains_num; i++) 199 | g[i].set_weight_g(g[i].get_weight_g()/total_w); 200 | 201 | } 202 | 203 | int polycrystal::ini_cry(string strin, VectorXd vin) 204 | { 205 | //transform str to lower case 206 | for (int i = 0; i < strin.size(); i++) 207 | strin[i] = tolower(strin[i]); 208 | crysym = strin; 209 | Cdim = vin(seq(0,2)); 210 | Cang = vin(seq(3,5)) / 180 * M_PI; //Converting degrees to radians 211 | 212 | //calculate conversion matrix of Miller indices according to the crysym 213 | if(!crysym.compare("hexag")) 214 | { 215 | Miller_n = 4; 216 | MatrixXd Mtemp(3,4); 217 | Trans_Miller = Mtemp; 218 | Trans_Miller << 219 | 1, 0, -1, 0, 220 | 0, 1, -1, 0, 221 | 0, 0, 0, 1; 222 | } 223 | else if(!crysym.compare("cubic")) 224 | { 225 | Miller_n = 3; 226 | MatrixXd Mtemp(3,3); 227 | Trans_Miller = Mtemp; 228 | Trans_Miller << 229 | 1, 0, 0, 230 | 0, 1, 0, 231 | 0, 0, 1; 232 | } 233 | 234 | Mabc(0,0)=sin(Cang(1)); 235 | Mabc(1,0)=0.; 236 | Mabc(2,0)=cos(Cang(1)); 237 | Mabc(0,1)=(cos(Cang(2))-cos(Cang(0))*cos(Cang(1)))/sin(Cang(1)); 238 | Mabc(2,1)=cos(Cang(0)); 239 | Mabc(1,1)=sqrt(1.0-pow(Mabc(0,1),2)-pow(Mabc(2,1),2)); 240 | Mabc(0,2)=0.; 241 | Mabc(1,2)=0.; 242 | Mabc(2,2)=1.; 243 | 244 | for(int i = 0; i < 3; i++) 245 | for(int j = 0; j < 3; j++) 246 | Mabc(i,j) = Cdim(j) * Mabc(i,j); 247 | 248 | return 0; 249 | } 250 | 251 | int polycrystal::get_Millern(){return Miller_n;} 252 | 253 | void polycrystal::check_cry() 254 | { 255 | cout << crysym << endl; 256 | cout << "the cdim and cang:" << endl; 257 | cout << Cdim.transpose() << endl; 258 | cout << Cang.transpose() << endl; 259 | } 260 | 261 | void polycrystal::ini_Cij6(MatrixXd Min) 262 | { 263 | Cij6 = Min; 264 | voigt(Cij6,Cijkl); 265 | } 266 | 267 | int polycrystal::check_Cij6() 268 | { 269 | cout << "elastic constant:\n" << Cij6 << "\n"; 270 | return 0; 271 | } 272 | 273 | int polycrystal::ini_therm(VectorXd vin) 274 | { 275 | therm = vin; 276 | return 0; 277 | } 278 | 279 | int polycrystal::check_therm() 280 | { 281 | cout << "Thermal coefficient:\n" << therm.transpose() << "\n"; 282 | return 0; 283 | } 284 | 285 | int polycrystal::ini_gmode(int n) 286 | { 287 | for(int i = 0; i < grains_num; i++) 288 | { 289 | g[i].ini_gmode_g(n); 290 | } 291 | return 0; 292 | } 293 | 294 | int polycrystal::check_gmode() 295 | { 296 | for(int i = 0; i < grains_num; i++) 297 | { 298 | cout << "the number of modes in Grain " << i << ":\n"; 299 | cout << g[i].check_gmode_g() << endl; 300 | } 301 | return 0; 302 | } 303 | 304 | int polycrystal::ini_sn(MatrixXd Min, int flag, int system_n, int modei) 305 | { 306 | MatrixXd Min_s, Min_n; 307 | 308 | Min_n = Min(all,seq(0,Miller_n-1))*Trans_Miller.transpose(); 309 | Min_s = Min(all,seq(Miller_n,2*Miller_n-1))*Trans_Miller.transpose(); 310 | //calculate the coordinate in Cartesian system 311 | Min_n = Min_n*Mabc.transpose(); 312 | Min_s = Min_s*Mabc.transpose(); 313 | 314 | //normalization 315 | for(int i = 0; i < system_n; i++) 316 | { 317 | Min_n.row(i) = Min_n.row(i).normalized(); 318 | Min_s.row(i) = Min_s.row(i).normalized(); 319 | } 320 | 321 | MatrixXd Min_ns(system_n,6); 322 | Min_ns.block(0,0,system_n,3) = Min_n; 323 | Min_ns.block(0,3,system_n,3) = Min_s; 324 | 325 | for(int i = 0; i < system_n; i++) 326 | for(int j = 0; j < 6; j++) 327 | if(abs(Min_ns(i,j)) <= 1e-3 ) Min_ns(i,j) = 0.0; 328 | 329 | for(int i = 0; i < grains_num; i++) 330 | { 331 | g[i].ini_sn_g(Min_ns, flag, system_n, modei); 332 | } 333 | return 0; 334 | } 335 | 336 | int polycrystal::check_sn() 337 | { 338 | for(int i = 0; i < grains_num; i++) 339 | { 340 | cout << "the deformation system in Grain " << i << ":\n"; 341 | g[i].check_sn_g(); 342 | } 343 | return 0; 344 | } 345 | 346 | int polycrystal::ini_GZ(double x) 347 | { 348 | GZ = x; 349 | return 0; 350 | } 351 | 352 | int polycrystal::ini_hardening(double nrsx_in, VectorXd CRSS_p_in, VectorXd hst_in, int modei) 353 | { 354 | for(int i = 0; i < grains_num; i++) 355 | { 356 | g[i].ini_hardening_g(nrsx_in, CRSS_p_in, hst_in, modei); 357 | } 358 | return 0; 359 | } 360 | 361 | int polycrystal::check_hardening() 362 | { 363 | for(int i = 0; i < grains_num; i++) 364 | { 365 | cout << "the hardening parameters in Grain " << i << ":\n"; 366 | g[i].check_hardening_g(); 367 | } 368 | return 0; 369 | } 370 | 371 | int polycrystal::Selfconsistent_E(int Istep, double ERRM, int ITMAX) 372 | { 373 | //-1 Calculate the Elastic stiffness in Jaumann rate in all grains 374 | //(Rotate from crystal to Sample axes according to the euler angle) 375 | // and sum with the weight 376 | // the result is CUB 377 | Matrix6d CUB; 378 | CUB = Matrix6d::Zero(); 379 | double C4SA[3][3][3][3]; // Elastic stiffness Rotate from crystal to Sample axes 380 | double C4SAS[3][3][3][3]; // ...in Jaumann rate 381 | Matrix3d sig_g; 382 | 383 | //cout << "\nCijkl:\n" << Cij6 << endl; 384 | 385 | double DUMMY = 0; //temporate variable in sum calculation; 386 | 387 | for(int G_n = 0; G_n < grains_num; G_n++) 388 | { 389 | // -2 Rotate the tensor Cijkl in grain to Sample Axes 390 | Matrix3d Euler_M = g[G_n].get_Euler_M_g(); 391 | Matrix3d ET = Euler_M.transpose(); 392 | voigt(rotate_C66(Cij6, ET), C4SA); 393 | g[G_n].Update_Cij6_SA_g(voigt(C4SA)); 394 | // -2 Rotate the tensor Cijkl in grain to Sample Axes 395 | 396 | sig_g = g[G_n].get_stress_g(); 397 | 398 | // -3 ( Eq[2.14] in Wang et al., 2010) 399 | // the elastic stiffness invovling Jaumann rate 400 | for(int i = 0; i < 3; i++) 401 | for(int j = 0; j < 3; j++) 402 | for(int k = 0; k < 3; k++) 403 | for(int l = 0; l < 3; l++) 404 | { 405 | C4SAS[i][j][k][l] = C4SA[i][j][k][l] - sig_g(i,j)*Iij(k,l); 406 | } 407 | // -3 ( Eq[2.14] in Wang et al., 2010) 408 | // the elastic stiffness invovling Jaumann rate 409 | 410 | g[G_n].Update_Mij6_J_g(Chg_basis6(C4SAS).inverse()); 411 | //store the Jaumann rate elastic stiffness in grains 412 | 413 | CUB += Chg_basis6(C4SAS) * g[G_n].get_weight_g(); 414 | 415 | // CUB is the volume average Elastic stiffness of all grains 416 | } 417 | //-1 Calculate the Elastic stiffness in Jaumann rate in all grains 418 | //(Rotate to Sample axes according to the euler angle) 419 | // and sum with the weight 420 | // the result is CUB 421 | 422 | if(Istep == 0) { 423 | CSC = CUB; //first step, use the volume average 424 | SSC = CSC.inverse(); //the initial guess of the elastic compliance 425 | } 426 | //-5 427 | //loop to make the guessed elastic stiffness CSC 428 | // to the Eshelby calculated CNEW 429 | Matrix6d SSC_new; 430 | 431 | int IT = 0; //loop flag 432 | double RER = 2*ERRM; 433 | while((RER >= ERRM) && (IT < ITMAX)) 434 | { 435 | IT++; 436 | SSC_new = Matrix6d::Zero(); 437 | 438 | Chg_basis(CSC, C4SA); 439 | 440 | Matrix6d Ctilde; 441 | Matrix6d S66; //the Sijkl Equ[5-33] in sample axes in Manual 7d 442 | double R4_SA[3][3][3][3]; //PIijkl 443 | double RSinv_SA[3][3][3][3]; 444 | Matrix6d S66inv; 445 | Matrix3d axisb_t; 446 | Vector3d axis_t; 447 | Matrix6d Me_g; 448 | 449 | //solve the eshelby tensor in the common ellipsoid 450 | if(Ishape == 0) 451 | { 452 | //-4 453 | //rotate the macro Elastic stiffness 454 | //from Sample axes to the ellipsoid axes; 455 | // if Ishape = 0, which means the grains share the same ellipsoid axes 456 | axisb_t = ell_axisb; 457 | axis_t = ell_axis; 458 | //Rotate the self consistent Elastic stiffness (CSC) 459 | //from sample axes to ellipsoid axes 460 | Matrix6d C66 = rotate_C66(voigt(C4SA), axisb_t.transpose()); 461 | //-4 462 | 463 | //-9 464 | //calculate the Eshelby tensor 465 | double S4_EA[3][3][3][3] = {0}; 466 | double R4_EA[3][3][3][3] = {0}; 467 | 468 | int case_c = Eshelby_case(axis_t); 469 | g[0].Eshelby_E(S4_EA,R4_EA,axis_t,C66,Gpsets[case_c].Gpaa6,Gpsets[case_c].Gpaaww6,Gpsets[case_c].Gpalpha); 470 | //-9 471 | 472 | //-10 473 | //rotate the eshelby tensor 474 | //back to the sample axes 475 | S66 = voigttoB6(rotate_C66(voigt(S4_EA), axisb_t)); 476 | rot_4th(R4_EA, axisb_t, R4_SA); 477 | //-10 478 | 479 | //-11 480 | //Calculate Ctilde 481 | //refer to Equ[5-33] in Manual 7d 482 | //M~=(I-S)^-1 * S * M 483 | //but here we used C~ = (M~)^-1 484 | //that is 485 | // C~ = C * (S^-1 - I) 486 | //-12 calculate (S)^-1 487 | S66inv = S66.inverse(); // 6x6 of S^-1 488 | Matrix6d S66inv_I; // 6x6 of (S^-1 - I) 489 | //for(int i = 0; i < 6; i++) 490 | // for(int j = 0; j < 6; j++) 491 | // S66inv_I(i,j) = S66inv(i,j) - Iij(i,j); 492 | S66inv_I = S66inv - Matrix6d::Identity(); 493 | //-12 494 | // C~ = C * (S^-1 - I) 495 | Ctilde = CSC * S66inv_I; 496 | //-11 497 | } 498 | //end of Ishape == 0 499 | 500 | for(int G_n = 0; G_n < grains_num; G_n++) 501 | { 502 | //solve the eshelby tensor in all the ellipsoid of grain 503 | if(Ishape == 1) 504 | { 505 | //-7 506 | //rotate the macro Elastic stiffness 507 | //from Sample axes to the ellipsoid axes; 508 | // if Ishape = 1, which means the ellipsoid axes varies in grains, 509 | axis_t = g[G_n].get_ell_axis_g(); 510 | axisb_t = g[G_n].get_ell_axisb_g(); 511 | Matrix6d C66 = rotate_C66(CSC, axisb_t.transpose()); 512 | 513 | //-9 514 | //calculate the Eshelby tensor 515 | double S4_EA[3][3][3][3] = {0}; 516 | double R4_EA[3][3][3][3] = {0}; 517 | int case_c = Eshelby_case(axis_t); 518 | g[G_n].Eshelby_E(S4_EA,R4_EA,axis_t,C66,Gpsets[case_c].Gpaa6,Gpsets[case_c].Gpaaww6,Gpsets[case_c].Gpalpha); 519 | //-9 520 | 521 | //-10 522 | //rotate the eshelby tensor 523 | //back to the sample axes 524 | S66 = rotate_C66(voigt(S4_EA), axisb_t); 525 | rot_4th(R4_EA, axisb_t, R4_SA); 526 | //-10 527 | 528 | //-11 529 | //Calculate Ctilde 530 | //refer to Equ[5-33] in Manual 7d 531 | //M~=(I-S)^-1 * S * M 532 | //but here we used C~ = (M~)^-1 533 | //that is 534 | // C~ = C * (S^-1 - I) 535 | //-12 calculate (S)^-1 536 | S66inv = S66.inverse(); // 6x6 of S^-1 537 | Matrix6d S66inv_I; // 6x6 of (S^-1 - I) 538 | //for(int i = 0; i < 6; i++) 539 | // for(int j = 0; j < 6; j++) 540 | // S66inv_I(i,j) = S66inv(i,j) - Iij(i,j); 541 | S66inv_I = S66inv - Matrix6d::Identity(); 542 | //-12 543 | // C~ = C * (S^-1 - I) 544 | Ctilde = CSC * S66inv_I; 545 | //-11 546 | } 547 | //-7 end of Ishape == 1; 548 | 549 | 550 | //-13 store some matrix into grain 551 | //store the C~ 552 | g[G_n].Update_Metilde_g(Ctilde.inverse()); 553 | //store the PI*(S^-1) 554 | double S66inv4th[3][3][3][3] = {0}; 555 | Chg_basis(S66inv,S66inv4th); 556 | mult_4th(R4_SA,S66inv4th,RSinv_SA); 557 | g[G_n].Update_RSinv_C_g(RSinv_SA); 558 | //-13 559 | 560 | //-14 561 | //Calculate the localization tensor B_g 562 | // _g means the value depends on the grain 563 | //refer to Equ[5-35] in Manual 7d 564 | // B_g = (M_g + M~)^-1 * (M_ + M~) 565 | Matrix6d Metilde = Ctilde.inverse(); 566 | Me_g = g[G_n].get_Mij6_J_g(); 567 | Matrix6d Part1 = Me_g + Metilde; 568 | Matrix6d Part1_inv = Part1.inverse(); 569 | Matrix6d Part2 = SSC + Metilde; 570 | Matrix6d B_g = Part1_inv * Part2; 571 | //-14 572 | 573 | /////// 574 | //-15 575 | //Calculate the New elastic consistent stiffness CNEW 576 | //refer to Equ[5-40a] in Manual 7d 577 | SSC_new += Me_g * B_g * g[G_n].get_weight_g(); 578 | //-15 579 | } //loop over grains 580 | 581 | //cout << "\nThe CNEW:\n" << CNEW << endl; 582 | //-16 583 | //error between CSC and CNEW 584 | RER=Errorcal(SSC,SSC_new); 585 | SSC = 0.5*(SSC_new+SSC_new.transpose()); 586 | CSC = SSC.inverse(); 587 | //-16 588 | cout << "**Error in ESC iteration_" << IT << ":\t" << RER << endl; 589 | 590 | } //while loop 591 | 592 | //SSC = Msup * Btovoigt(CSC.inverse()); 593 | 594 | return 0; 595 | } 596 | 597 | int polycrystal::Selfconsistent_P(int Istep, double ERRM, int ITMAX) 598 | { 599 | Matrix5d MNEW; //VP compliance updated in every do-while 600 | Vector5d D0_new; //the back-extrapolated term updated in every do-while 601 | Matrix5d B_g_ave; // in Equ[5-41a] average of B_g 602 | Vector5d b_g_ave; // in Equ[5-41b] average of b_g 603 | 604 | double DUMMY; 605 | 606 | int IT = 0; //loop flag 607 | double RER = 2*ERRM; 608 | while((RER >= ERRM) && (IT < ITMAX)) 609 | { 610 | IT++; 611 | 612 | MNEW = Matrix5d::Zero(); 613 | B_g_ave = Matrix5d::Zero(); 614 | D0_new = Vector5d::Zero(); 615 | b_g_ave = Vector5d::Zero(); 616 | // 617 | Matrix5d Mtilde; 618 | Matrix5d S55;//the Sijkl Equ[5-33] in sample axes in Manual 7d 619 | double R4_SA[3][3][3][3]; //PIijkl 620 | double RSinv_SA[3][3][3][3]; 621 | Matrix5d S55_inv; 622 | Matrix5d R55; 623 | Matrix3d axisb_t; 624 | Vector3d axis_t; 625 | // 626 | 627 | //solve the eshelby tensor in the common ellipsoid 628 | if(Ishape == 0) 629 | { 630 | //-1 631 | //rotate the macro VP stiffness (C_VP_SC) 632 | //from Sample axes to the ellipsoid axes; 633 | // if Ishape = 0, which means the ellipsoid axes 634 | // keep unchanged in grains, 635 | // the transform matrix should be taken from 636 | // the polycrystal 637 | axisb_t = ell_axisb; 638 | axis_t = ell_axis; 639 | 640 | Matrix6d C66 = rotate_C66(Btovoigt(C_VP_SC), axisb_t.transpose()); 641 | //-1 642 | 643 | //-3 644 | //Calculate Eshelby tensor 645 | double S4_EA[3][3][3][3] = {0}; 646 | double R4_EA[3][3][3][3] = {0}; 647 | 648 | int case_c = Eshelby_case(axis_t); 649 | g[0].Eshelby_P(S4_EA,R4_EA,axis_t,C66,Gpsets[case_c].Gpaa6,Gpsets[case_c].Gpaaww6,\ 650 | Gpsets[case_c].Gpalpha,Gpsets[case_c].Gpaww,Gpsets[case_c].Gpww); 651 | //-3 652 | 653 | //-4 654 | //rotate the eshelby tensor 655 | //back to the sample axes 656 | S55 = voigttoB5(rotate_C66(voigt(S4_EA), axisb_t)); 657 | rot_4th(R4_EA, axisb_t, R4_SA); 658 | //-4 659 | 660 | //Calculate Mtilde 661 | //refer to Equ[5-33] in Manual 7d 662 | //M~=(I-S)^-1 * S * M 663 | Matrix5d I_S55, I_S55_inv; // (I-S) and (I-S)^-1 664 | //for(int i = 0; i < 5; i++) 665 | // for(int j = 0; j < 5; j++) 666 | // I_S55(i,j) = Iij(i,j) - S55(i,j); 667 | I_S55 = Matrix5d::Identity() - S55; 668 | I_S55_inv = I_S55.inverse(); 669 | 670 | Mtilde = I_S55_inv * S55 * M_VP_SC; 671 | S55_inv = S55.inverse(); 672 | } 673 | //-1 674 | 675 | 676 | DVP_AV = Vector5d::Zero(); 677 | 678 | for(int G_n = 0; G_n < grains_num; G_n++) 679 | { 680 | //-2 681 | //rotate the macro VP stiffness 682 | //from Sample axes to the ellipsoid axes; 683 | // if Ishape = 1, which means the ellipsoid axes varies in grains, 684 | // the transform matrix should be taken out of 685 | // each grain 686 | if(Ishape == 1) 687 | { 688 | axis_t = g[G_n].get_ell_axis_g(); 689 | axisb_t = g[G_n].get_ell_axisb_g(); 690 | Matrix6d C66 = rotate_C66(Btovoigt(C_VP_SC), axisb_t.transpose()); 691 | 692 | //Calculate Eshelby tensor 693 | double S4_EA[3][3][3][3] = {0}; 694 | double R4_EA[3][3][3][3] = {0}; 695 | int case_c = Eshelby_case(axis_t); 696 | g[G_n].Eshelby_P(S4_EA,R4_EA,axis_t,C66,Gpsets[case_c].Gpaa6,Gpsets[case_c].Gpaaww6,\ 697 | Gpsets[case_c].Gpalpha,Gpsets[case_c].Gpaww,Gpsets[case_c].Gpww); 698 | //-3 699 | 700 | //-4 701 | //rotate the eshelby tensor 702 | //back to the sample axes 703 | S55 = voigttoB5(rotate_C66(voigt(S4_EA), axisb_t)); 704 | rot_4th(R4_EA, axisb_t, R4_SA); 705 | //-4 706 | 707 | //-4 708 | //Calculate Mtilde 709 | //refer to Equ[5-33] in Manual 7d 710 | //M~=(I-S)^-1 * S * M 711 | Matrix5d I_S55, I_S55_inv; // (I-S) and (I-S)^-1 712 | //for(int i = 0; i < 5; i++) 713 | // for(int j = 0; j < 5; j++) 714 | // I_S55(i,j) = Iij(i,j) - S55(i,j); 715 | I_S55 = Matrix5d::Identity() - S55; 716 | I_S55_inv = I_S55.inverse(); 717 | 718 | Mtilde = I_S55_inv * S55 * M_VP_SC; 719 | S55_inv = S55.inverse(); 720 | } 721 | //-2 722 | 723 | //-5 store some matrix into grain 724 | //store the M~ 725 | g[G_n].Update_Mptilde_g(Mtilde); 726 | //only affine case (interaction = 1) 727 | //store the PI*(S^-1) 728 | double S66inv4th[3][3][3][3] = {0}; 729 | Chg_basis(S55.inverse(),S66inv4th); 730 | mult_4th(R4_SA,S66inv4th,RSinv_SA); 731 | g[G_n].Update_RSinv_VP_g(RSinv_SA); 732 | //06.02 733 | //-5 734 | 735 | //07.14 736 | //Matrix5d M_g = voigttoB5(g[G_n].get_Mpij6_g()); 737 | //Vector5d d0_g = Chg_basis5(g[G_n].get_d0_g()); 738 | Matrix5d M_g = g[G_n].get_Mpij6_g(); 739 | Vector5d d0_g = g[G_n].get_d0_g(); 740 | 741 | double wei = g[G_n].get_weight_g(); 742 | 743 | //-6 744 | //Calculate the localization tensor B_g 745 | // _g means the value depends on the grain 746 | //refer to Equ[5-35] in Manual 7d 747 | // B_g = (M_g + M~)^-1 * (M_ + M~) 748 | Matrix5d Part1 = M_g + Mtilde; 749 | Matrix5d Part1_inv = Part1.inverse(); 750 | Matrix5d Part2 = M_VP_SC + Mtilde; 751 | Matrix5d B_g = Part1_inv * Part2; 752 | /// 753 | //refer to Equ[5-35] in Manual 7d 754 | // b_g = (M_g + M~)^-1 * (d- - d-_g) 755 | //Matrix3d dtemp = voigt(D0) - d0_g;//(d- - d-_g) 756 | //Vector6d b_gv = voigt5to6(Part1_inv) * Msupinv * voigt(dtemp); 757 | Vector5d b_gv = Part1_inv * (Chg_basis5(voigt(D0))-d0_g); 758 | //Matrix3d b_g = voigt(b_gv); 759 | //-6 760 | 761 | // MNEW = 762 | // Equ[5-40a] 763 | MNEW += M_g * B_g * wei; 764 | // 765 | B_g_ave += B_g * wei; 766 | // Equ[5-40b] 767 | // < M_g * b_g + d0_g> 768 | //Vector6d Mr_br = voigt5to6(M_g) * Msupinv * b_gv; // M_g * b_g 769 | Vector5d Mr_br = M_g * b_gv; 770 | D0_new += ( d0_g + Mr_br ) * wei; // < M_g * b_g + d0_g> 771 | // 772 | b_g_ave += b_gv * wei; 773 | 774 | //06.06 775 | DVP_AV += Chg_basis5(g[G_n].get_Dijp_g()) * wei; 776 | //06.06 777 | 778 | } //loop over grains 779 | 780 | // Equ[5-41a] 781 | // * ^-1 782 | MNEW = MNEW * B_g_ave.inverse(); 783 | Matrix5d MNEW2 = 0.5*(MNEW+MNEW.transpose()); 784 | MNEW = MNEW2; 785 | // Equ[5-41b] 786 | // < M_g * b_g + d0_g> - * ^-1 * 787 | // * ^-1 * 788 | //Vector6d M_bg = voigt5to6(MNEW) * Msupinv * b_g_ave; 789 | Vector5d M_bg = MNEW * b_g_ave; 790 | D0_new = D0_new - M_bg; 791 | 792 | //calculate the error between 793 | //the input M_VP_SC of do-while loop 794 | //and the output MNEW of the loop 795 | RER = Errorcal(M_VP_SC, MNEW); 796 | M_VP_SC = MNEW; 797 | D0 = voigt(Chg_basis(D0_new)); 798 | 799 | C_VP_SC = M_VP_SC.inverse(); 800 | 801 | cout << "**Error in VPSC iteration_" << IT << ":\t" << RER << endl; 802 | }//while loop 803 | return 0; 804 | } 805 | 806 | 807 | int polycrystal::Update_Fij(double Tincr) 808 | { 809 | Matrix3d Fnew; 810 | Fnew = Matrix3d::Zero(); 811 | for(int i = 0; i < 3; i++) 812 | for(int j = 0; j < 3; j++) 813 | for(int k = 0; k < 3; k++) 814 | { 815 | Fnew(i,j) += (Tincr*Udot_AV(i,k)+Iij(i,k))*Fij_m(k,j); 816 | } 817 | Fij_m = Fnew; 818 | return 0; 819 | } 820 | 821 | int polycrystal::Update_shape() 822 | { 823 | //-1 F.transpose()*F 824 | //BX = Matrix3d::Zero(); 825 | //for(int i = 0; i < 3; i++) 826 | // for(int j = 0; j < 3; j++) 827 | // BX(i,j) = Fij_g.row(i)*Fij_g.col(j); 828 | Matrix3d BX; 829 | Matrix3d FT = Fij_m.transpose(); 830 | BX = Fij_m*FT; 831 | //-1 F.transpose()*F 832 | 833 | //-2 solve the eigen vector of BX 834 | //and sort the value from largest to smallest 835 | //EigenSolver es(BX); 836 | Matrix3d BX_vectors; 837 | Vector3d BX_value; 838 | Jacobi(BX,BX_value,BX_vectors); 839 | //BX_value = (es.eigenvalues()).real(); 840 | //BX_vectors = (es.eigenvectors()).real(); 841 | 842 | Eigsrt(BX_vectors, BX_value); 843 | 844 | //-2 solve the eigen vector of BX 845 | //and sort the value from largest to smallest 846 | 847 | Matrix3d B = BX_vectors; 848 | Vector3d W = BX_value; 849 | //-3 850 | //redefine Axis(1) (the second) to be the largest 851 | //to improve the accuracy in calculation of Eshelby tensor 852 | //IF DET(B)<0 MEANS THAT THE SYSTEM IS LEFT HANDED. IT IS MADE RIGHT 853 | //HANDED BY EXCHANGING 1 AND 2. 854 | double Sign = -1; 855 | double temp; 856 | if(B.determinant() <= 0) Sign = 1; 857 | for(int i = 0; i < 3; i++) 858 | { 859 | temp = B(i,0); 860 | B(i,0) = B(i,1); 861 | B(i,1) = temp * Sign; 862 | } 863 | temp = W(0); W(0) = W(1); W(1) = temp; 864 | //-3 865 | 866 | //-4 update the stretching of ellipsoid 867 | double Ratmax=sqrt(W(1)/W(2)); 868 | double Ratmin=sqrt(W(0)/W(2)); 869 | 870 | ell_axisb = B; 871 | if(!Iflat) //if Iflat = 0 872 | for(int i = 0; i < 3; i++) 873 | ell_axis(i) = sqrt(W(i)); 874 | //if Iflat = 1, the axis of ellipsoid keeps unchange 875 | //-4 update the stretching of ellipsoid 876 | 877 | //-5 update the ellipsoid orientation 878 | Matrix3d BT = B.transpose(); 879 | ellip_ang = Euler_trans(BT); 880 | 881 | //-5 882 | 883 | //-6 Update the Iflat_g according to the Max axes ratio of ellipsoid 884 | if((!Iflat)&&(Ratmax >= ell_crit_shape)) 885 | { 886 | Iflat = 1; 887 | } 888 | //-6 889 | 890 | //-7 Iflat_g = 1; recaculates the Fij_g in grain 891 | else if((Iflat)&&(Ratmax >= ell_crit_shape)) 892 | { 893 | W(1) = W(1)/4; 894 | if(Ratmin >= 0.5 * ell_crit_shape) 895 | W(0) = W(0)/4; 896 | for(int i = 0; i < 3; i++) 897 | ell_axis(i) = sqrt(W(i)); 898 | 899 | Matrix3d Fijx; 900 | for(int i = 0; i < 3; i++) 901 | for(int j = 0; j < 3; j++) 902 | Fijx(i,j) = Iij(i,j) * ell_axis(i); 903 | 904 | for(int i = 0; i < 3; i++) 905 | for(int j = 0; j < 3; j++) 906 | { 907 | Fij_m(i,j) = 0; 908 | for(int k = 0; k < 3; k++) 909 | for(int l = 0; l < 3; l++) 910 | Fij_m(i,j) = Fij_m(i,j) + B(i,k)*B(j,l)*Fijx(k,l); 911 | } 912 | } 913 | return 0; 914 | } 915 | 916 | 917 | int polycrystal::EVPSC(int istep, double Tincr,\ 918 | bool Iupdate_ori,bool Iupdate_shp,bool Iupdate_CRSS) 919 | { 920 | double errd, errs, err_g; 921 | cout << "********STEP********\n\t" \ 922 | << istep << endl << "********STEP********\n"; 923 | 924 | Sig_m_old = Sig_m; //save the stress of the last step 925 | for(int G_n = 0; G_n < grains_num; ++G_n) 926 | g[G_n].save_sig_g_old();//save the grain stress of the last step 927 | 928 | for(int i = 0; i < 30; ++i) 929 | { 930 | //save the input for error calculation 931 | Sig_in = Sig_m; 932 | Dij_in = Dij_m; 933 | sig_in_AV = Matrix3d::Zero(); 934 | 935 | for(int G_n = 0; G_n < grains_num; ++G_n) 936 | sig_in_AV += g[G_n].get_stress_g() * g[G_n].get_weight_g(); 937 | 938 | /////////// 939 | cout << "iteration: " << i+1 << endl; 940 | Selfconsistent_E(istep, SC_err_m, SC_iter_m); 941 | Selfconsistent_P(istep, SC_err_m, SC_iter_m); 942 | Cal_Sig_m(Tincr); 943 | Cal_Sig_g(Tincr); 944 | Update_AV(); 945 | /////////// 946 | 947 | errs = Errorcal(Sig_m, Sig_in); 948 | errd = Errorcal(Dij_m, Dij_in); 949 | err_g = Errorcal(Sig_AV, sig_in_AV); 950 | 951 | cout << "\nerr_s:\t" << errs << endl; 952 | cout << "err_d:\t" << errd << endl; 953 | cout << "err_g:\t" << err_g << endl; 954 | cout << "=-=-=-=-=-=-=-=-=-=\n"; 955 | if((errs 5 | #include 6 | #include 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | #include "Grains.h" 12 | #include "Toolbox.h" 13 | 14 | namespace Polycs{ 15 | 16 | //const int max_grain_n = 3000; 17 | 18 | class polycrystal 19 | { 20 | private: 21 | Grains::grain* g = NULL; 22 | int grains_num = 0; 23 | 24 | double GZ = 30; //grain size (um) 25 | 26 | Gausspoint* Gpsets = NULL; 27 | 28 | string crysym; //crystal symmetry 29 | MatrixXd Trans_Miller;// the conversion matrix of Miller indices 30 | int Miller_n = 3;// the number of the Miller indices (3 or 4(hcp)) 31 | Matrix3d Mabc; 32 | 33 | Vector3d Cdim; //lattice constant 34 | Vector3d Cang; //lattice constant 35 | Vector6d therm; //Thermal expansion coefficients [K^(-1)] 36 | double Temp; // /(K^-1) 37 | 38 | //the shape of ellipsoid 39 | //Vector3d ell_axis_o; 40 | Vector3d ell_axis; //axial length of ellipsoid/grain (_o means the original value) 41 | Matrix3d ell_axisb; 42 | double ell_crit_shape = 25; 43 | Vector3d ellip_ang; //the rotate angle of the ellipsoid 44 | bool Iflat = 0; //flag of stretch the ellipsoid (0: yes; 1: no) 45 | bool Ishape = 0; //flag of individual ellipsoid for grain (1: yes; 0: no) 46 | /////// 47 | 48 | double Cijkl[3][3][3][3]; //elastic constants 3X3X3X3 49 | Matrix6d Cij6; //elastic constants 6X6 of crystal 50 | //ESC 51 | Matrix6d CSC; //The elastic consistent stiffness 52 | Matrix6d COLD;//The initial guessed elastic consistent stiffness 53 | Matrix6d SSC; //CSC^-1 54 | //VPSC 55 | Matrix5d C_VP_SC; //The visco-plastic stiffness 56 | Matrix5d M_VP_SC; //The visco-plastic compliance C_VP_SC^-1 57 | Vector6d D0; //the macro back-extrapolated term (follow Equ[5-41b]) 58 | 59 | Vector5d DVP_AV; 60 | 61 | Matrix3d Fij_m; //the macro deformation tensor in grain 62 | Matrix3d Udot_m; //the macro velocity gradient; 63 | Matrix3i IUdot; //the flag of known (control by Udot_m) and unknown (calculated by EVPSC) velocity components 64 | Vector6i IDdot; //the flag of known and unknown strain rate components 65 | Vector6i ISdot; //the flag of known and unknown stress componets 66 | 67 | Matrix3d Dij_m; //the macro strain rate tensor 68 | Matrix3d Wij_m; //the macro rotation rate tensor 69 | Matrix3d Udot_AV; 70 | // Udot_m = Dij_m + Wij_m 71 | Matrix3d Dij_AV; //the average strain rate tensor of all garins 72 | Matrix3d Dije_AV; //the elastic part 73 | Matrix3d Dijp_AV; //the vp part 74 | 75 | Matrix3d Eps_m; //macro strain 76 | Matrix3d Sig_m; //macro stress 77 | Matrix3d Sig_AV; //the average stress tensor of all garins 78 | Matrix3d Sig_m_old; //macro stress in last increment 79 | 80 | //some parameters for error control and iteration control 81 | double SC_err_m = 0.01; //the error limit of Self-consistent compliance or stiffness 82 | int SC_iter_m = 20; //the max iteration number of SC 83 | double errD_m = 0.01; //error limit between the input macro strain rate and output at each iteration 84 | double errS_m = 0.01; //error limit of the macro stress 85 | double err_g_AV = 0.01; //error limit of the average grain stress 86 | 87 | Matrix3d Sig_in; 88 | Matrix3d Dij_in; 89 | Matrix3d sig_in_AV; 90 | 91 | Matrix6d Msup; 92 | 93 | public: 94 | polycrystal(); 95 | 96 | void ini_Udot_m(Matrix3d); 97 | void ini_Sig_m(Matrix3d); 98 | void set_IUdot(Matrix3i); 99 | void set_ISdot(Vector6i); 100 | 101 | //input the number of grains 102 | int grains_n(int); 103 | int check_grains_n(); 104 | 105 | //input the euler angles and weights 106 | //needs loop over grains 107 | void ini_euler(Vector4d, int); 108 | void Norm_weight(); 109 | 110 | int ini_cry(string, VectorXd); 111 | //input the crystal constant 112 | void check_cry(); 113 | int get_Millern(); 114 | //output the need number of Miller indice 115 | 116 | void ini_Cij6(MatrixXd); 117 | //input the elastic constant in 6X6 tensor 118 | int check_Cij6(); 119 | 120 | int ini_therm(VectorXd); 121 | //input the thermal expansion coefficients [K^(-1)] 122 | int check_therm(); 123 | 124 | int ini_gmode(int n); 125 | //input the deformation modes 126 | //needs loop over grains 127 | int check_gmode(); 128 | 129 | //input the normal and Burgers vector of deformation system in a mode 130 | //input parameters: 131 | //(MatrixXd) sn, (int) flag of twin or slip, (int) number of systems,(int) mode label 132 | //needs loop over grains 133 | int ini_sn(MatrixXd, int, int, int); 134 | int check_sn(); 135 | 136 | int ini_GZ(double); 137 | //input the grain size; 138 | 139 | int ini_hardening(double, VectorXd, VectorXd, int); 140 | //input the hardening parameters 141 | //input parameters: 142 | //double nrsx_in; VectorXd CRSS_p_in; VectorXd hst_in; int modei 143 | int check_hardening(); 144 | 145 | int Update_Fij(double); 146 | int Update_shape(); 147 | Vector3d get_ell_axis(); 148 | Vector3d get_ellip_ang(); 149 | 150 | //the singular step according to a certain process 151 | int EVPSC(int, double, bool, bool, bool); 152 | 153 | //calculate the macro&grain elastic compliance 154 | int Selfconsistent_E(int, double, int); 155 | 156 | //calculate the macro&grain VP compliance 157 | int Selfconsistent_P(int, double, int); 158 | 159 | // calculate the Sig_m and Dij_m 160 | void Cal_Sig_m(double); 161 | 162 | // calculate the Sig_g and Dij_g including the elastic and vp part 163 | void Cal_Sig_g(double); 164 | 165 | void Update_AV(); //update the volume average value 166 | 167 | //output 168 | Vector6d get_Sig_m(); 169 | Vector6d get_Eps_m(); 170 | void get_euler(fstream &); 171 | 172 | 173 | }; 174 | 175 | 176 | } 177 | #endif -------------------------------------------------------------------------------- /Processes.cpp: -------------------------------------------------------------------------------- 1 | #include "Processes.h" 2 | using namespace Procs; 3 | 4 | Process::Process() 5 | { 6 | ss_out.open("str_str.out",ios::out); 7 | ss_out << setw(10) << "E11" << setw(11)<< "E22" << setw(11)<< "E33"; 8 | ss_out << setw(11) << "E32" << setw(11)<< "E13" << setw(11)<< "E12"; 9 | ss_out << setw(11) << "S11" << setw(11)<< "S22" << setw(11)<< "S33"; 10 | ss_out << setw(11) << "S32" << setw(11)<< "S13" << setw(11)<< "S12" << endl; 11 | 12 | tex_out.open("Tex.out",ios::out); 13 | } 14 | 15 | Process::~Process() 16 | { 17 | ss_out.close(); 18 | tex_out.close(); 19 | } 20 | 21 | void Process::load_ctrl(Vector4d Vin) 22 | { 23 | Nsteps = int(Vin(0)); 24 | Ictrl = int(Vin(1)) - 1; 25 | Eincr = Vin(2); 26 | Temp = Vin(3); 27 | 28 | if(!texctrl) texctrl = Nsteps; 29 | } 30 | 31 | void Process::get_Udot(Matrix3d Min) 32 | { 33 | Udot_input = Min; 34 | Ddot_input = 0.5*(Min + Min.transpose()); 35 | 36 | //calculate Time increment Tincr 37 | Vector6d Vtemp = voigt(Ddot_input); 38 | Tincr = Eincr / Vtemp(Ictrl); 39 | } 40 | void Process::get_Sdot(Matrix3d Min){Sdot_input = Min;} 41 | void Process::get_IUdot(Matrix3i Min){IUdot = Min;} 42 | void Process::get_ISdot(Vector6i Vin){ISdot = Vin;} 43 | 44 | void Process::loading(Polycs::polycrystal &pcrys) 45 | { 46 | pcrys.ini_Udot_m(Udot_input); 47 | pcrys.ini_Sig_m(Sdot_input); 48 | pcrys.set_IUdot(IUdot); 49 | pcrys.set_ISdot(ISdot); 50 | for(int istep = 0; istep < Nsteps; ++istep) 51 | { 52 | pcrys.EVPSC(istep, Tincr, Iupdate_ori, Iupdate_shp, Iupdate_CRSS); 53 | Out_sscurves(pcrys); 54 | if(!((istep+1)%texctrl)) 55 | Out_texture(pcrys,istep); 56 | } 57 | 58 | } 59 | 60 | void Process::Out_sscurves(Polycs::polycrystal &pcrys) 61 | { 62 | IOFormat Outformat(StreamPrecision); 63 | ss_out << setprecision(4) << scientific << pcrys.get_Eps_m().transpose().format(Outformat)<< " "; 64 | ss_out << setprecision(4) << scientific << pcrys.get_Sig_m().transpose().format(Outformat) << endl; 65 | } 66 | 67 | void Process::Out_texture(Polycs::polycrystal &pcrys, int istep) 68 | { 69 | IOFormat Outformat(StreamPrecision); 70 | tex_out << "TEXTURE AT STEP = " << istep+1 << endl; 71 | tex_out << setprecision(4) << pcrys.get_ell_axis().transpose().format(Outformat)<< endl; 72 | tex_out << setprecision(4) << pcrys.get_ellip_ang().transpose().format(Outformat) << endl << endl; 73 | pcrys.get_euler(tex_out); 74 | tex_out << endl; 75 | } 76 | 77 | void Process::Out_texset(int input){texctrl = input;} 78 | 79 | void Process::Update_ctrl(Vector3i input){ 80 | Iupdate_ori = input(0); 81 | Iupdate_shp = input(1); 82 | Iupdate_CRSS = input(2); 83 | } -------------------------------------------------------------------------------- /Processes.h: -------------------------------------------------------------------------------- 1 | #ifndef PROCESSES_H 2 | #define PROCESSES_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | using namespace Eigen; 11 | 12 | #include "Grains.h" 13 | #include "Polycrystals.h" 14 | #include "Toolbox.h" 15 | 16 | namespace Procs{ 17 | 18 | class Process 19 | { 20 | private: 21 | Matrix3d Udot_input; //the velocity gradient in process file 22 | Matrix3d Ddot_input; //the strain rate calculated by the velocity gradient in process file 23 | Matrix3d Sdot_input; //the stress tensor in process file 24 | 25 | Matrix3i IUdot; //the flag of known (control by Udot_input) and unknown (calculated by EVPSC) velocity components 26 | Vector6i IDdot; //the flag of known and unknown strain rate components 27 | Vector6i ISdot; //the flag of known and unknown stress componets 28 | 29 | double Eincr; //the increment of strain in every istep 30 | int Ictrl; 31 | int Nsteps; // total steps 32 | double Temp; // /(K^-1) temperature 33 | double Tincr; 34 | 35 | //Output files 36 | fstream ss_out; //output of the macro stress-strain curves 37 | fstream tex_out; //output of the texture 38 | 39 | int texctrl; //print the texture every n steps(0 means only print at the end) 40 | 41 | //update 42 | bool Iupdate_ori; //update the orientation 1:yes 0:no 43 | bool Iupdate_shp; //update the ellipsoid shape 1:yes 0:no 44 | bool Iupdate_CRSS; //update the CRSS 1:yes 0:no 45 | 46 | public: 47 | Process(); 48 | ~Process(); 49 | 50 | //get the total steps and increment of a process from files 51 | //Vector4d 0: Nsteps; 1: Ictrl; 2: Eincr; 3: Temperature; 52 | void load_ctrl(Vector4d); 53 | 54 | // 55 | void Update_ctrl(Vector3i); 56 | 57 | //get the velocity gradient in a process file 58 | void get_Udot(Matrix3d); 59 | 60 | //get the Cauchy stress tensor in a process file 61 | void get_Sdot(Matrix3d); 62 | 63 | //get the known and unknown flag tensor in a process file 64 | void get_IUdot(Matrix3i); 65 | void get_ISdot(Vector6i); 66 | 67 | void loading(Polycs::polycrystal &); 68 | 69 | ///// 70 | //Output functions: 71 | //output of stress&strain curves 72 | void Out_sscurves(Polycs::polycrystal &); 73 | 74 | //output of texture 75 | void Out_texture(Polycs::polycrystal &, int); 76 | void Out_texset(int); 77 | 78 | }; 79 | 80 | } 81 | 82 | #endif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | The cpp version of Elastic Visco-plastic Self-Consistent model 2 | # Elastic visco-plastic self-consistent model 3 | ## 1. 晶体变形运动学 4 | 描述单晶体大变形,即描述单晶体从初始构型(参考构型)变形到当前构型(变形后构型)时的几何变化和应力状态变化。 5 | 6 | 我们定义: 7 | $\boldsymbol X$ :物质点坐标,即在晶粒参考构型中的坐标 8 | $\boldsymbol{x(X)}$ :物质点在晶粒当前构型的坐标 9 | $\boldsymbol {u=x-X}$ :物质点的位移 10 | 11 | 根据有限变形理论,晶粒的变形可以通过变形梯度张量 $\boldsymbol F$ 及速度梯度张量 $\boldsymbol l$ ,定义为: 12 | 13 | $$\boldsymbol {l} = \frac{\partial \boldsymbol {\dot u}}{\partial \boldsymbol x} = \frac{\partial \boldsymbol v}{\partial \boldsymbol x} \tag{1-1}$$ 14 | 15 | $$\boldsymbol{F}= \frac{\partial \boldsymbol x}{\partial \boldsymbol X}= \frac{\partial \boldsymbol u}{\partial \boldsymbol X} + \boldsymbol I \tag{1-2}$$ 16 | 17 | 根据它们的偏微分关系,有: 18 | $$\boldsymbol {\dot F} = \boldsymbol {l \cdot F} \tag{1-3}$$ 19 | 20 | 如图1所示,变形梯度张量 $\boldsymbol {F}$ 可以分解为: 21 | $$\boldsymbol {F} = \boldsymbol {F}^e \cdot \boldsymbol {F}^p \tag{1-4}$$ 22 | 23 | 晶体在外力的作用下, 会发生晶格畸变,同时由于晶粒边界的约束和变形协调的要求,发生刚体转动, $\boldsymbol {F}^e$ 即表示由晶格畸变和刚体转动所产生的变形梯度, $\boldsymbol {F}^p$ 则表示晶体由于滑移/孪晶系统产生的均匀剪切产生的变形梯度。 24 | 25 |
26 |
图 1. 晶体弹塑性变形几何学
27 | 28 | 29 | 根据公式(1-3)和公式(1-4),速度梯度张量可以写成: 30 | 31 | $$\begin{align}\boldsymbol l &= \boldsymbol {\dot F} \cdot \boldsymbol {F}^{-1}\\ 32 | &= (\boldsymbol {\dot F}^e \cdot \boldsymbol { F}^p+\boldsymbol { F}^e \cdot \boldsymbol {\dot F}^p)\cdot(\boldsymbol { F}^e \cdot \boldsymbol {F}^p)^{-1}\\ 33 | &=\boldsymbol {\dot F}^e \cdot (\boldsymbol { F}^e)^{-1} + \boldsymbol { F}^e \cdot \boldsymbol {\dot F}^p \cdot (\boldsymbol {F}^p)^{-1} \cdot (\boldsymbol {F}^e)^{-1}\\ 34 | \end{align}\tag{1-5}$$ 35 | 36 | 令 $\boldsymbol {l}^e=\boldsymbol {\dot F}^e \cdot (\boldsymbol { F}^e)^{-1}$ , $\boldsymbol {l}^p= \boldsymbol { F}^e \cdot \boldsymbol {\dot F}^p \cdot (\boldsymbol {F}^p)^{-1} \cdot (\boldsymbol {F}^e)^{-1}$ 则速度梯度分解成弹性和塑性部分: 37 | $$\boldsymbol {l} = \boldsymbol {l}^e+\boldsymbol {l}^p \tag{1-6}$$ 38 | 39 | 速度梯度张量可以分解成对称张量(应变率张量) $\boldsymbol d$ 和反对称张量(旋率张量) $\boldsymbol w$ : 40 | $$\boldsymbol {l = d + w}\tag{1-7}$$ 41 | 42 | $\boldsymbol {l}$ 的弹性部分和塑性部分也可以进行类似的分解: 43 | $$\boldsymbol {l}^e = \boldsymbol {d}^e + \boldsymbol {w}^e\tag{1-8}$$ 44 | $$\boldsymbol {l}^p = \boldsymbol {d}^p + \boldsymbol {w}^p\tag{1-9}$$ 45 | 46 | 单晶体材料的塑性变形由滑移或孪生引起,在图 1所示的中间构型中,晶格矢量不发生变化,记第 $\alpha$ 个滑移/孪晶系统的变形方向为 $\boldsymbol {s}^\alpha_0$、变形法向为 $\boldsymbol {n}^\alpha_0$,则发生的塑性变形: 47 | $$\boldsymbol {\dot F}^p \cdot (\boldsymbol {F}^p)^{-1} = \sum_\alpha \dot\gamma^\alpha\boldsymbol {s}^\alpha_0\cdot(\boldsymbol {n}^\alpha_0)^T\tag{1-10}$$ 48 | 49 | 其中, $\dot\gamma^\alpha$ 为变形系 $\alpha$ 引起的剪切应变率。 50 | 51 | 在发生晶格畸变后,晶格矢量将发生拉伸和转动,他们会保持正交关系,但一般不再是单位矢量。晶格畸变后,变形方向和法向分别为 $\boldsymbol {s}^\alpha$ , $\boldsymbol {n}^\alpha$ : 52 | $$\boldsymbol {s}^\alpha=\boldsymbol{F}^e\cdot\boldsymbol {s}^\alpha_0\tag{1-11a}$$ 53 | $$\boldsymbol {n}^\alpha=(\boldsymbol{F}^e)^{-T}\cdot\boldsymbol {n}^\alpha_0\tag{1-11a}$$ 54 | 55 | 那么塑性速度梯度张量 $\boldsymbol {l}^p$: 56 | $$\boldsymbol {l}^p=\sum_\alpha \dot\gamma^\alpha \boldsymbol {s}^\alpha\cdot(\boldsymbol {n}^\alpha)^T\tag{1-12}$$ 57 | 58 | 根据公式(1-12),可以得到应变率张量 $\boldsymbol d$ 和旋率张量 $\boldsymbol w$ 的弹性和塑性部分 59 | $$\boldsymbol{d}^e= \frac{1}{2}\left[\boldsymbol{\dot F}^e\cdot(\boldsymbol{F}^e)^{-1}+(\boldsymbol{F}^e)^{-T}\cdot(\boldsymbol{\dot F}^e)^T 60 | \right]\tag{1-13}$$ 61 | $$\boldsymbol{w}^e= \frac{1}{2}\left[\boldsymbol{\dot F}^e\cdot(\boldsymbol{F}^e)^{-1}-(\boldsymbol{F}^e)^{-T}\cdot(\boldsymbol{\dot F}^e)^T 62 | \right]\tag{1-14}$$ 63 | $$\boldsymbol {d}^p=\sum_\alpha \dot\gamma^\alpha \boldsymbol {P}^\alpha\tag{1-15}$$ 64 | $$\boldsymbol {w}^p=\sum_\alpha \dot\gamma^\alpha \boldsymbol {R}^\alpha\tag{1-16}$$ 65 | 66 | 其中 $\boldsymbol {P}^\alpha=\frac{1}{2}\left[\boldsymbol {s}^\alpha\cdot(\boldsymbol {n}^\alpha)^T+\boldsymbol {n}^\alpha\cdot(\boldsymbol {s}^\alpha)^T 67 | \right]$(称为Schmid tensor施密特张量), 68 | $\boldsymbol {R}^\alpha=\frac{1}{2}\left[\boldsymbol {s}^\alpha\cdot(\boldsymbol {n}^\alpha)^T-\boldsymbol {n}^\alpha\cdot(\boldsymbol {s}^\alpha)^T 69 | \right]$ 70 | 71 | ## 2. 单晶本构关系 72 | 设晶体的弹性性质不受滑移/孪晶变形的影响,则单晶的本构方程为: 73 | $$\boldsymbol\sigma^{\nabla*}+\boldsymbol\sigma\ tr(\boldsymbol{d}^e)=\boldsymbol L:\boldsymbol{d}^e\tag{2-1}$$ 74 | 75 | 其中, $\boldsymbol L$ 为四阶弹性模量张量, $\boldsymbol\sigma^{\nabla*}$ 为基于中间构型的Cauchy应力张量的客观率(Jaumann率): 76 | $$\boldsymbol\sigma^{\nabla*}=\boldsymbol {\dot\sigma}-\boldsymbol {w}^e\cdot\boldsymbol\sigma+\boldsymbol\sigma\cdot\boldsymbol {w}^e\tag{2-2}$$ 77 | 78 | 而基于初始构型的Cauchy应力张量的Jaumann率为: 79 | 80 | $$\begin{align}\boldsymbol{\sigma}^\nabla &= \boldsymbol{\dot\sigma}-\boldsymbol w \cdot \boldsymbol \sigma + \boldsymbol \sigma \cdot \boldsymbol w \\ 81 | &= (\boldsymbol{\sigma}^{\nabla*}+\boldsymbol w^e\cdot\boldsymbol\sigma-\boldsymbol \sigma\cdot\boldsymbol w^e) - \boldsymbol w \cdot \boldsymbol \sigma + \boldsymbol \sigma\cdot \boldsymbol w\\ 82 | &=\boldsymbol\sigma^{\nabla*}-(\boldsymbol {w}-\boldsymbol {w}^e)\cdot\boldsymbol\sigma+\boldsymbol\sigma\cdot(\boldsymbol {w}-\boldsymbol {w}^e)\\ 83 | &=\boldsymbol\sigma^{\nabla*}-\boldsymbol {w}^p\cdot\boldsymbol\sigma+\boldsymbol\sigma\cdot\boldsymbol {w}^p\end{align}\tag{2-3}$$ 84 | 85 | 将式(2-3)代入单晶本构方程(2-1),得到在参考构型下的单晶本构方程: 86 | $$\boldsymbol{\sigma}^\nabla+\boldsymbol {w}^p\cdot\boldsymbol\sigma-\boldsymbol\sigma\cdot\boldsymbol {w}^p + \boldsymbol\sigma\ tr(\boldsymbol{d}-\boldsymbol{d}^p)=\boldsymbol L : (\boldsymbol{d}-\boldsymbol{d}^p)\tag{2-4}$$ 87 | 88 | 整理得到: 89 | $$\boldsymbol{\sigma}^\nabla= \boldsymbol {L'}:(\boldsymbol{d}-\boldsymbol{d}^p)+\boldsymbol\sigma^0\tag{2-5}$$ 90 | 91 | 其中, $L_{ijkl}'=L_{ijkl}-\sigma_{ij}\delta_{kl}$ , $\sigma^0_{ij}=w^p_{ik}\sigma_{kj}-\sigma_{ik}w^p_{kj}$ , 进而得到应变率张量与客观应力率的关系: 92 | $$\boldsymbol d = \boldsymbol M^e:\boldsymbol\sigma^\nabla+\boldsymbol d^p + \boldsymbol w^0\tag{2-6}$$ 93 | 94 | 其中 $\boldsymbol M^e=(\boldsymbol L')^{-1}$ 为弹性柔度张量, $\boldsymbol w^0=\boldsymbol M^e:\boldsymbol\sigma^0$ 95 | 96 | 根据式(1-14a),单晶的本构关系中还需要明确 $\alpha$ 滑移/孪生系的剪切应变率 $\dot\gamma^\alpha$ ,而对率相关材料, $\dot\gamma^\alpha$ 取决于变形系的分解剪切应力 $\tau^\alpha$ 、临界剪切应力 $\tau_{cr}^\alpha$ 以及率相关系数 $m$ 等: 97 | $$\dot\gamma^\alpha=\dot\gamma^\alpha(\tau^\alpha,\tau^\alpha_{cr},m,...)\tag{2-7}$$ 98 | 其中,变形系的分解剪切应力 $\tau^\alpha=\boldsymbol P^\alpha: \boldsymbol\sigma'$ , $\boldsymbol\sigma'$ 为应力偏张量。可以看出,这样定义的分解剪切应力 $\tau^\alpha$ 与剪切应变率 $\dot\gamma^\alpha$ 是功共轭的;而临界剪切应力 $\tau^\alpha_{cr}$ 反映了变形系的硬化/软化行为,其变化率 $\dot\tau^\alpha_{cr}$ 与当前临界剪切应力 $\tau^\alpha_{cr}$ 、其他变形系 $\beta$ 的累计剪切应变 $\gamma^\beta$ 和剪切应变率 $\dot\gamma^\beta$ 、以及孪晶系 $\kappa$ 的孪晶体积分数 $f^\kappa$ 相关: 99 | $$\dot\tau^\alpha_{cr}=\dot\tau^\alpha_{cr}(\tau^\alpha_{cr},\gamma^\beta,\dot\gamma^\beta,f^\kappa,...)\tag{2-8}$$ 100 | 101 | 其中,孪晶系 $\kappa$ 的孪晶体积分数 $f^\kappa$ 的变化率为: 102 | $$\dot{f}^\kappa=\frac{\gamma^\kappa}{\gamma^{tw}}\tag{2-9}$$ 103 | $\gamma^{tw}$ 为孪晶系的特征剪切应变值,为常数。 104 | 105 | 根据 Tomé等人的研究,对滑移系: 106 | $$\dot\gamma^\alpha=\dot\gamma_0|\dfrac{\tau^\alpha}{\tau^\alpha_{cr}}|^{1/m}sgn(\tau^\alpha)\tag{2-10}$$ 107 | 108 | 考虑到孪晶变形的极性,对孪晶系: 109 | 110 | $$\dot\gamma^\alpha=\begin{cases}\dot\gamma_0|\dfrac{\tau^\alpha}{\tau^\alpha_{cr}}|^{1/m} & , \tau^\alpha \gt 0 \\ 111 | 1 & , \tau^\alpha \le 0\end{cases}\tag{2-11}$$ 112 | 113 | $\dot\gamma_0$ 为参考剪切应变率, $sgn$ 为符号函数。 114 | 115 | 由此建立了塑性应变率 $\boldsymbol d^p$ 与应力张量 $\boldsymbol\sigma$ 的联系,注意到此时单晶体本构关系(2-6)成为一个非线性方程,可以通过不同的方法将该方程进行准线性化, 116 | 本构关系可以进一步表示为: 117 | $$\boldsymbol d = \boldsymbol M^e:\boldsymbol\sigma^\nabla+\boldsymbol M^{vp}:\boldsymbol\sigma'+\boldsymbol d^0 \tag{2-12}$$ 118 | 其中, $\boldsymbol M^{vp}$ 为粘塑性模量, $\boldsymbol d^0$ 为使该准线性方程成立的反推项,并且有 $\boldsymbol d^e=\boldsymbol M^e:\boldsymbol\sigma^\nabla$, $\boldsymbol d^p=\boldsymbol M^{vp}:\boldsymbol\sigma^{'}+\boldsymbol d^0$ 119 | 120 | ## 3. 多晶体自洽模型 121 | 122 | 多晶体材料可以看作是许多单晶的集合,基于单晶体本构模型和以各个晶体的取向,并结合应力应变协调方程可得到多晶体材料在宏观载荷下的力学响应,结合有限元理论即可实现(Crystal-plasticity finite element method, CPFEM方法)。然而,由于实际多晶体材料中包含的晶粒数量较多,通过CPFEM来计算宏观力学响应往往意味着较大的计算开销。多晶体自洽模型则是一种能在较小的计算开销下,得到多晶体材料的宏微观力学响应的均质化假设模型。 123 | 124 | 125 | 对多晶体材料,宏观应变率张量 $\boldsymbol D$ 、旋率张量 $\boldsymbol W$ 及 Cauchy 应力张量 $\boldsymbol\Sigma$ 可看作其包含的所有单晶体的对应张量的体积平均: 126 | $$\boldsymbol D = \langle\boldsymbol d\rangle=\frac{1}{V}\int\boldsymbol d\ dV\tag{3-1a}$$ 127 | $$\boldsymbol W = \langle\boldsymbol w\rangle=\frac{1}{V}\int\boldsymbol w\ dV\tag{3-1b}$$ 128 | $$\boldsymbol\Sigma = \langle\boldsymbol\sigma\rangle=\frac{1}{V}\int\boldsymbol\sigma\ dV\tag{3-1c}$$ 129 | 130 | $V$ 为多晶体的体积,算符〈⋯〉表示求体积平均。均匀化处理之后可以得到多晶体的本构方程: 131 | $$\boldsymbol D = \overline{\boldsymbol M}^e:\boldsymbol\Sigma^\nabla+\overline{\boldsymbol M}^{vp}:\boldsymbol\Sigma'+\boldsymbol D^0 \tag{3-2}$$ 132 | 133 | 其中, $\overline{\boldsymbol M}^e$ , $\overline{\boldsymbol M}^{vp}$ 和 $\boldsymbol D^0$ 分别为宏观弹性模量张量,宏观粘塑性模量张量和反推项。在实际计算中,仅仅只有宏观的边界条件是已知的,而宏观的模量和各个晶粒的模量以及塑性应变都是未知的,需要利用多晶体聚合体和晶粒之间的联系来迭代求解。 134 | 135 | ### 3.1 椭球体夹杂问题 136 | 上文提到的求解宏微观模量的方法,是通过将多晶体看作无限大均匀介质,从而使得需要求解的晶粒与晶粒之间的应力状态差异问题,转换为了根据本征应变求解本征应力的问题。现在假设均匀介质中存在一个局部区域 $\Omega$ ,若假设 $\Omega$ 不受到周围介质的约束,在由于某种物理或化学的原因,则会产生不产生应力场的均匀的局部应变 $\boldsymbol\varepsilon^+$,该局部应变就被称为本征应变。本征应变是一个广义的概念,它可以是热应变、相变应变和残余应力等,实际上区域 $\Omega$ 在周围介质的约束下,无法自由发生变形,从而在局部区域 $\Omega$ 内外产生应力场,产生本征应变的区域 $\Omega$ 称为夹杂。 137 | 138 | 本征应变问题可以分解为三个问题的叠加 139 | 140 | (i)将局部区域 $\Omega$ 剥离,让 $\Omega$ 自由产生本征应变 $\varepsilon_{ij}^+$ ,此时区域 $\Omega$ 内没有产生应力,而剩余区域 $\Omega^-$ 也不产生应变; 141 | 142 | (ii)当本征应变在区域 $\Omega$ 内均匀分布,则可以通过在夹杂边界 $S$ 附加虚拟面力 $p_i^+$ ,从而使区域 $\Omega$ 产生弹性应变 $-\varepsilon_{ij}^+$ ,恢复取出时的形状,这样产生的弹性应力场为: 143 | 144 | 145 | $$\sigma_{ij}^+=-C_{ijkl}\varepsilon_{ij}^+\tag{3-3}$$ 146 | 147 | 式中 $C_{ijkl}$ 为材料的弹性刚度, $σ_{ij}^+$ 即为对应的本征应力,虚拟面力 $p_i^+$ 为: 148 | 149 | $$p_i^+=-\sigma^{+}_{ij}n_j\tag{3-4}$$ 150 | 151 | 式中 $n_j$ 为边界的外法向。至此,局部区域 $\Omega$ 已经恢复成原来的形状,只是在边界上存在虚拟面力; 152 | 153 | (iii)将局部区域 $\Omega$ 放回均匀介质中,在夹杂边界上施加 $-p_i^+$ ,同时让整个均匀介质一起变形,释放虚拟载荷。求解此时无限大介质内的位移解即为夹杂问题的位移解。 154 | 155 | Eshebly (1957) 证明,当介质为线弹性,夹杂体形状为椭球体,而且本征应变 $\boldsymbol\varepsilon^+$ 为常应变(应变大小在夹杂体内不随位置改变),最终求解得到的夹杂内的实际应变 $\boldsymbol\varepsilon$ 也是常应变,二者之间满足: 156 | 157 | $$\varepsilon_{ij}^+=S_{ijkl}\varepsilon_{ij}^+\tag{3-5}$$ 158 | 159 | $S_{ijkl}$ 称为Eshebly张量,它仅与介质的弹性性质和椭球体的形状与取向有关。 $S_{ijkl}$ 关于 $i$ 和 $j$ , $k$ 和 $l$ 对称,但一般关于 $(i,j)$ 与 $(k,l)$ 不对称,故一般不具有 Voigt 对称性。 160 | 161 | ### 3.2 粘塑性介质中粘塑性夹杂问题 162 | 将多晶体视为无限大粘塑性介质,而某一晶粒则为夹杂体。根据单晶体塑性应变率 $\boldsymbol d^p=\boldsymbol M^{vp}:\boldsymbol\sigma'+\boldsymbol d^0$ 和多晶体塑性应变率表达式 $\boldsymbol D^p=\overline{\boldsymbol M}^{vp}:\boldsymbol\Sigma'+ \boldsymbol D^0$,将单晶体的塑性应变率通过宏观粘塑性张量整理成: 163 | $$\boldsymbol d^p=\overline{\boldsymbol M}^{vp}:\boldsymbol\Sigma'+\boldsymbol d^0 + \boldsymbol d^+\tag{3-6}$$ 164 | 165 | 这样, $\boldsymbol d^+=(\boldsymbol M^{vp}-\overline{\boldsymbol M}^{vp}):\boldsymbol\sigma'+(\boldsymbol d^0-\boldsymbol D^0)$ 则是此时的本征应变率,考虑到粘塑性刚度张量 $\overline{\boldsymbol L}^{vp}=(\overline{\boldsymbol M}^{vp})^{-1}$ ,并记 $\boldsymbol{\widetilde\sigma}'=\boldsymbol\sigma'-\boldsymbol\Sigma'$ , $\boldsymbol{\widetilde d}^p=\boldsymbol d^p-\boldsymbol D^p$ 式(3-6)可以改写成: 166 | $$\boldsymbol{\widetilde\sigma}'=\overline{\boldsymbol L}^{vp}:(\widetilde{\boldsymbol d}^p-\boldsymbol d^+)\tag{3-7a}$$ 167 | 168 | 记材料点的坐标为 $\boldsymbol x$ ,并将张量形式展开: 169 | 170 | $$\widetilde\sigma_{ij}'(\boldsymbol x)=\overline L_{ijkl}^{vp}:(\widetilde d_{kl}^p(\boldsymbol x)-d_{kl}^+(\boldsymbol x)) \tag{3-7b}$$ 171 | 172 | 平衡方程为: 173 | 174 | $$\sigma_{ij,j}(\boldsymbol x)=(\widetilde\sigma_{ij}(\boldsymbol x)+\Sigma_{ij}(\boldsymbol x)),j=\widetilde{\sigma}_{ij,j}(\boldsymbol x)=0\tag{3-8}$$ 175 | 176 | 应力张量 $\sigma_{ij}$,可以分解成球应力张量 $\sigma^p\delta_{ij}$ 与偏应力张量之和 $\sigma_{ij}'$: 177 | 178 | $$\sigma_{ij}(\boldsymbol x)=\sigma^p(\boldsymbol x)\delta_{ij}+\sigma_{ij}'(\boldsymbol x)\tag{3-9}$$ 179 | 180 | 再结合关系式 $\widetilde d_{ij}(\boldsymbol x)=\frac{1}{2}(\widetilde {\dot u_{i,j}}+\widetilde{\dot u_{j,i}})$ 和粘塑性刚度张量关于 $k$ 和 $l$ 的对称性 $\overline L_{ijkl}^{vp}=\overline L_{ijlk}^{vp}$ , $\widetilde\sigma_{ij,j}(\boldsymbol x)$ 可以通过位移来表示: 181 | 182 | $$\begin{align}\widetilde\sigma_{ij,j}(\boldsymbol x) &= \left[\widetilde\sigma^p(\boldsymbol x)\delta_{ij}+\sigma_{ij}'(\boldsymbol x) \right],j \\ 183 | &= \widetilde\sigma^p_{,i}(\boldsymbol x) + \left[\overline L_{ijkl}^{vp}\left(\widetilde d_{kl}^p(\boldsymbol x) - d_{kl}^+(\boldsymbol x)\right)\right]\\ 184 | &= \widetilde\sigma^p_{,i}(\boldsymbol x) + \sigma_{ij,j}^+(\boldsymbol x) + \left[\overline L_{ijkl}^{vp}\widetilde d_{kl}^p(\boldsymbol x)\right]\\ 185 | & = \widetilde\sigma^p_{,i}(\boldsymbol x) + \sigma_{ij,j}^+(\boldsymbol x) + \frac{1}{2}\left[\overline L_{ijkl}^{vp}\left(\widetilde {\dot u_{k,l}}(\boldsymbol x)+\widetilde{\dot u_{l,k}}(\boldsymbol x)\right)\right]\\ 186 | & = \widetilde\sigma^p_{,i}(\boldsymbol x) + \sigma_{ij,j}^+(\boldsymbol x) + \left[\overline L_{ijkl}^{vp}\widetilde {\dot u_{k,l}}(\boldsymbol x)\right],j\\ 187 | &= \widetilde\sigma^p_{,i}(\boldsymbol x) + \sigma_{ij,j}^+(\boldsymbol x) + \overline L_{ijkl}^{vp}\widetilde {\dot u_{k,lj}}(\boldsymbol x)\end{align}\tag{3-10}$$ 188 | 189 | 式中, $\sigma_{ij,j}^+(\boldsymbol x) = -\overline L_{ijkl}^{vp}d_{kl}^+(\boldsymbol x)$ 即为本征应变引起的本征应力,该应力在介质无穷远处为0. 记虚拟体力: 190 | 191 | $$f_i^+(\boldsymbol x)=\sigma_{ij,j}^+(\boldsymbol x)\tag{3-11}$$ 192 | 193 | 用位移表示的平衡方程为: 194 | 195 | $$\overline L_{ijkl}^{vp}\widetilde {\dot u_{k,lj}}(\boldsymbol x)+\widetilde\sigma^p_{,i}(\boldsymbol x) + f_i^+(\boldsymbol x)=0\tag{3-12a}$$ 196 | 197 | 结合不可压缩条件: 198 | 199 | $$\widetilde {\dot u_{k,k}}(\boldsymbol x)=0\tag{3-12b}$$ 200 | 201 | 式(3-12)给出的位移场即为夹杂问题的解。在无限大均匀介质在集中力作用下的位移场, 可以通过格林函数法解出(Kelvin解)。设 $\widetilde {\dot u_i}(\boldsymbol x)$ 和 $\widetilde\sigma^p(\boldsymbol x)$ 应的格林函数分别为 $G_{km}(\boldsymbol x)$ 和 $H_m(\boldsymbol x)$ (或者说是线性算子 $\overline L_{ijkl}^{vp}\frac{\partial^2}{\partial x_l\partial x_j}$ 和 $\frac{\partial}{\partial x_i}$ 的核函数), 它们可以通过求解线性系统在作用于x=0位置的单位冲击响应得到: 202 | 203 | $$\overline L_{ijkl}^{vp}G_{km,lj}(\boldsymbol x)+H_{m,i}(\boldsymbol x)+\delta_{im}\delta(\boldsymbol x)=0\tag{3-13a}$$ 204 | 205 | $$G_{km,k}(\boldsymbol x)= 0\tag{3-13b}$$ 206 | 207 | 其中 $\delta(\boldsymbol x)$ 为Dirac函数, $\delta_{im}$ 为Kronecker函数,二者可以通过下标区分. $\widetilde {\dot u_i}(\boldsymbol x)$ 和 $\widetilde\sigma^p(\boldsymbol x)$ 的解可以通过格林函数与集中力的卷积得到: 208 | 209 | $$\widetilde {\dot u_k}=\int_{R^3}G_{ki}(\boldsymbol x - \boldsymbol x')f_i^+(\boldsymbol x')d\boldsymbol x'\tag{3-14a}$$ 210 | 211 | $$\widetilde\sigma^p(\boldsymbol x)=\int_{R^3}H_{i}(\boldsymbol x - \boldsymbol x')f_i^+(\boldsymbol x')d\boldsymbol x'\tag{3-14b}$$ 212 | 213 | 将式(3-13)转换到傅立叶空间中: 214 | 215 | $$\alpha_l\alpha_j\overline L_{ijkl}^{vp}G_{km}\overline\xi^2\widehat G_{km}(\boldsymbol\xi)+\alpha_ii\overline\xi\widehat H_m(\boldsymbol\xi)=\delta_{im}\tag{3-15a}$$ 216 | 217 | $$\alpha_k\overline\xi^2\widehat G_{km}(\boldsymbol\xi)=0\tag{3-15b}$$ 218 | 219 | 其中 $i=\sqrt{-1}$ , $\boldsymbol\xi$ 为傅立叶空间中的向量,可以用单位向量表示成 $\boldsymbol\xi=\overline\xi\boldsymbol\alpha$ . 记 $A_{ik}^d=\alpha_l\alpha_j\overline L_{ijkl}^{vp}$ , 可以将式(3-15)转换成矩阵乘法 $\boldsymbol{A\cdot B=C}$ 表达: 220 | 221 | $$\boldsymbol A=\begin{bmatrix} A_{11}^d & A_{12}^d & A_{13}^d & \alpha_1\\ 222 | A_{21}^d & A_{22}^d & A_{23}^d & \alpha_2 \\ 223 | A_{31}^d & A_{32}^d & A_{33}^d & \alpha_3 \\ 224 | \alpha_1 & \alpha_2 & \alpha_3 & 0\end{bmatrix}\tag{3-16a}$$ 225 | 226 | $$\boldsymbol B=\begin{bmatrix} \overline\xi^2\widehat G_{11} & \overline\xi^2\widehat G_{12} & \overline\xi^2\widehat G_{13} \\ 227 | \overline\xi^2\widehat G_{21} & \overline\xi^2\widehat G_{22} & \overline\xi^2\widehat G_{23} \\ 228 | \overline\xi^2\widehat G_{31} & \overline\xi^2\widehat G_{32} & \overline\xi^2\widehat G_{33} \\ 229 | i\overline\xi\widehat H_1 & i\overline\xi\widehat H_2 & i\overline\xi\widehat H_3 \end{bmatrix}\tag{3-16b}$$ 230 | 231 | $$\boldsymbol C=\begin{bmatrix} 1 & 0 & 0\\ 232 | 0 & 1 & 0\\ 233 | 0 & 0 & 1\\ 234 | 0 & 0 & 0\end{bmatrix}\tag{3-16c}$$ 235 | 236 | 其中 $\boldsymbol A$ 为四阶实对称矩阵,其逆矩阵(若存在)一定也是实对称矩阵, $\boldsymbol C$ 已知,则: 237 | 238 | $$\boldsymbol B=\boldsymbol A^{-1}\boldsymbol C=\begin{bmatrix} A_{11}^{-1} & A_{12}^{-1} & A_{13}^{-1}\\ 239 | A_{21}^{-1} & A_{22}^{-1} & A_{23}^{-1}\\ 240 | A_{31}^{-1} & A_{32}^{-1} & A_{33}^{-1}\\ 241 | A_{41}^{-1} & A_{42}^{-1} & A_{43}^{-1}\end{bmatrix}\tag{3-17}$$ 242 | 243 | 显然有: 244 | 245 | $$\overline\xi^2\widehat G_{ij}=A_{ij}^{-1}\ (i,j=1,2,3)\tag{3-18a}$$ 246 | 247 | $$i\overline\xi\widehat H_{i}=A_{4i}^{-1}\ (i=1,2,3)\tag{3-18b}$$ 248 | 249 | 至此, $\widehat G_{km}(\boldsymbol\xi)$ 和 $\widehat H_{m}(\boldsymbol\xi)$ 的值可以求得,再通过傅立叶变换即可得到实数域的解。对卷积式(3-14a)求偏导,并将(3-11)代入,并考虑卷积的微分特性,可得速度梯度解: 250 | 251 | $$\widetilde {\dot u_{k,l}}=\int_{R^3}G_{ki,lj}(\boldsymbol x - \boldsymbol x')\sigma_{ij}^+(\boldsymbol x')d\boldsymbol x'\tag{3-19}$$ 252 | 253 | Eshelby (1957)已经证明,夹杂区域 $\Omega$ 为椭球,且本征应变为常应变且弹性模量在区域内为常张量,那么本征应力也将是常应力。故可以假设本征应力在 $\Omega$ 内为常量而在 $\Omega$ 外为 $0$ , 所以式(3-18)可以转变成求在Ω内的速度梯度 $\widetilde {\dot u_{k,l}}$ 的平均值: 254 | 255 | $$\begin{align}\widetilde {\dot u_{k,l}} &= \left(\int_{R^3}-G_{ki,lj}(\boldsymbol x - \boldsymbol x')d\boldsymbol x'\right)\overline L_{ijkl}^{vp}d_{kl}^+\\ 256 | &=\left(-\int_{\Omega}\int_{\Omega}G_{ki,lj}(\boldsymbol x - \boldsymbol x')d\boldsymbol xd\boldsymbol x'\right)\overline L_{ijkl}^{vp}d_{kl}^+\end{align}\tag{3-20}$$ 257 | 258 | 同时将 $G_{ki,lj}$ 用傅立叶变换表达,则有: 259 | 260 | $$\begin{align}\widetilde {\dot u_{k,l}}&=\left(\frac{1}{8\pi^3\Omega}\int_{\Omega}\int_{\Omega}\int_{R^3}\alpha_l\alpha_j\overline\xi^2\widehat G_{km}(\boldsymbol\xi)e^{-i\boldsymbol\xi(\boldsymbol x - \boldsymbol x')}d\boldsymbol\xi d\boldsymbol xd\boldsymbol x'\right)\overline L_{ijkl}^{vp}d_{kl}^+\\\ 261 | &=T_{klij}^{vp}\overline L_{ijkl}^{vp}d_{kl}^+\end{align}\tag{3-21}$$ 262 | 263 | $T_{klij}^{vp}$ 称为格林作用张量,在球坐标系中, $d\boldsymbol\xi = \overline\xi^2d\overline\xi sin\theta d\theta d\phi$ , $\theta$ 和 $\phi$ 为傅立叶空间的单位向量 $\boldsymbol\alpha$ 的球坐标,将式(3-18a)代入,并在轴长为 $(a,b,c)$ 的椭球体晶粒内进行积分(Berveiller et al., 1987): 264 | 265 | $$T_{klij}^{vp}=\dfrac{abc}{4\pi}\int_0^{2\pi}\int_0^{\pi}\dfrac{\alpha_l\alpha_j A_{ki}^{-1}(\boldsymbol\alpha)}{\left[\rho(\boldsymbol\alpha)\right]^3}sin\theta d\theta d\phi\tag{3-22}$$ 266 | 267 | 其中, $\rho(\boldsymbol\alpha)=\left[(a\alpha_1)+(b\alpha_2)+(c\alpha_3)\right]^{1/2}$ . 根据式(3-22)张量 $T_{klij}^{vp}$ 可以通过数值积分的方法计算,注意 $A_{ki}^{-1}(\boldsymbol\alpha)$ 需要在每一个积分位置 $\boldsymbol\alpha$ 都计算一次逆矩阵. 268 | 269 | 进一步可以得到对称和反对称的Eshelby张量: 270 | 271 | $$S_{ijkl}^{vp}=\frac{1}{4}\left(T_{ijmn}^{vp}+T_{jimn}^{vp}+T_{ijmn}^{vp}+T_{ijnm}^{vp}\right)\overline L_{mnkl}^{vp}\tag{3-23a}$$ 272 | 273 | $$\Pi_{ijkl}^{vp}=\frac{1}{4}\left(T_{ijmn}^{vp}-T_{jimn}^{vp}+T_{ijmn}^{vp}-T_{ijnm}^{vp}\right)\overline L_{mnkl}^{vp}\tag{3-23a}$$ 274 | 275 | 所以: 276 | 277 | $$\boldsymbol{\widetilde d}^p=\boldsymbol S^{vp}:\boldsymbol d^+\tag{3-24a}$$ 278 | 279 | $$\boldsymbol {\widetilde {\dot w}}^p=\boldsymbol\Pi^{vp}:\boldsymbol d^+ =\boldsymbol\Pi^{vp}:\left(\boldsymbol S^{vp}\right)^{-1}:\boldsymbol{\widetilde d}^p\tag{3-24b}$$ 280 | 281 | 结合式(3-24a)和式(3-7a),可以消去本征应变率 $\boldsymbol d^+$ , 得到 $\boldsymbol{\widetilde d}^p=\boldsymbol S^{vp}:\left(\boldsymbol{\widetilde d}^p-\overline{\boldsymbol M}^{vp}:\widetilde{\boldsymbol\sigma'}\right)$ , 整理得: 282 | 283 | $$\boldsymbol{\widetilde d}^p=-\widetilde{\boldsymbol M}^{vp}:\widetilde{\boldsymbol\sigma'}\tag{3-25}$$ 284 | 285 | 其中 $\widetilde{\boldsymbol M}^{vp}$ 为粘塑性相互作用张量: 286 | 287 | $$\widetilde{\boldsymbol M}^{vp}=(\boldsymbol I-\boldsymbol S^{vp}):\boldsymbol S^{vp}:\overline{\boldsymbol M}^{vp}\tag{3-26}$$ 288 | 289 | 将式(3-25)与宏微观的塑性应变率表达式结合, 可以得到用宏观应力张量和晶粒应变张量的关系: 290 | 291 | $$\boldsymbol\sigma'=\boldsymbol B^{vp}:\boldsymbol\Sigma'+\boldsymbol b^{vp} \tag{3-27}$$ 292 | 293 | 其中 $\boldsymbol B^{vp}$ 为局部化粘塑性张量: 294 | 295 | $$\boldsymbol B^{vp}=\left(\boldsymbol M^{vp} + \widetilde{\boldsymbol M}^{vp}\right)^{-1}:\left(\overline{\boldsymbol M}^{vp}+\widetilde{\boldsymbol M}^{vp}\right)\tag{3-28a}$$ 296 | 297 | $$\boldsymbol b^{vp}=\left(\boldsymbol M^{vp} + \widetilde{\boldsymbol M}^{vp}\right)^{-1}:\left(\boldsymbol D^0-\boldsymbol d^0\right)\tag{3-28b}$$ 298 | 299 | ### 3.3 弹性介质中弹性夹杂问题 300 | 与粘塑性夹杂问题通过格林函数法求解类似,将求解的微分算子改变为 $\overline L_{ijkl}^e\frac{\partial^2}{\partial x_l\partial x_j}$ , 即可得到对应的弹性夹杂问题的解: 301 | 302 | $$\boldsymbol{\widetilde d}^e=\boldsymbol S^{e}:\boldsymbol d^{e+}\tag{3-29a}$$ 303 | 304 | $$\boldsymbol {\widetilde {\dot w}}^e=\boldsymbol\Pi^{e}:\boldsymbol d^{e+} =\boldsymbol\Pi^{e}:\left(\boldsymbol S^{e}\right)^{-1}:\boldsymbol{\widetilde d}^e\tag{3-29b}$$ 305 | 306 | 存在 $\widetilde{\boldsymbol M}^{e}$ 弹性相互作用张量: 307 | 308 | $$\widetilde{\boldsymbol M}^{e}=(\boldsymbol I-\boldsymbol S^{e}):\boldsymbol S^{e}:\overline{\boldsymbol M}^{e}\tag{3-30}$$ 309 | 310 | 宏观应力率和晶粒应力率的关系: 311 | 312 | $$\boldsymbol{\dot\sigma}=\boldsymbol B^e:\boldsymbol{\dot\Sigma} \tag{3-31}$$ 313 | 314 | 其中 $\boldsymbol B^e$ 为局部化弹性张量: 315 | 316 | $$\boldsymbol B^e=\left(\boldsymbol M^e + \widetilde{\boldsymbol M}^e\right)^{-1}:\left(\overline{\boldsymbol M}^e+\widetilde{\boldsymbol M}^e\right)\tag{3-32}$$ 317 | 318 | ### 3.4 弹粘塑性自洽 319 | 晶粒的应变率张量可以通过相互作用张量与宏观的应力以及应力率建立联系: 320 | 321 | $$\boldsymbol d = -\widetilde{\boldsymbol M}^e:(\boldsymbol\sigma^\nabla-\boldsymbol\Sigma^\nabla)-\widetilde{\boldsymbol M}^{vp}:(\boldsymbol\sigma-\boldsymbol\Sigma)\tag{3-33}$$ 322 | 323 | 根据自洽条件式(3-1), 式(3-26), 式(3-30)以及宏观应变率式(3-2): 324 | 325 | $$\overline{\boldsymbol M}^e:\boldsymbol\Sigma^\nabla+\overline{\boldsymbol M}^{vp}:\boldsymbol\Sigma+\boldsymbol D^0=\\ 326 | \langle\boldsymbol M^e:\boldsymbol B^e\rangle:\boldsymbol\Sigma^\nabla+\langle\boldsymbol M^{vp}:\boldsymbol B^{vp}\rangle:\boldsymbol\Sigma+\langle\boldsymbol M^{vp}:\boldsymbol b^{vp}+\boldsymbol d^0\rangle\tag{3-34}$$ 327 | 328 | 在所有晶粒的形状和方向都相同时, 有: 329 | 330 | $$\overline{\boldsymbol M}^e=\langle\boldsymbol M^e:\boldsymbol B^e\rangle\tag{3-35a}$$ 331 | 332 | $$\overline{\boldsymbol M}^{vp}=\langle\boldsymbol M^{vp}:\boldsymbol B^{vp}\rangle\tag{3-35b}$$ 333 | 334 | $$\boldsymbol D^0=\langle\boldsymbol M^{vp}:\boldsymbol b^{vp}+\boldsymbol d^0\rangle\tag{3-35c}$$ 335 | 336 | 根据Walpole (1969)和 Lebensohn 等人(1996&2004)的研究,当每个晶粒(椭球体)形状和取向不同时,有更一般的关系式: 337 | 338 | $$\overline{\boldsymbol M}^e=\langle\boldsymbol M^e:\boldsymbol B^e\rangle\:\langle\boldsymbol B^e\rangle^{-1}\tag{3-36a}$$ 339 | 340 | $$\overline{\boldsymbol M}^{vp}=\langle\boldsymbol M^{vp}:\boldsymbol B^{vp}\rangle:\langle\boldsymbol B^{vp}\rangle^{-1}\tag{3-36b}$$ 341 | 342 | $$\boldsymbol D^0=\langle\boldsymbol M^{vp}:\boldsymbol b^{vp}+\boldsymbol d^0\rangle-\boldsymbol M^{vp}:\langle\boldsymbol b^{vp}\rangle\tag{3-36c}$$ 343 | -------------------------------------------------------------------------------- /Systems_Voce.cpp: -------------------------------------------------------------------------------- 1 | #include "Systems_Voce.h" 2 | 3 | using namespace DSystems_Voce; 4 | 5 | // 6 | int dsystem::ini_sn_s(VectorXd vin) 7 | { 8 | n = vin(seq(0,2)); //normal 9 | s = vin(seq(3,5)); //Burgers 10 | Pij=0.5*(s*n.transpose()+n*s.transpose()); 11 | Rij=0.5*(s*n.transpose()-n*s.transpose()); 12 | return 0; 13 | } 14 | 15 | int dsystem::check_sn_s() 16 | { 17 | cout << n.transpose() << "\t" << s.transpose() << endl; 18 | cout << "Pij\n" << Pij << endl; 19 | return 0; 20 | } 21 | 22 | int dsystem::ini_hardening_s(VectorXd CRSS_p_in) 23 | { 24 | tau0 = CRSS_p_in(0); 25 | tau1 = CRSS_p_in(1); 26 | theta0 = CRSS_p_in(2); 27 | theta1 = CRSS_p_in(3); 28 | 29 | aratio = theta0/tau1; 30 | CRSS = tau0; 31 | return 0; 32 | } 33 | 34 | int dsystem::check_hardening_s() 35 | { 36 | Vector4d vout(tau0, tau1, theta0, theta1); 37 | cout << vout.transpose() << endl; 38 | return 0; 39 | } 40 | 41 | double dsystem::cal_RSSx(Matrix3d sig) 42 | { 43 | double RSS = 0; 44 | for(int i = 0; i < 3; i++ ) 45 | for(int j = 0; j < 3; j++ ) 46 | RSS += Pij(i,j) * sig(i,j); 47 | 48 | return RSS/CRSS; 49 | } 50 | 51 | Matrix3d dsystem::cal_dijp_a(Matrix3d sig, double nrsx) 52 | { 53 | double RSSx = cal_RSSx(sig); 54 | gammarate = gamma0 * pow(abs(RSSx), nrsx-1) * RSSx; 55 | return gammarate * Pij; 56 | } 57 | 58 | Matrix3d dsystem::cal_rotslip_a() 59 | { 60 | return gammarate * Rij; 61 | } 62 | 63 | Matrix6d dsystem::get_Fgrads(Matrix3d sig, double nrsx) 64 | { 65 | double RSSx = cal_RSSx(sig); 66 | 67 | Vector6d Pijv = voigt(Pij); 68 | Matrix6d Mout = Pijv * Pijv.transpose(); 69 | 70 | return Mout * gamma0 * pow(abs(RSSx), nrsx-1) / CRSS * nrsx; 71 | } 72 | 73 | double dsystem::get_gammarate(){return abs(gammarate);} 74 | 75 | void dsystem::Update_CRSS_a(double Hstpart,double gamma_delta, double gamma_total) 76 | { 77 | double exp1 = exp(-aratio*gamma_total); 78 | double exp2 = exp(-aratio*gamma_delta); 79 | CRSS_delta = Hstpart * ( \ 80 | theta1*gamma_delta \ 81 | - (aratio*tau1-theta1)/aratio*exp1*(exp2-1.0) \ 82 | - theta1/aratio*exp1*(exp2*(1+aratio*(gamma_total+gamma_delta))\ 83 | - (1.0 + aratio*gamma_total)) \ 84 | ); 85 | CRSS += CRSS_delta; 86 | } -------------------------------------------------------------------------------- /Systems_Voce.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSTEMS_VOCE_H 2 | #define SYSTEMS_VOCE_H 3 | 4 | #include "Toolbox.h" 5 | 6 | namespace DSystems_Voce{ 7 | //deformation system from which slip&twinning system can be derived 8 | class dsystem 9 | { 10 | protected: 11 | double gamma0 = 1e-3; //reference shear strain rate 12 | double gammarate = 0; 13 | 14 | double tau0,tau1;//the initial CRSS and the back-extrapolated CRSS(tau0+tau1) 15 | double theta0,theta1;//the initial hardening rate, the asymptotic hardening rate 16 | double aratio = 0; // = theta0/tau1; 17 | double CRSS; 18 | double CRSS_delta; 19 | 20 | //double nrsx; //rate sensitivity component 21 | Vector3d s,n; //the Burgers vector(s) and normal(n) of plane 22 | Matrix3d Pij; 23 | Matrix3d Rij; 24 | 25 | public: 26 | 27 | //initial the sn and calculate the pij 28 | int ini_sn_s(VectorXd); 29 | int check_sn_s(); 30 | 31 | //input the harderning parameter tau0, tau1, theta0, theta1; 32 | int ini_hardening_s(VectorXd); 33 | int check_hardening_s(); 34 | 35 | double cal_RSSx(Matrix3d); 36 | 37 | double get_gammarate(); 38 | 39 | //calculate the gamma_rate * Pij to get the vp strain rate Dijp_g 40 | //Parametes: 41 | //Matrix3d sig, double nrsx 42 | Matrix3d cal_dijp_a(Matrix3d, double); 43 | 44 | //calculate the gamma_rate * Rij 45 | Matrix3d cal_rotslip_a(); 46 | 47 | //update CRSS of system 48 | //parameters: 49 | //double Hstpart, double gamma_delta, double gamma_total 50 | void Update_CRSS_a(double, double, double); 51 | 52 | Matrix6d get_Fgrads(Matrix3d, double); 53 | }; 54 | 55 | class slip : public dsystem 56 | { 57 | }; 58 | 59 | class twin : public dsystem 60 | { 61 | }; 62 | 63 | 64 | } 65 | #endif -------------------------------------------------------------------------------- /Toolbox.cpp: -------------------------------------------------------------------------------- 1 | #include "Toolbox.h" 2 | using namespace std; 3 | using namespace Eigen; 4 | 5 | ///////////////////////// 6 | //Chg_basis and its overload function 7 | //with BASIS TENSOR Basis[3][3][6] 8 | const double Basis[3][3][6] = { 9 | //1,1 10 | -RSQ2, -RSQ6, 0, 0, 0, RSQ3, 11 | //1,2 12 | 0, 0, 0, 0, RSQ2, 0, 13 | //1,3 14 | 0, 0, 0, RSQ2, 0, 0, 15 | //2,1 16 | 0, 0, 0, 0, RSQ2, 0, 17 | //2,2 18 | RSQ2, -RSQ6, 0, 0, 0, RSQ3, 19 | //2,3 20 | 0, 0, RSQ2, 0, 0, 0, 21 | //3,1 22 | 0, 0, 0, RSQ2, 0, 0, 23 | //3,2 24 | 0, 0, RSQ2, 0, 0, 0, 25 | //3,3 26 | 0, 2.0*RSQ6, 0, 0, 0, RSQ3 27 | }; 28 | 29 | 30 | ///////////////////////// 31 | 32 | ///////////////////////// 33 | //Voigt and its overload function 34 | //to realize the 3X3X3X3 to 6X6 and the reverse transformation 35 | //and realize the 3X3 to 6X1 and the reverse transformation 36 | const int IJV[6][2]= {0,0,1,1,2,2,1,2,0,2,0,1}; 37 | ///////////////////////// 38 | 39 | /// 40 | int Eshelby_case(Vector3d Axis){ 41 | double RATIO1=Axis(1)/Axis(2); 42 | double RATIO2=Axis(0)/Axis(2); 43 | Matrix DTE; 44 | DTE << 0.0, 45 | -0.7*RATIO1+7, 46 | -RATIO1+17, 47 | -RATIO1+23, 48 | -RATIO1+26, 49 | -RATIO1+29.3, 50 | -RATIO1+32, 51 | -RATIO1+34.85, 52 | -RATIO1+37, 53 | -RATIO1+41.9, 54 | -RATIO1+44.5; 55 | int case_c = 11; 56 | for(int i = 1; i <= 10; i++) 57 | if(RATIO2 >= DTE(i-1)&& RATIO2 < DTE(i)) case_c = i; 58 | return case_c-1; 59 | } 60 | 61 | 62 | /// function definition of gau_leg 63 | void gau_leg(double x1, double x2, VectorXd &x, VectorXd &w, int n) 64 | { 65 | double eps = 1e-7; 66 | 67 | double m = n / 2; 68 | double xm = 0.5*(x1 + x2); 69 | double xl = 0.5*(x2 - x1); 70 | double xn = n; 71 | 72 | for (int i = 0; i < m; i++) 73 | { 74 | double xi = i + 1; 75 | double z = cos(M_PI*(xi - 0.25) / (xn + 0.5)); 76 | double p1, p2, p3, xj, pp, z1; 77 | 78 | z1 = z + 1; 79 | 80 | while (abs(z1 - z) > eps) 81 | { 82 | p1 = 1; 83 | p2 = 0; 84 | for (int j = 0; j < n; j++) 85 | { 86 | xj = j + 1; 87 | p3 = p2; 88 | p2 = p1; 89 | p1 = ((2 * j + 1)*z*p2 - (xj - 1)*p3) / xj; 90 | } 91 | 92 | pp = n*(z*p1 - p2) / (z*z - 1); 93 | z1 = z; 94 | z = z1 - p1 / pp; 95 | } 96 | 97 | x(i) = xm - xl*z; 98 | x(n - 1 - i) = xm + xl*z; 99 | w(i) = 2 * xl / ((1 - z*z)*pp*pp); 100 | w(n - 1 - i) = w(i); 101 | } 102 | } 103 | 104 | /// function definition of voigt 105 | Matrix3d voigt(Vector6d Vin) 106 | { 107 | Matrix3d Mout; 108 | int I1,I2; 109 | for(int i = 0; i < 6; i++) 110 | { 111 | I1 = IJV[i][0]; 112 | I2 = IJV[i][1]; 113 | Mout(I1,I2) = Vin(i); 114 | Mout(I2,I1) = Vin(i); 115 | } 116 | return Mout; 117 | } 118 | 119 | Vector6d voigt(Matrix3d Min) 120 | { 121 | Vector6d Vout(6); 122 | int I1,I2; 123 | for(int i = 0; i < 6; i++) 124 | { 125 | I1 = IJV[i][0]; 126 | I2 = IJV[i][1]; 127 | Vout(i) = Min(I1,I2); 128 | } 129 | return Vout; 130 | } 131 | 132 | Vector6i voigt(Matrix3i Min) 133 | { 134 | Vector6i Vout(6); 135 | int I1,I2; 136 | for(int i = 0; i < 6; i++) 137 | { 138 | I1 = IJV[i][0]; 139 | I2 = IJV[i][1]; 140 | Vout(i) = Min(I1,I2); 141 | } 142 | return Vout; 143 | } 144 | 145 | Matrix6d voigt(double M3333[3][3][3][3]) 146 | { 147 | Matrix6d Mout(6,6); 148 | int I1,I2,J1,J2; 149 | for(int i = 0; i < 6; i++) 150 | { 151 | I1 = IJV[i][0]; 152 | I2 = IJV[i][1]; 153 | for(int j = 0; j < 6; j++) 154 | { 155 | J1 = IJV[j][0]; 156 | J2 = IJV[j][1]; 157 | Mout(i,j) = M3333[I1][I2][J1][J2]; 158 | } 159 | } 160 | return Mout; 161 | } 162 | 163 | void voigt(Matrix6d Min, double M3333[3][3][3][3]) 164 | { 165 | int I1,I2,J1,J2; 166 | for(int i = 0; i < 6; i++) 167 | { 168 | I1 = IJV[i][0]; 169 | I2 = IJV[i][1]; 170 | for(int j = 0; j < 6; j++) 171 | { 172 | J1 = IJV[j][0]; 173 | J2 = IJV[j][1]; 174 | M3333[I1][I2][J1][J2] = Min(i,j); 175 | M3333[I2][I1][J1][J2] = Min(i,j); 176 | M3333[I1][I2][J2][J1] = Min(i,j); 177 | M3333[I2][I1][J2][J1] = Min(i,j); 178 | } 179 | } 180 | } 181 | 182 | //11-->1, 22-->2, 33-->3, 23=32-->4, 31=13-->5, 12=21-->6 \ 183 | 14-->7, 24-->8, 34-->9, 44-->10 184 | Vector10d voigt(Matrix4d Min) 185 | { 186 | Vector10d Vout; 187 | Vout(0) = Min(0,0); 188 | Vout(1) = Min(1,1); 189 | Vout(2) = Min(2,2); 190 | Vout(3) = Min(1,2); 191 | Vout(4) = Min(2,0); 192 | Vout(5) = Min(0,1); 193 | Vout(6) = Min(0,3); 194 | Vout(7) = Min(1,3); 195 | Vout(8) = Min(2,3); 196 | Vout(9) = Min(3,3); 197 | return Vout; 198 | } 199 | 200 | Matrix4d voigt(Vector10d Vin) 201 | { 202 | Matrix4d Mout; 203 | Mout(0,0) = Vin(0); 204 | Mout(1,1) = Vin(1); 205 | Mout(2,2) = Vin(2); 206 | Mout(1,2) = Vin(3); Mout(2,1) = Vin(3); 207 | Mout(2,0) = Vin(4); Mout(0,2) = Vin(4); 208 | Mout(0,1) = Vin(5); Mout(1,0) = Vin(5); 209 | Mout(0,3) = Vin(6); Mout(3,0) = Vin(6); 210 | Mout(1,3) = Vin(7); Mout(3,1) = Vin(7); 211 | Mout(2,3) = Vin(8); Mout(3,2) = Vin(8); 212 | Mout(3,3) = Vin(9); 213 | return Mout; 214 | } 215 | 216 | Matrix5d voigt6to5(Matrix6d M66) 217 | { 218 | Matrix M55; 219 | for (int i = 0; i < 2; i++) 220 | { 221 | M55(0,i) = M66(0,i); 222 | M55(1,i) = M66(1,i); 223 | M55(2,i) = M66(3,i); 224 | M55(3,i) = M66(4,i); 225 | M55(4,i) = M66(5,i); 226 | } 227 | for (int i = 2; i < 5; i++) 228 | { 229 | M55(0,i) = M66(0,i+1); 230 | M55(1,i) = M66(1,i+1); 231 | M55(2,i) = M66(3,i+1); 232 | M55(3,i) = M66(4,i+1); 233 | M55(4,i) = M66(5,i+1); 234 | } 235 | 236 | for (int i = 0; i < 2; i++) 237 | { 238 | M55(0,i) = M55(0,i) - M66(0,2); 239 | M55(1,i) = M55(1,i) - M66(1,2); 240 | M55(2,i) = M55(2,i) - M66(3,2); 241 | M55(3,i) = M55(3,i) - M66(4,2); 242 | M55(4,i) = M55(4,i) - M66(5,2); 243 | } 244 | return M55; 245 | } 246 | 247 | Matrix6d voigt5to6(Matrix5d M55) 248 | { 249 | Matrix6d M66; 250 | for (int i = 0; i < 2; i++) 251 | { 252 | M66(0,i) = M55(0,i); 253 | M66(1,i) = M55(1,i); 254 | M66(3,i) = M55(2,i); 255 | M66(4,i) = M55(3,i); 256 | M66(5,i) = M55(4,i); 257 | } 258 | for (int i = 3; i < 6; i++) 259 | { 260 | M66(0,i) = M55(0,i-1); 261 | M66(1,i) = M55(1,i-1); 262 | M66(3,i) = M55(2,i-1); 263 | M66(4,i) = M55(3,i-1); 264 | M66(5,i) = M55(4,i-1); 265 | 266 | M66(2,i) = - M66(0,i) - M66(1,i); 267 | M66(i,2) = M66(2,i); 268 | } 269 | 270 | M66(2,2) = 0; 271 | for (int i = 3; i < 6; i++) 272 | { 273 | M66(i,0) = M66(i,0) + M66(i,2); 274 | M66(i,1) = M66(i,1) + M66(i,2); 275 | } 276 | 277 | 278 | for (int i = 0; i < 2; i++) 279 | { 280 | M66(2,i) = -M66(0,i) - M66(1,i); 281 | M66(i,2) = M66(2,i); 282 | } 283 | 284 | for (int i = 0; i < 2; i++) 285 | { 286 | M66(0,i) = M66(0,i) + M66(0,2); 287 | M66(1,i) = M66(1,i) + M66(1,2); 288 | } 289 | return M66; 290 | } 291 | 292 | /// function definition of Chg_basis 293 | Matrix3d Chg_basis(VectorXd Vin) 294 | { 295 | Matrix3d Mout = Matrix3d::Zero(); 296 | for(int i = 0; i < 3; i++) 297 | for(int j = 0; j < 3; j++) 298 | for(int n = 0; n < Vin.size(); n++) 299 | Mout(i,j) += Vin(n) * Basis[i][j][n]; 300 | return Mout; 301 | } 302 | 303 | void Chg_basis(MatrixXd Min, double M3333[3][3][3][3]) 304 | { 305 | int KDIM = Min.cols(); 306 | double dummy = 0; 307 | for(int i = 0; i < 3; i++) 308 | for(int j = 0; j < 3; j++) 309 | for(int k = 0; k < 3; k++) 310 | for(int l = 0; l < 3; l++) 311 | { 312 | dummy = 0; 313 | for(int n = 0; n < KDIM; n++) 314 | for(int m = 0; m < KDIM; m++) 315 | dummy += Min(n,m)*Basis[i][j][n]*Basis[k][l][m]; 316 | M3333[i][j][k][l] = dummy; 317 | } 318 | } 319 | 320 | Vector6d Chg_basis6(Matrix3d Min) 321 | { 322 | Vector6d Vout = Vector6d::Zero(); 323 | for(int n = 0; n < 6; n++) 324 | for(int i = 0; i < 3; i++) 325 | for(int j = 0; j < 3; j++) 326 | Vout(n) += Min(i,j)*Basis[i][j][n]; 327 | return Vout; 328 | } 329 | 330 | Matrix6d Chg_basis6(Matrix6d Min) 331 | { 332 | double M3333[3][3][3][3] ={0}; 333 | voigt(Min,M3333); 334 | return Chg_basis6(M3333); 335 | } 336 | 337 | Matrix6d Chg_basis6(double M3333[3][3][3][3]) 338 | { 339 | Matrix6d Mout = Matrix6d::Zero(); 340 | for(int n = 0; n < 6; n++) 341 | for(int m = 0; m < 6; m++) 342 | for(int i = 0; i < 3; i++) 343 | for(int j = 0; j < 3; j++) 344 | for(int k = 0; k < 3; k++) 345 | for(int l = 0; l < 3; l++) 346 | Mout(n,m) += M3333[i][j][k][l]*Basis[i][j][n]*Basis[k][l][m]; 347 | 348 | return Mout; 349 | } 350 | 351 | Vector5d Chg_basis5(Matrix3d Min) 352 | { 353 | Vector5d Vout = Vector5d::Zero(); 354 | for(int n = 0; n < 5; n++) 355 | for(int i = 0; i < 3; i++) 356 | for(int j = 0; j < 3; j++) 357 | Vout(n) += Min(i,j)*Basis[i][j][n]; 358 | return Vout; 359 | } 360 | 361 | Matrix5d Chg_basis5(Matrix6d Min) 362 | { 363 | double M3333[3][3][3][3] ={0}; 364 | voigt(Min,M3333); 365 | return Chg_basis5(M3333); 366 | } 367 | 368 | Matrix5d Chg_basis5(double M3333[3][3][3][3]) 369 | { 370 | Matrix5d Mout = Matrix5d::Zero(); 371 | for(int n = 0; n < 5; n++) 372 | for(int m = 0; m < 5; m++) 373 | for(int i = 0; i < 3; i++) 374 | for(int j = 0; j < 3; j++) 375 | for(int k = 0; k < 3; k++) 376 | for(int l = 0; l < 3; l++) 377 | Mout(n,m) += M3333[i][j][k][l]*Basis[i][j][n]*Basis[k][l][m]; 378 | 379 | return Mout; 380 | } 381 | 382 | /// function definition of Euler 383 | Matrix3d Euler_trans(Vector3d Vin) 384 | { 385 | Matrix3d Mout; 386 | double PH,TH,TM; 387 | Vin = Vin / 180 * M_PI; // in radians 388 | PH = Vin(0); 389 | TH = Vin(1); 390 | TM = Vin(2); 391 | 392 | double SPH,STH,STM; 393 | double CPH,CTH,CTM; 394 | SPH=sin(PH); CPH=cos(PH); 395 | STH=sin(TH); CTH=cos(TH); 396 | STM=sin(TM); CTM=cos(TM); 397 | Mout(0,0)=CTM*CPH-SPH*STM*CTH; 398 | Mout(1,0)=-STM*CPH-SPH*CTM*CTH; 399 | Mout(2,0)=SPH*STH; 400 | Mout(0,1)=CTM*SPH+CPH*STM*CTH; 401 | Mout(1,1)=-SPH*STM+CPH*CTM*CTH; 402 | Mout(2,1)=-STH*CPH; 403 | Mout(0,2)=STH*STM; 404 | Mout(1,2)=CTM*STH; 405 | Mout(2,2)=CTH; 406 | 407 | return Mout; 408 | } 409 | 410 | Vector3d Euler_trans(Matrix3d Min) 411 | { 412 | Vector3d Vout; 413 | double PH,TH,TM; 414 | double STH; 415 | 416 | TH = acos(Min(2,2)); 417 | if(abs(Min(2,2))>= 0.999) 418 | { 419 | TM = 0; 420 | PH = atan2(Min(0,1),Min(0,0)); 421 | } 422 | else 423 | { 424 | STH = sin(TH); 425 | TM = atan2(Min(0,2)/STH,Min(1,2)/STH); 426 | PH = atan2(Min(2,0)/STH,-Min(2,1)/STH); 427 | } 428 | Vout << PH,TH,TM; 429 | Vout = Vout * 180 / M_PI; // in degree 430 | return Vout; 431 | } 432 | 433 | /// function definition of Identity tensor 434 | double Iij(int i, int j) 435 | { 436 | if(i == j) return 1; 437 | return 0; 438 | } 439 | 440 | // function definition of Eigsrt 441 | void Eigsrt(Matrix3d &V, Vector3d &D) 442 | { 443 | int n = 3; 444 | double P,t; 445 | int K; 446 | for(int i = 0; i < n-1; i++) 447 | { 448 | K = i; 449 | P = D(i); 450 | for(int j = i+1; j < n; j++) 451 | if(D(j) >= P) 452 | { K = j; P = D(j);} 453 | 454 | if(K != i) 455 | { 456 | D(K) = D(i); 457 | D(i) = P; 458 | for(int m = 0; m < n; m++) 459 | { 460 | t = V(m,i); 461 | V(m,i) = V(m,K); 462 | V(m,K) = t; 463 | } 464 | } 465 | } 466 | 467 | // int count = 0; 468 | // for(int j = 0; j < 3; j++) 469 | // { 470 | // count = 0; 471 | // for(int i = 0; i < 3; i++) 472 | // if( V(i,j) < 0) count+=1; 473 | // if(count > 2) V.col(j) = -V.col(j); 474 | // } 475 | } 476 | 477 | //fuction definition of Mult_voigt 478 | Vector6d Mult_voigt(Matrix6d B, Vector6d C) 479 | { 480 | Vector6d A; 481 | A(0)=B(0,0)*C(0)+B(5,5)*C(1)+B(4,4)*C(2)\ 482 | +2*(B(4,5)*C(3)+B(0,4)*C(4)+B(0,5)*C(5)); 483 | 484 | A(1)=B(5,5)*C(0)+B(1,1)*C(1)+B(3,3)*C(2)\ 485 | +2*(B(1,3)*C(3)+B(3,5)*C(4)+B(1,5)*C(5)); 486 | 487 | A(2)=B(4,4)*C(0)+B(3,3)*C(1)+B(2,2)*C(2)\ 488 | +2*(B(2,3)*C(3)+B(2,4)*C(4)+B(3,4)*C(5)); 489 | 490 | A(3)=B(4,5)*C(0)+B(1,3)*C(1)+B(2,3)*C(2)\ 491 | +(B(1,2)+B(3,3))*C(3)\ 492 | +(B(2,5)+B(3,4))*C(4)\ 493 | +(B(3,5)+B(1,4))*C(5); 494 | 495 | A(4)=B(0,4)*C(0)+B(3,5)*C(1)+B(2,4)*C(2)\ 496 | +(B(2,5)+B(3,4))*C(3)\ 497 | +(B(0,2)+B(4,4))*C(4)\ 498 | +(B(0,3)+B(4,5))*C(5); 499 | 500 | A(5)=B(0,5)*C(0)+B(1,5)*C(1)+B(3,4)*C(2)\ 501 | +(B(3,5)+B(1,4))*C(3)\ 502 | +(B(0,3)+B(4,5))*C(4)\ 503 | +(B(0,1)+B(5,5))*C(5); 504 | return A; 505 | } 506 | 507 | //fuction definition of Inv_voigt 508 | void Inv_voigt(double A[3][3][3][3], double Ainv[3][3][3][3]) 509 | { 510 | Matrix6d Ainv66; 511 | Ainv66 = voigt(A).inverse(); 512 | voigt(Ainv66, Ainv); 513 | } 514 | 515 | //fuction definition of Errorcal 516 | double Errorcal(Matrix6d A, Matrix6d B) 517 | { 518 | double err; 519 | Matrix6d C1,C2; 520 | C1 = A - B; 521 | C2 = 0.5*(A + B); 522 | err = C1.norm()/C2.norm(); 523 | return err; 524 | } 525 | 526 | double Errorcal(Vector6d A, Vector6d B) 527 | { 528 | double err; 529 | double A1 = A.norm(); 530 | double B1 = B.norm(); 531 | double Tmax = max(A1, B1); 532 | double Tmin = min(A1, B1); 533 | if(Tmax==0) 534 | {err = 0;} 535 | else if(Tmin/Tmax < 1e-3) 536 | {err = Tmax - Tmin;} 537 | else 538 | { 539 | Vector6d C1,C2; 540 | C1 = A - B; 541 | C2 = 0.5*(A + B); 542 | err = C1.norm()/C2.norm(); 543 | } 544 | return err; 545 | } 546 | 547 | double Errorcal(Matrix3d A, Matrix3d B) 548 | { 549 | double err; 550 | Matrix3d C1,C2; 551 | C1 = A - B; 552 | C2 = 0.5*(A + B); 553 | err = C1.norm()/C2.norm(); 554 | return err; 555 | } 556 | 557 | double Errorcal(Matrix5d A, Matrix5d B) 558 | { 559 | double err; 560 | Matrix5d C1,C2; 561 | C1 = A - B; 562 | C2 = 0.5*(A + B); 563 | err = C1.norm()/C2.norm(); 564 | return err; 565 | } 566 | 567 | //function definition of mult_dot 568 | Vector6d mult_dot(Vector6d Vin, Vector6i Iv) 569 | { 570 | Vector6d Vout; 571 | int n = 6; 572 | for(int i = 0; i < n; i++) 573 | Vout(i) = Vin(i)*Iv(i); 574 | return Vout; 575 | } 576 | 577 | void mult_4th(double A[3][3][3][3],double B[3][3][3][3],double C[3][3][3][3]) 578 | { 579 | for(int i = 0; i < 3; i++) 580 | for(int j = 0; j < 3; j++) 581 | for(int k = 0; k < 3; k++) 582 | for(int l = 0; l < 3; l++) 583 | for(int m = 0; m < 3; m++) 584 | for(int n = 0; n < 3; n++) 585 | C[i][j][k][l] = A[i][j][m][n] * B[m][n][k][l]; 586 | } 587 | 588 | Matrix3d mult_4th(double A[3][3][3][3],Matrix3d B) 589 | { 590 | Matrix3d C = Matrix3d::Zero(); 591 | for(int i = 0; i < 3; i++) 592 | for(int j = 0; j < 3; j++) 593 | for(int k = 0; k < 3; k++) 594 | for(int l = 0; l < 3; l++) 595 | C(i,j) = A[i][j][k][l] * B(k,l); 596 | return C; 597 | } 598 | 599 | //function definition of devia 600 | Matrix3d devia(Matrix3d X) 601 | { 602 | Matrix3d Mout = X; 603 | //transform into the deviatoric tensor 604 | double pr = (X(0,0) + X(1,1) + X(2,2))/3; 605 | Mout(0,0) = X(0,0) - pr; 606 | Mout(1,1) = X(1,1) - pr; 607 | Mout(2,2) = X(2,2) - pr; 608 | return Mout; 609 | } 610 | 611 | Vector6d devia(Vector6d X) 612 | { 613 | Vector6d Vout = X; 614 | //transform into the deviatoric tensor 615 | double pr = (X(0) + X(1) + X(2))/3; 616 | Vout(0) = X(0) - pr; 617 | Vout(1) = X(1) - pr; 618 | Vout(2) = X(2) - pr; 619 | return Vout; 620 | } 621 | 622 | Matrix6d devia(Matrix6d Min) 623 | { 624 | Matrix6d deviaM; 625 | deviaM<< 2/3, -1/3, -1/3, 0, 0, 0, 626 | -1/3, 2/3, -1/3, 0, 0, 0, 627 | -1/3, -1/3, 2/3, 0, 0, 0, 628 | 0, 0, 0, 1, 0, 0, 629 | 0, 0, 0, 0, 1, 0, 630 | 0, 0, 0, 0, 0, 1; 631 | return Min*deviaM; 632 | } 633 | 634 | //definition of rotate 6*6 tensor 635 | Matrix6d rotate_C66(Matrix6d C66, Matrix3d E) 636 | { 637 | Matrix6d E66, E66T; 638 | E66 = rot_stress(E); 639 | E66T = E66.transpose(); 640 | return E66*C66*E66T; 641 | } 642 | 643 | Matrix6d rot_stress(Matrix3d M) 644 | { 645 | Matrix6d M66; 646 | double xx,yy,zz,yz,xz,xy,yx,zx,zy; 647 | xx = M(0,0); 648 | yy = M(1,1); 649 | zz = M(2,2); 650 | yz = M(1,2); 651 | xz = M(0,2); 652 | xy = M(0,1); 653 | yx = M(1,0); 654 | zx = M(2,0); 655 | zy = M(2,1); 656 | 657 | for(int i = 0; i < 3; i++) 658 | for(int j = 0; j < 3; j++) 659 | M66(i,j) = M(i,j)*M(i,j); 660 | 661 | M66(0,3) = 2*xy*xz; 662 | M66(0,4) = 2*xx*xz; 663 | M66(0,5) = 2*xx*xy; 664 | 665 | M66(1,3) = 2*yy*yz; 666 | M66(1,4) = 2*yx*yz; 667 | M66(1,5) = 2*yx*yy; 668 | 669 | M66(2,3) = 2*zy*zz; 670 | M66(2,4) = 2*zx*zz; 671 | M66(2,5) = 2*zx*zy; 672 | 673 | M66(3,0) = yx*zx; 674 | M66(3,1) = yy*zy; 675 | M66(3,2) = yz*zz; 676 | 677 | M66(4,0) = xx*zx; 678 | M66(4,1) = xy*zy; 679 | M66(4,2) = xz*zz; 680 | 681 | M66(5,0) = xx*yx; 682 | M66(5,1) = xy*yy; 683 | M66(5,2) = xz*yz; 684 | 685 | M66(3,3) = yy*zz+yz*zy; 686 | M66(3,4) = yx*zz+yz*zx; 687 | M66(3,5) = yx*zy+yy*zx; 688 | 689 | M66(4,3) = xy*zz+xz*zy; 690 | M66(4,4) = xx*zz+xz*zx; 691 | M66(4,5) = xx*zy+xy*zx; 692 | 693 | M66(5,3) = xy*yz+xz*yy; 694 | M66(5,4) = xx*yz+xz*yx; 695 | M66(5,5) = xx*yy+xy*yx; 696 | 697 | return M66; 698 | } 699 | 700 | void rot_4th(double A[3][3][3][3], Matrix3d E, double B[3][3][3][3]) 701 | { 702 | double DUMMY; 703 | for(int i = 0; i < 3; i++) 704 | for(int j = 0; j < 3; j++) 705 | for(int m = 0; m < 3; m++) 706 | for(int n = 0; n < 3; n++) 707 | { 708 | DUMMY = 0; 709 | for(int i1 = 0; i1 < 3; i1++) 710 | for(int j1 = 0; j1 < 3; j1++) 711 | for(int m1 = 0; m1 < 3; m1++) 712 | for(int n1 = 0; n1 < 3; n1++) 713 | DUMMY += E(i,i1)*E(j,j1)*E(m,m1)*E(n,n1)*A[i1][j1][m1][n1]; 714 | B[i][j][m][n] = DUMMY; 715 | } 716 | } 717 | 718 | //convention between voigt C66 and Bbasis C66orC55 719 | Matrix6d Btovoigt(MatrixXd B) 720 | { 721 | double C4[3][3][3][3] = {0}; 722 | Chg_basis(B,C4); 723 | return voigt(C4); 724 | } 725 | 726 | Matrix5d voigttoB5(Matrix6d M) 727 | { 728 | double C4[3][3][3][3] = {0}; 729 | voigt(M,C4); 730 | return Chg_basis5(C4); 731 | } 732 | 733 | Matrix6d voigttoB6(Matrix6d M) 734 | { 735 | double C4[3][3][3][3] = {0}; 736 | voigt(M,C4); 737 | return Chg_basis6(C4); 738 | } 739 | 740 | //definition of Rodrigues 741 | Matrix3d Rodrigues(Matrix3d C) 742 | { 743 | Matrix3d AROT; 744 | // Matrix3d Iij3; Iij(Iij3); 745 | Vector3d V; 746 | V(0)=C(2,1); V(1)=C(0,2); V(2)=C(1,0); 747 | double Vnorm = V.norm(); 748 | if(Vnorm < 1e-30) 749 | AROT = Matrix3d::Identity(); 750 | else 751 | { 752 | double Coef1 = sin(Vnorm)/Vnorm; 753 | double Coef2 = (1.0 - cos(Vnorm))/(Vnorm*Vnorm); 754 | AROT = Matrix3d::Identity() + Coef1*C + Coef2*C*C; 755 | } 756 | return AROT; 757 | } 758 | 759 | Matrix6d Bbasisadd(Matrix6d M66,Matrix5d M55) 760 | { 761 | Matrix6d Mout; 762 | Mout = M66; 763 | Mout.block(0,0,5,5) += M55; 764 | return Mout; 765 | } 766 | 767 | Vector6d Bbasisadd(Vector6d V6,Vector5d V5) 768 | { 769 | Vector6d Vout; 770 | Vout = V6; 771 | Vout.head(5) += V5; 772 | return Vout; 773 | } 774 | 775 | int Jacobi(Matrix3d A,Vector3d &D,Matrix3d &V) 776 | { 777 | int n = 3; 778 | V = Matrix3d::Identity(); 779 | Vector3d B,Z; 780 | for(int i = 0; i < n; i++) 781 | { 782 | B(i) = A(i,i); 783 | D(i) = B(i); 784 | Z(i) = 0; 785 | } 786 | int Nrot = 0; 787 | 788 | double Sm, Tresh, G, H, T, theta; 789 | double C, S, Tau; 790 | 791 | for(int i = 0; i < 50; i++) 792 | { 793 | Sm = 0; 794 | for(int ip = 0; ip < n-1; ip++) 795 | for(int iq = ip+1; iq < n; iq++) 796 | Sm += abs(A(ip,iq)); 797 | if(Sm == 0) return 0; 798 | 799 | Tresh = 0; 800 | if(i < 4) Tresh = 0.2*Sm/n/n; 801 | 802 | for(int ip = 0; ip < n-1; ip++) 803 | for(int iq = ip+1; iq < n; iq++) 804 | { 805 | G=100*abs(A(ip,iq)); 806 | if((i > 4)&&(abs(D(ip))+G == abs(D(ip)))&&(abs(D(iq))+G == abs(D(iq)))) 807 | {A(ip,iq) = 0;} 808 | else if(abs(A(ip,iq))>Tresh) 809 | { 810 | H = D(iq)-D(ip); 811 | if(abs(H)+G == abs(H)) 812 | {T=A(ip,iq)/H;} 813 | else 814 | { 815 | theta = 0.5*H/A(ip,iq); 816 | T=1.0/(abs(theta)+sqrt(1.0+theta*theta)); 817 | if(theta < 0) T=-T; 818 | } 819 | C=1.0/sqrt(1+T*T); 820 | S=T*C; 821 | Tau=S/(1.0+C); 822 | H=T*A(ip,iq); 823 | Z(ip)=Z(ip)-H; 824 | Z(iq)=Z(iq)+H; 825 | D(ip)=D(ip)-H; 826 | D(iq)=D(iq)+H; 827 | A(ip,iq)=0.0; 828 | for(int j = 0; j < ip-1; j++) 829 | { 830 | G=A(j,ip); 831 | H=A(j,iq); 832 | A(j,ip)=G-S*(H+G*Tau); 833 | A(j,iq)=H+S*(G-H*Tau); 834 | } 835 | for(int j = ip+1; j < iq-1; j++) 836 | { 837 | G=A(ip,j); 838 | H=A(j,iq); 839 | A(ip,j)=G-S*(H+G*Tau); 840 | A(j,iq)=H+S*(G-H*Tau); 841 | } 842 | for(int j = iq+1; j < n; j++) 843 | { 844 | G=A(ip,j); 845 | H=A(iq,j); 846 | A(ip,j)=G-S*(H+G*Tau); 847 | A(iq,j)=H+S*(G-H*Tau); 848 | } 849 | for(int j = 0; j < n; j++) 850 | { 851 | G=V(j,ip); 852 | H=V(j,iq); 853 | V(j,ip)=G-S*(H+G*Tau); 854 | V(j,iq)=H+S*(G-H*Tau); 855 | } 856 | Nrot += 1; 857 | } 858 | } 859 | for(int ik = 0; ik < n; ik++) 860 | { 861 | B(ik)=B(ik)+Z(ik); 862 | D(ik)=B(ik); 863 | Z(ik)=0; 864 | } 865 | } 866 | return 1; 867 | } -------------------------------------------------------------------------------- /Toolbox.h: -------------------------------------------------------------------------------- 1 | #ifndef TOOLBOX_H 2 | #define TOOLBOX_H 3 | 4 | #if __INTELLISENSE__ 5 | #undef __ARM_NEON 6 | #undef __ARM_NEON__ 7 | #endif 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #define SQR2 1.41421356237309 14 | #define RSQ2 0.70710678118654744 15 | #define RSQ3 0.57735026918962584 16 | #define RSQ6 0.40824829046386304 17 | 18 | using namespace std; 19 | using namespace Eigen; 20 | 21 | // 22 | #define Intn 10 //number of integral points in Eshelby calculation 23 | #define Mtr 1 //number of Multithread 24 | // 25 | typedef Matrix Matrix6d; 26 | typedef Matrix Matrix5d; 27 | typedef Matrix Vector6d; 28 | typedef Matrix Vector5d; 29 | typedef Matrix Vector6i; 30 | typedef Matrix Vector10d; 31 | typedef Matrix Integralpoint3; 32 | typedef Matrix Integralpoint6; 33 | typedef Matrix Integralpoint1; 34 | 35 | ////////// 36 | struct Gausspoint 37 | { 38 | //integral points and weights 39 | Integralpoint3 Gpalpha, Gpaww; 40 | Integralpoint6 Gpaa6, Gpaaww6; //coordinate and weigts in Fourier space 41 | Integralpoint1 Gpww; 42 | }; 43 | 44 | ///////////////////////// 45 | //choose the gausspoint set according to the length of ellisoid 46 | int Eshelby_case(Vector3d); 47 | ///////////////////////// 48 | 49 | ///////////////////////// 50 | //Identity tensor 51 | double Iij(int, int); 52 | ///////////////////////// 53 | 54 | ///////////////////////// 55 | //transform into the deviatoric tensor 56 | Matrix3d devia(Matrix3d); 57 | Vector6d devia(Vector6d); 58 | Matrix6d devia(Matrix6d); 59 | ///////////////////////// 60 | 61 | ///////////////////////// 62 | //A(I,K)=B(I,J,K,L)*C(J,L) using voigt's notation 63 | Vector6d Mult_voigt(Matrix6d, Vector6d); 64 | ///////////////////////// 65 | 66 | ///////////////////////// 67 | //calculate the inverse of a forth order tensor A 68 | void Inv_voigt(double A[3][3][3][3], double Ainv[3][3][3][3]); 69 | //parameters: double A[3][3][3][3], double Ainv[3][3][3][3] 70 | //Ainv = A^-1 as a output 71 | ///////////////////////// 72 | 73 | ///////////////////////// 74 | //calculate the error between matrix A and B 75 | double Errorcal(Matrix6d, Matrix6d); 76 | double Errorcal(Vector6d, Vector6d); 77 | double Errorcal(Matrix3d, Matrix3d); 78 | double Errorcal(Matrix5d, Matrix5d); 79 | ///////////////////////// 80 | 81 | ///////////////////////// 82 | //Sort the eigen values from largest to smallest 83 | // and change the order of the eigen vectors 84 | void Eigsrt(Matrix3d &, Vector3d &); 85 | ///////////////////////// 86 | 87 | ///////////////////////// 88 | //calculate C(i) = A(i)*B(i) 89 | Vector6d mult_dot(Vector6d, Vector6i); 90 | //calculate Cijkl = Aijmn * Bmnkl 91 | void mult_4th(double A[3][3][3][3],double B[3][3][3][3],double C[3][3][3][3]); 92 | //calculate Cij = Aijkl * Bkl 93 | Matrix3d mult_4th(double A[3][3][3][3],Matrix3d B); 94 | ///////////////////////// 95 | 96 | ///////////////////////// 97 | //THE EULER ANGLES ASSOCIATED WITH THE TRANSFORMATION MATRIX 98 | Matrix3d Euler_trans(Vector3d); 99 | Vector3d Euler_trans(Matrix3d); 100 | ///////////////////////// 101 | 102 | ///////////////////////// 103 | //Chg_basis and its overload function 104 | //with BASIS TENSOR Basis[3][3][6] 105 | Matrix3d Chg_basis(VectorXd); 106 | void Chg_basis(MatrixXd, double M3333[3][3][3][3]); 107 | /// 108 | Vector6d Chg_basis6(Matrix3d); 109 | Matrix6d Chg_basis6(Matrix6d); 110 | Matrix6d Chg_basis6(double M3333[3][3][3][3]); 111 | /// 112 | Vector5d Chg_basis5(Matrix3d); 113 | Matrix5d Chg_basis5(Matrix6d); 114 | Matrix5d Chg_basis5(double M3333[3][3][3][3]); 115 | ///////////////////////// 116 | 117 | ///////////////////////// 118 | //change a B-basis tensor into voigt notation 119 | Matrix6d Btovoigt(MatrixXd); 120 | Matrix5d voigttoB5(Matrix6d); 121 | Matrix6d voigttoB6(Matrix6d); 122 | ///////////////////////// 123 | 124 | ///////////////////////// 125 | //Voigt and its overload function 126 | //to realize the 3X3X3X3 to 6X6 and the reverse transformation 127 | //and realize the 3X3 to 6X1 and the reverse transformation 128 | //11-->1, 22-->2, 33-->3, 23=32-->4, 31=13-->5, 12=21-->6 129 | Matrix3d voigt(Vector6d); // 6X1 to 3X3 130 | Vector6d voigt(Matrix3d); // 3X3 to 6X1 131 | Matrix6d voigt(double M3333[3][3][3][3]); // 3X3X3X3 to 6X6 132 | void voigt(Matrix6d, double M3333[3][3][3][3]); // 6X6 to 3X3X3X3 133 | Vector10d voigt(Matrix4d); // 4X4 to 10X1 134 | Matrix4d voigt(Vector10d); // 10X1 to 4X4 135 | Vector6i voigt(Matrix3i); //int version 136 | 137 | Matrix5d voigt6to5(Matrix6d); 138 | Matrix6d voigt5to6(Matrix5d); 139 | ///////////////////////// 140 | 141 | ///////////////////////// 142 | Matrix6d Bbasisadd(Matrix6d,Matrix5d); 143 | Vector6d Bbasisadd(Vector6d,Vector5d); 144 | ///////////////////////// 145 | 146 | ///////////////////////// 147 | //Gauss-Legendre points 148 | //double x1, double x2, Vector x,w,int n 149 | //calculate the points and weights (VectorXd x,w) 150 | //according the Integral interval (x1, x2) and number of points (n) 151 | void gau_leg(double, double, VectorXd &, VectorXd &, int); 152 | ///////////////////////// 153 | 154 | ///////////////////////// 155 | //Rotate the stiffness or compliance in 6*6 matrix 156 | Matrix6d rotate_C66(Matrix6d C66, Matrix3d M); 157 | Matrix6d rot_stress(Matrix3d); 158 | void rot_4th(double A[3][3][3][3], Matrix3d, double B[3][3][3][3]); 159 | ///////////////////////// 160 | 161 | ///////////////////////// 162 | //Refer to Appendix D: Crystal rotation (Rodrigues) and misorientation 163 | Matrix3d Rodrigues(Matrix3d); 164 | ///////////////////////// 165 | 166 | int Jacobi(Matrix3d A,Vector3d &D,Matrix3d &V); 167 | 168 | #endif -------------------------------------------------------------------------------- /global.cpp: -------------------------------------------------------------------------------- 1 | #include "global.h" 2 | using namespace std; 3 | 4 | double temp_K = 0.0; 5 | Logger logger; 6 | 7 | void update_progress(double progress_f) 8 | { 9 | const int bar_width = 70; 10 | int bar_position = (int)(bar_width * progress_f); 11 | 12 | std::cout << "["; 13 | for (int i = 0; i < bar_width; ++i) { 14 | if (i < bar_position) { 15 | std::cout << "="; 16 | } else if (i == bar_position) { 17 | std::cout << ">"; 18 | } else { 19 | std::cout << " "; 20 | } 21 | } 22 | std::cout << "] " << (int)(progress_f * 100) << "%\r"; 23 | std::cout.flush(); 24 | } 25 | -------------------------------------------------------------------------------- /global.h: -------------------------------------------------------------------------------- 1 | #ifndef GLOBALS_H 2 | #define GLOBALS_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | extern double temp_K; 12 | extern std::ofstream outfile; 13 | class Logger; 14 | extern Logger logger; // Global logger object, include global.h to use it 15 | 16 | void update_progress(double progress_f); 17 | 18 | // Logger class for logging messages to the console and a log file 19 | class Logger { 20 | public: 21 | Logger() : outfile("EVPSC_log.txt") {} 22 | 23 | // Define the message hierarchy levels inside the Logger class 24 | enum class MessageLevel { 25 | DEBUG, 26 | NOTICE, 27 | WARN, 28 | INFO, 29 | ERROR, 30 | }; 31 | 32 | // Log a message at a specific message level 33 | void log(MessageLevel level, const std::string& message) { 34 | // Get the current time 35 | std::time_t t = std::time(nullptr); 36 | std::string timestamp = std::asctime(std::localtime(&t)); 37 | timestamp.pop_back(); // Remove the newline character from the end 38 | 39 | // Output the message to the console 40 | if (console_level_ <= level) { 41 | std::cout << "[" << timestamp << "] "; 42 | printPrefix(level); 43 | std::cout << message << std::endl; 44 | } 45 | 46 | // Output the message to the log file 47 | if (file_level_ <= level) { 48 | outfile << "[" << timestamp << "] "; 49 | printPrefix(level, outfile); 50 | outfile << message << std::endl; 51 | } 52 | } 53 | 54 | void log(MessageLevel level, const Eigen::MatrixXd& message) { 55 | // Get the current time 56 | std::time_t t = std::time(nullptr); 57 | std::string timestamp = std::asctime(std::localtime(&t)); 58 | timestamp.pop_back(); // Remove the newline character from the end 59 | Eigen::IOFormat LogFmt(4, 0, ", ", "\n", "["+timestamp+"] "+getPrefix(level)+ "[", "]"); 60 | // Output the message to the console 61 | if (console_level_ <= level) { 62 | std::cout << message.format(LogFmt) << std::endl; 63 | } 64 | // Output the message to the log file 65 | if (file_level_ <= level) { 66 | outfile << message.format(LogFmt) << std::endl; 67 | } 68 | } 69 | 70 | // Overloaded functions for different message levels 71 | void debug(const std::string& message) { log(MessageLevel::DEBUG, message); } 72 | void info(const std::string& message) { log(MessageLevel::INFO, message); } 73 | void notice(const std::string& message) { log(MessageLevel::NOTICE, message); } 74 | void warn(const std::string& message) { log(MessageLevel::WARN, message); } 75 | void error(const std::string& message) { log(MessageLevel::ERROR, message); } 76 | void debug(const Eigen::MatrixXd& message) { log(MessageLevel::DEBUG, message); } 77 | void info(const Eigen::MatrixXd& message) { log(MessageLevel::INFO, message); } 78 | void notice(const Eigen::MatrixXd& message) { log(MessageLevel::NOTICE, message); } 79 | void warn(const Eigen::MatrixXd& message) { log(MessageLevel::WARN, message); } 80 | void error(const Eigen::MatrixXd& message) { log(MessageLevel::ERROR, message); } 81 | // Set the message level filter for console output 82 | void setConsoleLevel(MessageLevel level) { console_level_ = level; } 83 | 84 | // Set the message level filter for file output 85 | void setFileLevel(MessageLevel level) { file_level_ = level; } 86 | 87 | private: 88 | std::ofstream outfile; 89 | MessageLevel console_level_ = MessageLevel::INFO; 90 | MessageLevel file_level_ = MessageLevel::DEBUG; 91 | 92 | // Helper function to print the message prefix based on the message level 93 | void printPrefix(MessageLevel level, std::ostream& stream = std::cout) { 94 | switch (level) { 95 | case MessageLevel::DEBUG: 96 | stream << "[ DEBUG] "; 97 | break; 98 | case MessageLevel::INFO: 99 | stream << "[ INFO ] "; 100 | break; 101 | case MessageLevel::NOTICE: 102 | stream << "[NOTICE] "; 103 | break; 104 | case MessageLevel::WARN: 105 | stream << "[ WARN ] "; 106 | break; 107 | case MessageLevel::ERROR: 108 | stream << "[ ERROR] "; 109 | break; 110 | default: 111 | break; 112 | } 113 | } 114 | std::string getPrefix(MessageLevel level) { 115 | switch (level) { 116 | case MessageLevel::DEBUG: 117 | return "[ DEBUG] "; 118 | case MessageLevel::INFO: 119 | return "[ INFO ] "; 120 | case MessageLevel::NOTICE: 121 | return "[NOTICE] "; 122 | case MessageLevel::WARN: 123 | return "[ WARN ] "; 124 | case MessageLevel::ERROR: 125 | return "[ ERROR] "; 126 | default: 127 | return ""; 128 | } 129 | } 130 | }; 131 | 132 | 133 | #endif 134 | 135 | -------------------------------------------------------------------------------- /workspace.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | } 6 | ], 7 | "settings": { 8 | "files.associations": { 9 | "iostream": "cpp", 10 | "random": "cpp", 11 | "ostream": "cpp", 12 | "*.expression": "cpp", 13 | "alignedvector3": "cpp", 14 | "fft": "cpp", 15 | "string_view": "cpp", 16 | "array": "cpp", 17 | "atomic": "cpp", 18 | "*.tcc": "cpp", 19 | "cctype": "cpp", 20 | "chrono": "cpp", 21 | "clocale": "cpp", 22 | "cmath": "cpp", 23 | "complex": "cpp", 24 | "condition_variable": "cpp", 25 | "cstdarg": "cpp", 26 | "cstddef": "cpp", 27 | "cstdint": "cpp", 28 | "cstdio": "cpp", 29 | "cstdlib": "cpp", 30 | "cstring": "cpp", 31 | "ctime": "cpp", 32 | "cwchar": "cpp", 33 | "cwctype": "cpp", 34 | "deque": "cpp", 35 | "list": "cpp", 36 | "unordered_map": "cpp", 37 | "unordered_set": "cpp", 38 | "vector": "cpp", 39 | "exception": "cpp", 40 | "algorithm": "cpp", 41 | "functional": "cpp", 42 | "iterator": "cpp", 43 | "map": "cpp", 44 | "memory": "cpp", 45 | "memory_resource": "cpp", 46 | "numeric": "cpp", 47 | "optional": "cpp", 48 | "ratio": "cpp", 49 | "set": "cpp", 50 | "string": "cpp", 51 | "system_error": "cpp", 52 | "tuple": "cpp", 53 | "type_traits": "cpp", 54 | "utility": "cpp", 55 | "hash_map": "cpp", 56 | "fstream": "cpp", 57 | "future": "cpp", 58 | "initializer_list": "cpp", 59 | "iomanip": "cpp", 60 | "iosfwd": "cpp", 61 | "istream": "cpp", 62 | "limits": "cpp", 63 | "mutex": "cpp", 64 | "new": "cpp", 65 | "sstream": "cpp", 66 | "stdexcept": "cpp", 67 | "streambuf": "cpp", 68 | "thread": "cpp", 69 | "cinttypes": "cpp", 70 | "typeinfo": "cpp", 71 | "valarray": "cpp", 72 | "dense": "cpp", 73 | "regex": "cpp", 74 | "bitset": "cpp", 75 | "__locale": "cpp" 76 | } 77 | } 78 | } --------------------------------------------------------------------------------