Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F91072134
Stress.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Thu, Nov 7, 14:13
Size
24 KB
Mime Type
text/x-c
Expires
Sat, Nov 9, 14:13 (2 d)
Engine
blob
Format
Raw Data
Handle
22190665
Attached To
rLAMMPS lammps
Stress.cpp
View Options
#include "Stress.h"
#include "CauchyBorn.h"
#include "CBLattice.h"
#include "CbLjCut.h"
#include "CbLjSmoothLinear.h"
#include "CbEam.h"
#include "ATC_Error.h"
#include "LammpsInterface.h"
#include "VoigtOperations.h"
#include <iostream>
using
ATC_Utility
::
command_line
;
using
ATC_Utility
::
str2dbl
;
using
voigt3
::
voigt_idx1
;
using
voigt3
::
voigt_idx2
;
using
voigt3
::
to_voigt_unsymmetric
;
using
voigt3
::
from_voigt_unsymmetric
;
using
voigt3
::
to_voigt
;
using
voigt3
::
from_voigt
;
using
std
::
stringstream
;
using
std
::
vector
;
using
std
::
string
;
using
std
::
fstream
;
namespace
ATC
{
//=============================================================================
// extracts a stress at an integration point
// Note: Utility function: not in header
//=============================================================================
DENS_MAT
extract_stress
(
const
DENS_MAT_VEC
&
sigma
,
INDEX
ip
=
0
)
{
DENS_MAT
s
(
3
,
3
,
false
);
for
(
int
j
=
0
;
j
<
3
;
j
++
)
for
(
int
i
=
0
;
i
<
3
;
i
++
)
s
(
i
,
j
)
=
sigma
[
i
](
ip
,
j
);
return
s
;
}
//=============================================================================
// computes the pressure from the stress at the first quadrature point (in atm)
// Note: Utility function: not in header
//=============================================================================
double
compute_pressure
(
const
DENS_MAT_VEC
&
sigma
,
const
DENS_MAT
&
F
)
{
// pressure in units (mass-velocity^2)/Volume (LAMMPS real)
double
p
=
(
sigma
[
0
](
0
,
0
)
+
sigma
[
1
](
0
,
1
)
+
sigma
[
2
](
0
,
2
))
*
(
1.0
/
3.0
);
p
*=
1.0e14
/
6.0221415
;
// convert from units real to Pa
p
*=
1.0
/
101235.0
;
// convert from Pa to ATM
return
p
*
pow
(
det
(
F
),
-
1.0
/
3.0
);
// convert from PK2 to Cauchy stress
}
//=============================================================================
// extracts the deformation gradient at a quadrature point, q
// Note: Utility function: not in header
//=============================================================================
void
deformation_gradient
(
const
DENS_MAT_VEC
&
du
,
INDEX
q
,
MATRIX
&
F
)
{
F
.
reset
(
du
.
size
(),
du
.
size
(),
false
);
for
(
INDEX
j
=
0
;
j
<
F
.
nCols
();
j
++
)
{
for
(
INDEX
i
=
0
;
i
<
F
.
nRows
();
i
++
)
F
(
i
,
j
)
=
du
[
j
](
q
,
i
);
F
(
j
,
j
)
+=
1.0
;
}
}
//=============================================================================
// E = 1/2 stress*strain for linear elastic models
//=============================================================================
void
Stress
::
elastic_energy
(
const
FIELD_MATS
&
fields
,
const
GRAD_FIELD_MATS
&
gradFields
,
DENS_MAT
&
energy
)
const
{
int
nRows
=
(
((
gradFields
.
find
(
DISPLACEMENT
))
->
second
)[
0
]).
nRows
();
energy
.
reset
(
nRows
,
1
);
ATC
::
LammpsInterface
::
instance
()
->
print_msg
(
"WARNING: returning dummy elastic energy"
);
}
//=============================================================================
// isotropic linear elastic
//=============================================================================
StressLinearElastic
::
StressLinearElastic
(
fstream
&
fileId
)
:
StressCubicElastic
(),
E_
(
0
),
nu_
(
0
),
mu_
(
0
),
lambda_
(
0
)
{
if
(
!
fileId
.
is_open
())
throw
ATC_Error
(
"cannot open material file"
);
vector
<
string
>
line
;
while
(
fileId
.
good
())
{
command_line
(
fileId
,
line
);
if
(
line
[
0
]
==
"end"
)
{
mu_
=
E_
/
(
2.0
+
2.0
*
nu_
);
lambda_
=
mu_
*
nu_
/
(
0.5
-
nu_
);
StressCubicElastic
::
c11_
=
E_
*
(
1
-
nu_
)
/
(
1
+
nu_
)
/
(
1
-
2
*
nu_
);
StressCubicElastic
::
c12_
=
E_
*
nu_
/
(
1
+
nu_
)
/
(
1
-
2
*
nu_
);
StressCubicElastic
::
c44_
=
E_
/
(
1
+
nu_
)
/
2
;
if
(
nu_
<
0.0
||
nu_
>
1.0
)
throw
ATC_Error
(
"bad linear elastic constants"
);
if
(
lambda_
<
0.0
||
mu_
<
0.0
)
throw
ATC_Error
(
"bad continuum material parameter"
);
return
;
}
else
if
(
line
[
0
]
==
"modulus"
)
E_
=
str2dbl
(
line
[
1
]);
else
if
(
line
[
0
]
==
"possions_ratio"
)
nu_
=
str2dbl
(
line
[
1
]);
else
throw
ATC_Error
(
"unrecognized material function"
);
}
}
//=============================================================================
// compute the stress at N integration points from the displacement gradient
// T_{ij} = 1/2*C_{ijkl}* (u_{k,l} + u_{l,k})
//=============================================================================
void
StressLinearElastic
::
stress
(
const
FIELD_MATS
&
fields
,
const
GRAD_FIELD_MATS
&
gradFields
,
DENS_MAT_VEC
&
sigma
)
{
GRAD_FIELD_MATS
::
const_iterator
du_itr
=
gradFields
.
find
(
DISPLACEMENT
);
const
DENS_MAT_VEC
&
du
=
du_itr
->
second
;
CLON_VEC
uxx
(
du
[
0
],
CLONE_COL
,
0
);
CLON_VEC
uxy
(
du
[
1
],
CLONE_COL
,
0
);
CLON_VEC
uxz
(
du
[
2
],
CLONE_COL
,
0
);
CLON_VEC
uyx
(
du
[
0
],
CLONE_COL
,
1
);
CLON_VEC
uyy
(
du
[
1
],
CLONE_COL
,
1
);
CLON_VEC
uyz
(
du
[
2
],
CLONE_COL
,
1
);
CLON_VEC
uzx
(
du
[
0
],
CLONE_COL
,
2
);
CLON_VEC
uzy
(
du
[
1
],
CLONE_COL
,
2
);
CLON_VEC
uzz
(
du
[
2
],
CLONE_COL
,
2
);
const
INDEX
N
=
uxx
.
size
();
// # of integration pts
sigma
.
assign
(
3
,
DENS_MAT
(
N
,
3
));
// precompute the pressure and copy to the diagonal
column
(
sigma
[
0
],
0
)
=
(
uxx
+
uyy
+
uzz
)
*
(
-
lambda_
);
column
(
sigma
[
1
],
1
)
=
column
(
sigma
[
0
],
0
);
column
(
sigma
[
2
],
2
)
=
column
(
sigma
[
0
],
0
);
column
(
sigma
[
0
],
0
)
-=
2.0
*
mu_
*
uxx
;
column
(
sigma
[
0
],
1
)
=
(
uxy
+
uyx
)
*
(
-
mu_
);
column
(
sigma
[
0
],
2
)
=
(
uxz
+
uzx
)
*
(
-
mu_
);
column
(
sigma
[
1
],
0
)
=
column
(
sigma
[
0
],
1
);
column
(
sigma
[
1
],
1
)
-=
2.0
*
mu_
*
uyy
;
column
(
sigma
[
1
],
2
)
=
(
uyz
+
uzy
)
*
(
-
mu_
);
column
(
sigma
[
2
],
0
)
=
column
(
sigma
[
0
],
2
);
column
(
sigma
[
2
],
1
)
=
column
(
sigma
[
1
],
2
);
column
(
sigma
[
2
],
2
)
-=
2.0
*
mu_
*
uzz
;
}
//=============================================================================
// cubic elastic
//=============================================================================
StressCubicElastic
::
StressCubicElastic
(
fstream
&
fileId
)
:
c11_
(
0
),
c12_
(
0
),
c44_
(
0
)
{
if
(
!
fileId
.
is_open
())
throw
ATC_Error
(
"cannot open material file"
);
vector
<
string
>
line
;
while
(
fileId
.
good
())
{
command_line
(
fileId
,
line
);
if
(
line
[
0
]
==
"end"
)
return
;
else
if
(
line
[
0
]
==
"c11"
)
c11_
=
str2dbl
(
line
[
1
]);
else
if
(
line
[
0
]
==
"c12"
)
c12_
=
str2dbl
(
line
[
1
]);
else
if
(
line
[
0
]
==
"c44"
)
c44_
=
str2dbl
(
line
[
1
]);
else
throw
ATC_Error
(
"unrecognized material function"
);
}
}
//---------------------------------------------------------------------------
// compute the stress at N integration points from the displacement gradient
// T_{ij} = 1/2*C_{ijkl}*(u_{k,l} + u_{l,k})
//---------------------------------------------------------------------------
void
StressCubicElastic
::
stress
(
const
FIELD_MATS
&
fields
,
const
GRAD_FIELD_MATS
&
gradFields
,
DENS_MAT_VEC
&
sigma
)
{
GRAD_FIELD_MATS
::
const_iterator
du_itr
=
gradFields
.
find
(
DISPLACEMENT
);
const
DENS_MAT_VEC
&
du
=
du_itr
->
second
;
CLON_VEC
uxx
(
du
[
0
],
CLONE_COL
,
0
);
CLON_VEC
uxy
(
du
[
1
],
CLONE_COL
,
0
);
CLON_VEC
uxz
(
du
[
2
],
CLONE_COL
,
0
);
CLON_VEC
uyx
(
du
[
0
],
CLONE_COL
,
1
);
CLON_VEC
uyy
(
du
[
1
],
CLONE_COL
,
1
);
CLON_VEC
uyz
(
du
[
2
],
CLONE_COL
,
1
);
CLON_VEC
uzx
(
du
[
0
],
CLONE_COL
,
2
);
CLON_VEC
uzy
(
du
[
1
],
CLONE_COL
,
2
);
CLON_VEC
uzz
(
du
[
2
],
CLONE_COL
,
2
);
const
INDEX
N
=
uxx
.
size
();
// # of integration pts
sigma
.
assign
(
3
,
DENS_MAT
(
N
,
3
));
const
double
c12
=
c12_
;
const
double
c11
=
c11_
;
const
double
c44
=
c44_
;
// scaling: stress must return (-) stress
column
(
sigma
[
0
],
0
)
=
-
c11
*
uxx
-
c12
*
(
uyy
+
uzz
);
column
(
sigma
[
1
],
1
)
=
-
c11
*
uyy
-
c12
*
(
uxx
+
uzz
);
column
(
sigma
[
2
],
2
)
=
-
c11
*
uzz
-
c12
*
(
uxx
+
uyy
);
column
(
sigma
[
0
],
1
)
=
-
c44
*
(
uxy
+
uyx
);
column
(
sigma
[
1
],
0
)
=
column
(
sigma
[
0
],
1
);
column
(
sigma
[
0
],
2
)
=
-
c44
*
(
uxz
+
uzx
);
column
(
sigma
[
2
],
0
)
=
column
(
sigma
[
0
],
2
);
column
(
sigma
[
1
],
2
)
=
-
c44
*
(
uyz
+
uzy
);
column
(
sigma
[
2
],
1
)
=
column
(
sigma
[
1
],
2
);
}
//---------------------------------------------------------------------------
// compute the elastic energy at N integration points from displacement gradient
// E = 1/8*C_{ijkl}* (u_{k,l} + u_{l,k})* (u_{i,j} + u_{j,i})*rho ?
// = 1/2 (4 c44 (u12^2 + u13^2 + u23^2) + 2 c12 (u11 u22 + u11 u33 + u22 u33)
// + c11 (u11^2 + u22^2 + u33^2))
//---------------------------------------------------------------------------
void
StressCubicElastic
::
elastic_energy
(
const
FIELD_MATS
&
fields
,
const
GRAD_FIELD_MATS
&
gradFields
,
DENS_MAT
&
energy
)
const
{
GRAD_FIELD_MATS
::
const_iterator
du_itr
=
gradFields
.
find
(
DISPLACEMENT
);
const
DENS_MAT_VEC
&
du
=
du_itr
->
second
;
CLON_VEC
uxx
(
du
[
0
],
CLONE_COL
,
0
);
CLON_VEC
uxy
(
du
[
1
],
CLONE_COL
,
0
);
CLON_VEC
uxz
(
du
[
2
],
CLONE_COL
,
0
);
CLON_VEC
uyx
(
du
[
0
],
CLONE_COL
,
1
);
CLON_VEC
uyy
(
du
[
1
],
CLONE_COL
,
1
);
CLON_VEC
uyz
(
du
[
2
],
CLONE_COL
,
1
);
CLON_VEC
uzx
(
du
[
0
],
CLONE_COL
,
2
);
CLON_VEC
uzy
(
du
[
1
],
CLONE_COL
,
2
);
CLON_VEC
uzz
(
du
[
2
],
CLONE_COL
,
2
);
CLON_VEC
E
(
energy
,
CLONE_COL
,
0
);
const
double
c12
=
c12_
;
const
double
c11
=
c11_
;
const
double
c44
=
c44_
;
//double scale = (ATC::LammpsInterface::instance()->mvv2e());
for
(
INDEX
gp
=
0
;
gp
<
du
.
front
().
nRows
();
gp
++
)
{
double
u11
=
uxx
(
gp
);
double
u22
=
uyy
(
gp
);
double
u33
=
uzz
(
gp
);
double
u12
=
0.5
*
(
uxy
(
gp
)
+
uyx
(
gp
));
double
u13
=
0.5
*
(
uxz
(
gp
)
+
uzx
(
gp
));
double
u23
=
0.5
*
(
uyz
(
gp
)
+
uzy
(
gp
));
double
EE
=
0.5
*
(
4.0
*
c44
*
(
u12
*
u12
+
u13
*
u13
+
u23
*
u23
)
+
2.0
*
c12
*
(
u11
*
u22
+
u11
*
u33
+
u22
*
u33
)
+
c11
*
(
u11
*
u11
+
u22
*
u22
+
u33
*
u33
));
E
(
gp
)
=
EE
;
}
}
void
StressCubicElastic
::
set_tangent
(
void
)
{
C_
.
reset
(
6
,
6
);
C_
(
0
,
0
)
=
C_
(
1
,
1
)
=
C_
(
2
,
2
)
=
c11_
;
C_
(
0
,
1
)
=
C_
(
1
,
0
)
=
C_
(
1
,
2
)
=
C_
(
2
,
1
)
=
C_
(
0
,
2
)
=
C_
(
2
,
0
)
=
c12_
;
C_
(
3
,
3
)
=
C_
(
4
,
4
)
=
C_
(
5
,
5
)
=
c44_
;
}
//=============================================================================
// damped cubic elastic
//=============================================================================
StressCubicElasticDamped
::
StressCubicElasticDamped
(
fstream
&
fileId
)
:
StressCubicElastic
(),
gamma_
(
0
)
{
if
(
!
fileId
.
is_open
())
throw
ATC_Error
(
"cannot open material file"
);
vector
<
string
>
line
;
while
(
fileId
.
good
())
{
command_line
(
fileId
,
line
);
if
(
line
[
0
]
==
"end"
)
return
;
else
if
(
line
[
0
]
==
"c11"
)
StressCubicElastic
::
c11_
=
str2dbl
(
line
[
1
]);
else
if
(
line
[
0
]
==
"c12"
)
StressCubicElastic
::
c12_
=
str2dbl
(
line
[
1
]);
else
if
(
line
[
0
]
==
"c44"
)
StressCubicElastic
::
c44_
=
str2dbl
(
line
[
1
]);
else
if
(
line
[
0
]
==
"gamma"
)
gamma_
=
str2dbl
(
line
[
1
]);
else
throw
ATC_Error
(
"unrecognized material function"
);
}
}
//---------------------------------------------------------------------------
// compute the stress at N integration points
//---------------------------------------------------------------------------
void
StressCubicElasticDamped
::
stress
(
const
FIELD_MATS
&
fields
,
const
GRAD_FIELD_MATS
&
gradFields
,
DENS_MAT_VEC
&
sigma
)
{
StressCubicElastic
::
stress
(
fields
,
gradFields
,
sigma
);
GRAD_FIELD_MATS
::
const_iterator
dv_itr
=
gradFields
.
find
(
VELOCITY
);
const
DENS_MAT_VEC
&
dv
=
dv_itr
->
second
;
CLON_VEC
vxx
(
dv
[
0
],
CLONE_COL
,
0
);
CLON_VEC
vxy
(
dv
[
1
],
CLONE_COL
,
0
);
CLON_VEC
vxz
(
dv
[
2
],
CLONE_COL
,
0
);
CLON_VEC
vyx
(
dv
[
0
],
CLONE_COL
,
1
);
CLON_VEC
vyy
(
dv
[
1
],
CLONE_COL
,
1
);
CLON_VEC
vyz
(
dv
[
2
],
CLONE_COL
,
1
);
CLON_VEC
vzx
(
dv
[
0
],
CLONE_COL
,
2
);
CLON_VEC
vzy
(
dv
[
1
],
CLONE_COL
,
2
);
CLON_VEC
vzz
(
dv
[
2
],
CLONE_COL
,
2
);
// scaling: stress must return (-) stress
column
(
sigma
[
0
],
0
)
+=
-
gamma_
*
vxx
;
column
(
sigma
[
1
],
1
)
+=
-
gamma_
*
vyy
;
column
(
sigma
[
2
],
2
)
+=
-
gamma_
*
vzz
;
column
(
sigma
[
0
],
1
)
+=
-
0.5
*
gamma_
*
(
vxy
+
vyx
);
column
(
sigma
[
1
],
0
)
+=
column
(
sigma
[
0
],
1
);
column
(
sigma
[
0
],
2
)
+=
-
0.5
*
gamma_
*
(
vxz
+
vzx
);
column
(
sigma
[
2
],
0
)
+=
column
(
sigma
[
0
],
2
);
column
(
sigma
[
1
],
2
)
+=
-
0.5
*
gamma_
*
(
vyz
+
vzy
);
column
(
sigma
[
2
],
1
)
+=
column
(
sigma
[
1
],
2
);
}
//==============================================================================
// cauchy born model
//==============================================================================
StressCauchyBorn
::
StressCauchyBorn
(
fstream
&
fileId
,
CbData
&
cb
)
:
cblattice_
(
NULL
),
potential_
(
NULL
),
makeLinear_
(
false
),
cubicMat_
(
NULL
),
initialized_
(
false
),
fixed_temperature_
(
0.
),
cbdata_
(
cb
)
{
if
(
!
fileId
.
is_open
())
throw
ATC_Error
(
"cannot open material file"
);
while
(
fileId
.
good
())
{
// reads a line from the material file
vector
<
string
>
line
;
command_line
(
fileId
,
line
);
if
(
line
.
empty
())
continue
;
// skip blank lines
else
if
(
line
[
0
]
==
"end"
)
{
delete
cblattice_
;
if
(
!
potential_
)
throw
ATC_Error
(
"no potential defined"
);
cblattice_
=
new
CBLattice
(
cbdata_
.
cell_vectors
,
cbdata_
.
basis_vectors
);
return
;
}
else
if
(
line
[
0
]
==
"pair_style"
)
{
if
(
line
[
1
]
==
"lj/cut"
)
{
// Lennard-Jones w/ cutoff radius
if
(
line
.
size
()
<
3
)
throw
(
ATC_Error
(
"no lj/cut cutoff radius"
));
const
double
rc
=
str2dbl
(
line
[
2
]);
while
(
!
fileId
.
eof
())
{
// find next pair_coeff command
command_line
(
fileId
,
line
);
if
(
line
.
size
()
&&
line
[
0
]
==
"pair_coeff"
)
break
;
}
if
(
line
[
0
]
!=
"pair_coeff"
||
line
.
size
()
!=
3
)
{
throw
(
ATC_Error
(
"lj/cut needs 2 coefficents"
));
}
delete
potential_
;
potential_
=
new
CbLjCut
(
str2dbl
(
line
[
1
]),
str2dbl
(
line
[
2
]),
rc
);
}
else
if
(
line
[
1
]
==
"lj/smooth/linear"
)
{
// Lennard-Jones w/ cutoff radius and smoothed
if
(
line
.
size
()
<
3
)
throw
(
ATC_Error
(
"no lj/smooth/linear cutoff radius"
));
const
double
rc
=
str2dbl
(
line
[
2
]);
while
(
!
fileId
.
eof
())
{
// find next pair_coeff command
command_line
(
fileId
,
line
);
if
(
line
.
size
()
&&
line
[
0
]
==
"pair_coeff"
)
break
;
}
if
(
line
[
0
]
!=
"pair_coeff"
||
line
.
size
()
!=
3
)
{
throw
(
ATC_Error
(
"lj/smooth/linear needs 2 coefficents"
));
}
delete
potential_
;
potential_
=
new
CbLjSmoothLinear
(
str2dbl
(
line
[
1
]),
str2dbl
(
line
[
2
]),
rc
);
}
else
if
(
line
[
1
]
==
"eam"
)
{
// Embedded atom method potential
delete
potential_
;
potential_
=
new
CbEam
();
}
else
throw
(
ATC_Error
(
"Invalid pair style"
));
}
else
if
(
line
[
0
]
==
"linear"
)
makeLinear_
=
true
;
else
if
(
line
[
0
]
==
"temperature"
&&
line
.
size
()
==
2
)
{
fixed_temperature_
=
str2dbl
(
line
[
1
]);
}
else
if
(
line
[
0
]
==
"material"
||
line
[
0
]
==
"stress"
)
/* ignore this */
;
else
throw
ATC_Error
(
"Unrecognized Cauchy-Born parameter: "
+
line
[
0
]
+
"."
);
}
}
//==============================================================================
//* default destructor - delete potential and lattice
//==============================================================================
StressCauchyBorn
::~
StressCauchyBorn
()
{
if
(
potential_
)
delete
potential_
;
if
(
cblattice_
)
delete
cblattice_
;
if
(
cubicMat_
)
delete
cubicMat_
;
}
//==============================================================================
// initialize
//==============================================================================
void
StressCauchyBorn
::
initialize
(
void
)
{
if
(
!
initialized_
)
{
if
(
makeLinear_
)
linearize
();
stringstream
ss
;
double
k
=
stiffness
()
*
cbdata_
.
e2mvv
;
double
m
=
cbdata_
.
atom_mass
;
double
w0
=
sqrt
(
k
*
m
);
ss
<<
"CB stiffness: "
<<
stiffness
()
<<
" Einstein freq: "
<<
w0
;
ATC
::
LammpsInterface
::
instance
()
->
print_msg_once
(
ss
.
str
());
initialized_
=
true
;
}
}
//==============================================================================
// compute the bond stiffness consistent with the einstein freq
//==============================================================================
double
StressCauchyBorn
::
stiffness
(
void
)
const
{
AtomCluster
vac
;
cblattice_
->
atom_cluster
(
eye
<
double
>
(
3
,
3
),
potential_
->
cutoff_radius
(),
vac
);
DENS_MAT
k
=
vac
.
force_constants
(
0
,
potential_
);
return
k
(
0
,
0
);
}
//==============================================================================
// compute the stress at N integration points from the displacement gradient
//==============================================================================
void
StressCauchyBorn
::
stress
(
const
FIELD_MATS
&
fields
,
const
GRAD_FIELD_MATS
&
gradFields
,
DENS_MAT_VEC
&
sigma
)
{
if
(
cubicMat_
)
{
cubicMat_
->
stress
(
fields
,
gradFields
,
sigma
);
return
;
}
FIELD_MATS
::
const_iterator
temp
=
fields
.
find
(
TEMPERATURE
);
GRAD_FIELD_MATS
::
const_iterator
disp_gradient
=
gradFields
.
find
(
DISPLACEMENT
);
// Scaling factor - scale by atomic volume and energy conversion.
// negative because stress must return (-) stress
const
double
fact
=
-
cbdata_
.
inv_atom_volume
*
cbdata_
.
e2mvv
;
const
DENS_MAT_VEC
&
du
(
disp_gradient
->
second
);
const
INDEX
num_integration_pts
=
du
.
front
().
nRows
();
const
INDEX
nsd
=
du
.
size
();
DENS_MAT
F
(
nsd
,
nsd
);
// displacement gradient
bool
temp_varies
=
(
temp
!=
fields
.
end
());
sigma
.
assign
(
nsd
,
DENS_MAT
(
num_integration_pts
,
nsd
));
StressAtIP
S
(
sigma
);
// wrapper for quadrature points.
AtomCluster
vac
;
for
(
INDEX
gp
=
0
;
gp
<
num_integration_pts
;
gp
++
)
{
// Sets the quadrature point to be computed.
S
.
set_quadrature_point
(
gp
);
// Get displacement gradient and construct a virtual atom cluster.
deformation_gradient
(
du
,
gp
,
F
);
// Generates the atom cluster, given the deformation gradient.
cblattice_
->
atom_cluster
(
F
,
potential_
->
cutoff_radius
(),
vac
);
// Get temperature (assume 0K if no temperature field is present).
const
double
T
=
(
temp_varies
?
temp
->
second
[
gp
]
:
fixed_temperature_
);
// Computes the cauchy-born stresses.
const
StressArgs
args
(
vac
,
potential_
,
cbdata_
.
boltzmann
,
cbdata_
.
hbar
,
T
);
cb_stress
(
args
,
S
);
// copy symmetric part of stress and scale by V0
for
(
INDEX
i
=
0
;
i
<
nsd
;
i
++
)
{
S
(
i
,
i
)
*=
fact
;
for
(
INDEX
j
=
i
+
1
;
j
<
nsd
;
j
++
)
S
(
j
,
i
)
=
(
S
(
i
,
j
)
*=
fact
);
}
}
}
//==============================================================================
// Computes free (T>0)/potential(T=0) energy density. [mvv/L^3]
//==============================================================================
void
StressCauchyBorn
::
elastic_energy
(
const
FIELD_MATS
&
fields
,
const
GRAD_FIELD_MATS
&
gradFields
,
DENS_MAT
&
energy
)
const
{
if
(
cubicMat_
)
{
cubicMat_
->
elastic_energy
(
fields
,
gradFields
,
energy
);
return
;
}
FIELD_MATS
::
const_iterator
temp
=
fields
.
find
(
TEMPERATURE
);
GRAD_FIELD_MATS
::
const_iterator
disp_gradient
=
gradFields
.
find
(
DISPLACEMENT
);
const
DENS_MAT_VEC
&
du
(
disp_gradient
->
second
);
DENS_MAT
F
(
du
.
size
(),
du
.
size
());
AtomCluster
vac
;
for
(
INDEX
gp
=
0
;
gp
<
du
.
front
().
nRows
();
gp
++
)
{
deformation_gradient
(
du
,
gp
,
F
);
cblattice_
->
atom_cluster
(
F
,
potential_
->
cutoff_radius
(),
vac
);
double
T
=
(
temp
!=
fields
.
end
()
?
temp
->
second
[
gp
]
:
fixed_temperature_
);
energy
[
gp
]
=
cb_energy
(
StressArgs
(
vac
,
potential_
,
cbdata_
.
boltzmann
,
cbdata_
.
hbar
,
T
));
}
// Scaling factor - scale by atomic volume and energy conversion.
energy
*=
cbdata_
.
inv_atom_volume
*
cbdata_
.
e2mvv
;
}
//==============================================================================
// Computes entropic energy density. [mvv/L^3]
//==============================================================================
void
StressCauchyBorn
::
entropic_energy
(
const
FIELD_MATS
&
fields
,
const
GRAD_FIELD_MATS
&
gradFields
,
DENS_MAT
&
energy
)
const
{
FIELD_MATS
::
const_iterator
temp
=
fields
.
find
(
TEMPERATURE
);
GRAD_FIELD_MATS
::
const_iterator
disp_gradient
=
gradFields
.
find
(
DISPLACEMENT
);
const
DENS_MAT_VEC
&
du
(
disp_gradient
->
second
);
DENS_MAT
F
(
du
.
size
(),
du
.
size
());
AtomCluster
vac
;
for
(
INDEX
gp
=
0
;
gp
<
du
.
front
().
nRows
();
gp
++
)
{
deformation_gradient
(
du
,
gp
,
F
);
cblattice_
->
atom_cluster
(
F
,
potential_
->
cutoff_radius
(),
vac
);
double
T
=
(
temp
!=
fields
.
end
()
?
temp
->
second
[
gp
]
:
fixed_temperature_
);
energy
[
gp
]
=
cb_entropic_energy
(
StressArgs
(
vac
,
potential_
,
cbdata_
.
boltzmann
,
cbdata_
.
hbar
,
T
));
}
// Scaling factor - scale by atomic volume and energy conversion.
energy
*=
cbdata_
.
inv_atom_volume
*
cbdata_
.
e2mvv
;
}
//==============================================================================
// creates a linearization for a deformation gradient
//==============================================================================
void
StressCauchyBorn
::
linearize
(
MATRIX
*
F
)
{
if
(
cubicMat_
)
delete
cubicMat_
;
DENS_MAT
C
;
if
(
F
)
tangent
(
*
F
,
C
);
else
tangent
(
eye
<
double
>
(
3
,
3
),
C
);
cubicMat_
=
new
StressCubicElastic
(
C
(
0
,
0
),
C
(
0
,
1
),
C
(
3
,
3
));
stringstream
ss
;
double
c11
=
C
(
0
,
0
)
/
cbdata_
.
e2mvv
;
double
c12
=
C
(
0
,
1
)
/
cbdata_
.
e2mvv
;
double
c44
=
C
(
3
,
3
)
/
cbdata_
.
e2mvv
;
ss
<<
"created cubic stress function:"
<<
"
\n
lammps ATC units"
<<
"
\n
c11="
<<
c11
<<
" "
<<
C
(
0
,
0
)
<<
"
\n
c12="
<<
c12
<<
" "
<<
C
(
0
,
1
)
<<
"
\n
c44="
<<
c44
<<
" "
<<
C
(
3
,
3
);
ATC
::
LammpsInterface
::
instance
()
->
print_msg_once
(
ss
.
str
());
}
//==============================================================================
// sets C as the material tangent modulus, given deformation gradient F
//==============================================================================
// Note: C is dS/dC which is 1/2 dS/dF_sym
void
StressCauchyBorn
::
tangent
(
const
MATRIX
&
F
,
MATRIX
&
C
)
const
{
if
(
cubicMat_
)
{
cubicMat_
->
tangent
(
F
,
C
);
return
;
}
elasticity_tensor
(
F
,
C
);
}
//==============================================================================
// 1st elasticity tensor : B = dP/dF = C F F + S I ( 9 x 9 in Voigt notation)
// 2nd elasticity tensor : C = dS/dE ( 6 x 6 in Voigt notation)
//==============================================================================
DENS_VEC
StressCauchyBorn
::
elasticity_tensor
(
const
VECTOR
&
Fv
,
MATRIX
&
C
,
const
ElasticityTensorType
type
)
const
{
DENS_MAT
F
;
if
(
Fv
.
nRows
()
==
9
)
{
F
=
from_voigt_unsymmetric
(
Fv
);
}
else
{
F
=
from_voigt
(
Fv
);
}
return
elasticity_tensor
(
F
,
C
,
type
);
}
DENS_VEC
StressCauchyBorn
::
elasticity_tensor
(
const
MATRIX
&
F
,
MATRIX
&
C
,
const
ElasticityTensorType
type
)
const
{
double
T
=
0
;
AtomCluster
vac
;
cblattice_
->
atom_cluster
(
F
,
potential_
->
cutoff_radius
(),
vac
);
if
(
vac
.
size
()
<
4
)
throw
ATC_Error
(
"StressCauchyBorn::second_elasticity_tensor cluster does not have sufficient atoms"
);
const
StressArgs
args
(
vac
,
potential_
,
cbdata_
.
boltzmann
,
cbdata_
.
hbar
,
T
);
// if using EAM potential, calculate embedding function and derivatives
bool
hasEAM
=
potential_
->
terms
.
embedding
;
double
embed_p
=
0
;
double
embed_pp
=
0
;
if
(
hasEAM
)
{
double
e_density
=
cb_electron_density
(
args
);
embed_p
=
potential_
->
F_p
(
e_density
);
// "F" in usual EAM symbology
embed_pp
=
potential_
->
F_pp
(
e_density
);
}
int
size
=
6
;
if
(
type
==
FIRST_ELASTICITY_TENSOR
)
{
size
=
9
;
}
DENS_VEC
Z
(
size
),
S
(
size
),
Zfp
(
size
);
Zfp
=
0
;
C
.
reset
(
size
,
size
);
for
(
INDEX
a
=
0
;
a
<
vac
.
size
();
a
++
)
{
const
DENS_VEC
&
Ra
=
vac
.
R
(
a
);
if
(
type
==
FIRST_ELASTICITY_TENSOR
)
{
DENS_VEC
ra
=
F
*
Ra
;
for
(
INDEX
i
=
0
;
i
<
size
;
i
++
)
{
Z
(
i
)
=
ra
(
voigt_idx1
[
i
])
*
Ra
(
voigt_idx2
[
i
]);
}
}
else
{
for
(
INDEX
i
=
0
;
i
<
size
;
i
++
)
{
Z
(
i
)
=
Ra
(
voigt_idx1
[
i
])
*
Ra
(
voigt_idx2
[
i
]);
}
}
double
d
=
vac
.
bond_length
(
a
);
double
rinv
=
1.0
/
d
;
double
phi_r
=
potential_
->
phi_r
(
d
);
// computes phi'
double
phi_rr
=
potential_
->
phi_rr
(
d
);
// computes phi''
double
fact1
=
0.5
*
phi_r
*
rinv
;
// 1/2 see Philips
double
fact2
=
0.5
*
(
phi_rr
-
phi_r
*
rinv
)
*
rinv
*
rinv
;
if
(
hasEAM
)
{
double
rho_r
=
potential_
->
rho_r
(
d
);
// computes rho'
double
rho_rr
=
potential_
->
rho_rr
(
d
);
// computes rho''
fact1
+=
embed_p
*
rho_r
*
rinv
;
fact2
+=
embed_p
*
(
rho_rr
-
rho_r
*
rinv
)
*
rinv
*
rinv
;
Zfp
+=
Z
*
(
rho_r
*
rinv
);
}
for
(
INDEX
i
=
0
;
i
<
size
;
i
++
)
{
S
(
i
)
+=
fact1
*
Z
(
i
);
for
(
INDEX
j
=
0
;
j
<
size
;
j
++
)
{
C
(
i
,
j
)
+=
fact2
*
Z
(
i
)
*
Z
(
j
);
}
}
if
(
type
==
FIRST_ELASTICITY_TENSOR
)
{
for
(
INDEX
i
=
0
;
i
<
9
;
i
++
)
{
for
(
INDEX
j
=
0
;
j
<
9
;
j
++
)
{
if
(
voigt_idx1
[
i
]
==
voigt_idx1
[
j
]
)
{
// \delta_ik S_JL
C
(
i
,
j
)
+=
fact1
*
Ra
(
voigt_idx2
[
i
])
*
Ra
(
voigt_idx2
[
j
]);
}
}
}
}
}
if
(
hasEAM
)
{
for
(
INDEX
i
=
0
;
i
<
6
;
i
++
)
{
for
(
INDEX
j
=
0
;
j
<
6
;
j
++
)
{
C
(
i
,
j
)
+=
embed_pp
*
Zfp
(
i
)
*
Zfp
(
j
);
}
}
}
double
s
=
cbdata_
.
inv_atom_volume
*
cbdata_
.
e2mvv
;
S
*=
s
;
C
*=
s
;
return
S
;
}
}
// end atc namespace
Event Timeline
Log In to Comment