#include<iostream>
#include<vector>
#include<cmath>
#include<iomanip>
std::vector<std::vector<int>> mat_voigt_ind(const int N)
{
/** this function will create pointer vector of matrix mat
* in voigt notation
*/
/** for every element A(i,j) of given
* it will stores it index in the voigt vetor
* given that matrix is square matrix of size N x N*/
std::vector<std::vector<int>> mat = std::vector<std::vector<int>>(N, std::vector<int>(N, 0)) ;
// starting and end index of the column to be filled
std::size_t row_s = 0 ;
std::size_t row_e = N - 1 ;
std::size_t col_s = 0 ;
std::size_t col_e = N - 1 ;
/**we will fill diagonal first
* then the last column
* then first row
*
* now next iteration
*/
// starting index for matrix
int i = row_s ;
int j = col_s ;
// k upto (N*N + N)/2 means we will run loop only for upper triangulat matrix
for(std::size_t k = 0; k < (N*N + N)/2; k++)
{
mat[i][j] = k ;
/** if non diagonal el, then add the el of lower triangle also */
if(i != j)
mat[j][i] = k + (N*N - N)/2 ;
/** now update the index for matrix */
// last column
if(j == col_e and i > row_s)
i-- ;
// first row
else if(i == row_s and j > col_s + 1)
j-- ;
// condition for next cycle
else if(i == row_s and j == col_s + 1)
{
row_s += 1 ;
row_e -= 2 ;
col_s += 2 ;
col_e -= 1 ;
i = row_s ;
j = col_s ;
}
// along the diagonal
else
{
i++ ;
j++ ;
}
}
return mat ;
}
template <class T>
std::vector<std::vector<T>> dyadic(const std::vector<std::vector<T>>& A, const std::vector<std::vector<T>>& B)
{
/** it will retun C as A dyadic B
* given dimensions of A and B are equal
*/
int N = A.size() ;
std::vector<std::vector<T>> C(N*N, std::vector<float>(N*N,0)) ; // N is the size of matrix A, i.e. which is calling the function
/** if size of A and B are not equal */
if(A.size() != B.size())
return C ;
/** generate a matrix of same size as A and B
* which will store the index of voigt's matrix for that index of matrix
*/
std::vector<std::vector<int>> voigt_mat = mat_voigt_ind(N) ;
/** Cijkl = Aij * Bkl */
for(int i= 0; i<N; i++)
for(int j= 0; j<N; j++)
for(int k= 0; k<N; k++)
for(int l= 0; l<N; l++)
C[voigt_mat[i][j]][voigt_mat[k][l]] = A[i][j] * B[k][l] ;
// C ij kl = A ij * B kl
return C ;
}
template <class T>
std::vector<std::vector<T>> dyadic_up(const std::vector<std::vector<T>>& A, const std::vector<std::vector<T>>& B)
{
/** it will retun C as A dyadic up B
* given dimensions of A and B are equal
*/
int N = A.size() ;
std::vector<std::vector<T>> C(N*N, std::vector<float>(N*N,0)) ; // N is the size of matrix A, i.e. which is calling the function
/** if size of A and B are not equal */
if(A.size() != B.size())
return C ;
/** generate a matrix of same size as A and B
* which will store the index of voigt's matrix for that index of matrix
*/
std::vector<std::vector<int>> voigt_mat = mat_voigt_ind(N) ;
/** Cijkl = Aik * Bjl */
for(int i= 0; i<N; i++)
for(int j= 0; j<N; j++)
for(int k= 0; k<N; k++)
for(int l= 0; l<N; l++)
C[voigt_mat[i][j]][voigt_mat[k][l]] = A[i][k] * B[j][l] ;
// C ij kl = A ik * B jl
return C ;
}
template <class T>
std::vector<std::vector<T>> dyadic_down(const std::vector<std::vector<T>>& A, const std::vector<std::vector<T>>& B)
{
/** it will retun C as A dyadic down B
* given dimensions of A and B are equal
*/
int N = A.size() ;
std::vector<std::vector<T>> C(N*N, std::vector<float>(N*N,0)) ; // N is the size of matrix A, i.e. which is calling the function
/** if size of A and B are not equal */
if(A.size() != B.size())
return C ;
/** generate a matrix of same size as A and B
* which will store the index of voigt's matrix for that index of matrix
*/
std::vector<std::vector<int>> voigt_mat = mat_voigt_ind(N) ;
/** Cijkl = Aik * Bjl */
for(int i= 0; i<N; i++)
for(int j= 0; j<N; j++)
for(int k= 0; k<N; k++)
for(int l= 0; l<N; l++)
C[voigt_mat[i][j]][voigt_mat[k][l]] = A[i][l] * B[j][k] ;
// C ij kl = A il * B jk
return C ;
}
template <class T>
void printMatrix(const std::vector<std::vector<T>>& C, int N = 3)
{
for(int i=0; i<C.size(); i++)
{
for(int j= 0; j<C[i].size(); j++)
{
std::cout<<std::setw(10) << std::fixed << std::setprecision(4)<<C[i][j] ;
if((j+1)%N == 0)
std::cout<<"\t" ;
}
if((i+1)%N == 0)
std::cout<<std::endl ;
std::cout<<std::endl ;
}
}
int main()
{
constexpr int N = 3 ;
std::vector<std::vector<float>> A(N, std::vector<float>(N,0)) ;
std::vector<std::vector<float>> B(N, std::vector<float>(N,0)) ;
/** Problem no 5.3
* considering alpha as 0
*/
float alp = M_PI/2 ;
// Rotation Matrix about V1
A = { {1 , 0 , 0}, {0 , cos(alp), sin(alp)}, {0, -sin(alp), cos(alp)}} ;
std::cout<<"\nTransformation Matrix for second order tensor for rotation about e1:"<<std::endl ;
printMatrix(dyadic_up(A, A)) ;
// Rotation Matrix about V2
B = { {cos(alp), 0, -sin(alp)}, {0 , 1, 0}, {sin(alp), 0, cos(alp)}} ;
std::cout<<"\nTransformation Matrix for second order tensor for rotation about e2:"<<std::endl ;
printMatrix(dyadic_up(B, B)) ;
/** for problem 5.4 */
A = { {5, 3, 0}, {2, 4, 6}, {0, 6, 2}} ;
B = { {4, 5, 2}, {0, 3, 4}, {0, 2, 5}} ;
std::cout<<"\nA dyadic B:"<<std::endl ;
printMatrix(dyadic(A, B)) ;
std::cout<<"\nA dyadic up B:"<<std::endl ;
printMatrix(dyadic_up(A, B)) ;
return 0 ;
}