/trunk/SIFEL/GEFEL/Makefile |
---|
46,7 → 46,7 |
SRCS += dskyline.cpp eigsol.cpp elemmat.cpp elemnode.cpp elemtools.cpp endnode.cpp |
SRCS += floatsub.cpp fllopsif.cpp fuzzygen.cpp fuzzynum.cpp gadaptivity.cpp gedge.cpp gelement.cpp gfunct.cpp gmatrix.cpp gfmatrix.cpp |
SRCS += gnode.cpp gphase.cpp gsurf.cpp gtopology.cpp hdbcontr.cpp import_T3d.cpp intools.cpp intp.cpp |
SRCS += iotools.cpp ipmap.cpp itablefunct.cpp kwdset.cpp lgnode.cpp libtrace.cpp list.cpp mathem.cpp matrix.cpp nodmap.cpp obj_funct.cpp |
SRCS += iotools.cpp ipmap.cpp itablefunct.cpp kwdset.cpp lcoordsys.cpp lgnode.cpp libtrace.cpp list.cpp mathem.cpp matrix.cpp nodmap.cpp obj_funct.cpp |
SRCS += obj_funct_gefel.cpp ordering.cpp precond.cpp saddpoint.cpp scc.cpp scr.cpp selection.cpp seqfeti.cpp seqschur.cpp |
SRCS += seqselnodes.cpp seqtop.cpp siftop.cpp skyline.cpp slesolv.cpp fllopsif.cpp stacktrace.cpp tablefunct.cpp |
SRCS += tensor.cpp timecontr.cpp vector.cpp xfile.cpp |
143,7 → 143,6 |
@(echo " gefel BIN was successfully cleaned") |
#################################################################### |
# List of targets with dependent modules |
# |
/trunk/SIFEL/GEFEL/galias.h |
---|
130,12 → 130,12 |
// aliases for different types of selection |
enum seltype {sel_no=0, sel_all=1, sel_range=2, sel_list=3, sel_period=4, |
sel_realrange=5, sel_reallist=6, sel_mtx=7, sel_range_mtx=8, sel_range_vec=9, |
sel_realperiod=10, sel_impvalues=11, sel_vec=12, sel_prop=13, sel_impvallst=14, sel_sarray=15}; |
sel_realperiod=10, sel_impvalues=11, sel_vec=12, sel_prop=13, sel_impvallst=14, sel_sarray=15, sel_single=16}; |
const enumstr seltypestr[] = {{"sel_no",0}, {"sel_all",1}, {"sel_range",2}, {"sel_list",3}, |
{"sel_period",4}, {"sel_realrange",5}, {"sel_reallist",6}, |
{"sel_mtx",7}, {"sel_rangem",8}, {"sel_rangev",9}, |
{"sel_realperiod",10}, {"sel_impvalues",11}, {"sel_vec",12}, |
{"sel_prop",13}, {"sel_impvallst",14}, {"sel_sarray",15}}; |
{"sel_prop",13}, {"sel_impvallst",14}, {"sel_sarray",15}, {"sel_single", 16}}; |
const kwdset seltype_kwdset(sizeof(seltypestr)/sizeof(*seltypestr), seltypestr); |
251,11 → 251,28 |
// aliases for quantity character |
enum quantchar {undefq=0, scalq=1, vectq=2, tensq=3}; |
const enumstr quantcharstr[] = {{"undefq", 0}, {"scalq", 1}, {"vectq", 2}, {"tensq", 3}}; |
const kwdset quantchar_kwdset(sizeof(quantcharstr)/sizeof(*quantcharstr), quantcharstr); |
#endif |
// aliases for quantity mathematical representation |
enum quantrep {undefq=0, scalq=1, vectq=2, tensq=3}; |
const enumstr quantrepstr[] = {{"undefq", 0}, {"scalq", 1}, {"vectq", 2}, {"tensq", 3}}; |
const kwdset quantrep_kwdset(sizeof(quantrepstr)/sizeof(*quantrepstr), quantrepstr); |
// aliases for the second order tensor storage notation |
enum tensqnot {undeftn=0, voigtred=1, voigtfull=2, fullmtx=3}; |
const enumstr tensqnotstr[] {{"undeftn",0}, {"voigtred",1}, {"voigtfull",2}, {"fullmtx",3}}; |
const kwdset tensqnot_kwdset(sizeof(tensqnotstr)/sizeof(*tensqnotstr), tensqnotstr); |
// aliases for the definition of local coordinate systems |
enum tmat_type {no_tr=0, gen_tr=1, cyl_tr=2, gfgen_tr=3}; |
const enumstr tmat_typestr[] {{"no_tr",0}, {"gen_tr",1}, {"cyl_tr",2}, {"gfgen_tr",3}}; |
const kwdset tmat_type_kwdset(sizeof(tmat_typestr)/sizeof(*tmat_typestr), tmat_typestr); |
// aliases for format of graphics output |
enum resfilefmt {resfmt_no=0, resfmt_open_dx=1, resfmt_femcad=2, resfmt_gid=3, resfmt_vtk=4, |
resfmt_plain_out=5, resfmt_diag_dat=6}; |
const enumstr resfilefmtstr[] = {{"resfmt_no",0}, {"resfmt_open_dx",1}, {"resfmt_femcad",2}, |
{"resfmt_gid",3}, {"resfmt_vtk",4}, {"resfmt_plain_out",5}, |
{"resfmt_diag_dat",6}}; |
const kwdset resfilefmt_kwdset(sizeof(resfilefmtstr)/sizeof(*resfilefmtstr), resfilefmtstr); |
#endif |
/trunk/SIFEL/GEFEL/gmatrix.h |
---|
1,7 → 1,7 |
#ifndef GMATRIX_H |
#define GMATRIX_H |
#include "LAPACK/spmatrix.h" |
//#include "LAPACK/spmatrix.h" |
#include "SPARSE/DSSolver.h" |
#include "galias.h" |
143,7 → 143,7 |
compcol *cc; |
symcompcol *scc; |
elemmat *em; |
MatrixPtr Matrix; |
//MatrixPtr Matrix; |
ISolver *sdirect; |
//spasol *iss; |
/trunk/SIFEL/GEFEL/iotools.cpp |
---|
3897,6 → 3897,66 |
/** |
Function decomposes name of file(with path) to path, filename and extension. |
r:/ppp/ppp/fff.fff.sss -> path = "r:/ppp/ppp" , name = "fff.fff" , ext = ".sss" |
@param[in] fnstr - pointer to the string of decomposed file name |
@param[out] path - pointer into the fnstr to the path beginning or NULL if no path is given |
@param[out] name - pointer into the fnstr to the file name beginning |
@param[out] suffix - pointer into the fnstr to the file extension beginning or NULL if no extension is given |
@return The function returns pointers to decomposed parts in the parameters |
path, name and ext, no memory is allocated for these pointers. |
Created by Tomas Koudelka, 10.2023 |
*/ |
void filename_decomp_ptr (const char *fnstr, const char *&path, const char *&name, const char *&ext) |
{ |
path = strrchr(fnstr,'/'); |
if (path == NULL) |
path = strrchr(fnstr,'\\'); |
if (path) |
name = path + 1; |
else |
name = fnstr; |
ext = strrchr(name, '.'); |
} |
/** |
Function decomposes name of file(with path) to path, filename and extension. |
r:/ppp/ppp/fff.fff.sss -> path = "r:/ppp/ppp" , name = "fff.fff" , ext = ".sss" |
@param[in] fnstr - pointer to the string of decomposed file name |
@param[out] path - pointer into the fnstr to the path beginning or NULL if no path is given |
@param[out] name - pointer into the fnstr to the file name beginning |
@param[out] suffix - pointer into the fnstr to the file extension beginning or NULL if no extension is given |
@return The function returns pointers to decomposed parts in the parameters |
path, name and ext, no memory is allocated for these pointers. |
Created by Tomas Koudelka, 10.2023 |
*/ |
void filename_decomp_ptr (char *fnstr, char *&path, char *&name, char *&ext) |
{ |
path = strrchr(fnstr,'/'); |
if (path == NULL) |
path = strrchr(fnstr,'\\'); |
if (path) |
name = path + 1; |
else |
name = fnstr; |
ext = strrchr(name, '.'); |
} |
/** |
The function extracts path from the filename given by parameter file. |
@param file[in] - string pointer with filename |
/trunk/SIFEL/GEFEL/iotools.h |
---|
166,6 → 166,12 |
/// function decomposes the file name to strings with path, filename and suffix |
void filename_decomposition (const char *file,char *&path,char *&name,char *&suffix); |
/// function decomposes the file name into pointers to the beginnings of path, name and extension |
void filename_decomp_ptr (const char *fnstr, const char *&path, const char *&name, const char *&ext); |
/// function decomposes the file name into pointers to the beginnings of path, name and extension |
void filename_decomp_ptr (char *fnstr, char *&path, char *&name, char *&ext); |
/// function returns string with file path from the given filename |
char* get_path (char *file, char *&p); |
#endif |
/trunk/SIFEL/GEFEL/lcoordsys.cpp |
---|
0,0 → 1,192 |
#include "lcoordsys.h" |
#include "gfmatrix.h" |
#include "matrix.h" |
#include "vector.h" |
#include "gnode.h" |
#include "iotools.h" |
#include <stdlib.h> |
const double lcoordsys::zero = 1.0e-10; |
const char *lcoordsys::namepar[] = {"x", "y", "z", "t"}; |
lcoordsys::lcoordsys() : dim{3L}, tt{no_tr}, caxis{NULL}, paxis{NULL}, tmat{NULL}, gftmat{NULL} |
{ |
} |
lcoordsys::lcoordsys(long pdim) : dim{pdim}, tt{no_tr}, caxis{NULL}, paxis{NULL}, tmat{NULL}, gftmat{NULL} |
{ |
} |
lcoordsys::~lcoordsys() |
{ |
delete paxis; |
delete caxis; |
delete tmat; |
} |
/** |
The function reads definition of one local coordinate system from the opened text file. |
@param[in] in - pointer to the opened text file |
@retval 0 - on success |
@retval 1 - error of the reading of coordinate system definition |
Created by Tomas Koudelka, 09.2023 |
*/ |
void lcoordsys::read (XFILE *in) |
{ |
xfscanf(in, "%k%m", "transf_type", &tmat_type_kwdset, &tt); |
switch (tt){ |
case gen_tr: |
tmat = new matrix(dim, dim); |
readm(in, *tmat); |
break; |
case cyl_tr: |
if (dim != 3) |
dim = 3; |
paxis = new vector(dim); |
caxis = new vector(dim); |
readv(in, *paxis); |
readv(in, *caxis); |
normalize(*caxis); |
break; |
case gfgen_tr: |
gftmat = new gfmatrix(dim, dim); |
readm(in, *tmat); |
break; |
default: |
print_err("unknown type %d of a local coordinate system\n", |
__FILE__, __LINE__, __func__, tt); |
abort(); |
} |
} |
/** |
The function reads definition of one local coordinate system from the opened text file. |
@param[in] in - pointer to the opened text file |
@retval 0 - on success |
@retval 1 - error of the reading of coordinate system definition |
Created by Tomas Koudelka, 09.2023 |
*/ |
void lcoordsys::print (FILE *out) |
{ |
fprintf(out, "%d\n", int(tt)); |
switch (tt){ |
case gen_tr: |
printm(out, *tmat); |
break; |
case cyl_tr: |
printv(out, *paxis); |
printv(out, *caxis); |
break; |
case gfgen_tr: |
printm(out, *tmat); |
break; |
default: |
print_err("unknown type %d of a local coordinate system\n", |
__FILE__, __LINE__, __func__, tt); |
abort(); |
} |
fprintf(out, "\n"); |
} |
/** |
The function returns transformation matrix in the argument t. |
@param[in,out] t - transformation matrix, it must be allocated to dimensions (dim,dim). |
@param[in] pc - point coordinates at which the transformation matrix will be assembled. |
@param[in] time - actual time for the transformation with the help of a general function matrix |
Created by Tomas Koudelka, 09.2023 |
*/ |
void lcoordsys::give_transfmat(matrix &t, vector &pc, double time) |
{ |
vector auxv; |
switch (tt){ |
case no_tr: |
identm(t); |
break; |
case gen_tr: |
if (copym(*tmat, t)){ |
print_err("cannot assemble of the lcs transformation matrix\n", |
__FILE__, __LINE__, __func__); |
abort(); |
} |
break; |
case cyl_tr: |
give_cyl_transfmat(t, pc); |
break; |
case gfgen_tr: |
reallocv(RSTCKVEC(4, auxv)); |
auxv(0) = pc(0); |
auxv(1) = pc(1); |
auxv(2) = pc(2); |
auxv(3) = time; |
gftmat->evaluate(auxv, namepar, t); |
break; |
default: |
print_err("unknown type %d of a local coordinate system\n", |
__FILE__, __LINE__, __func__, tt); |
abort(); |
} |
} |
/** |
The function assembles transformation matrix for a cylindrical domain. The matrix is returned in |
the argument t. |
@param[in,out] t - transformation matrix, it must be allocated to dimensions (dim,dim) |
@param[in] pc - point coordinates at which the transformation matrix will be assembled. |
Created by Tomas Koudelka, 09.2023 |
*/ |
void lcoordsys::give_cyl_transfmat(matrix &t, vector &pc) |
{ |
vector lx(ASTCKVEC(3)); |
vector ly(ASTCKVEC(3)); |
vector lz(ASTCKVEC(3)); |
copyv(*caxis, lz); |
lx(0L) = pc(0) - (*paxis)(0L); |
lx(1L) = pc(1) - (*paxis)(1L); |
lx(2L) = pc(2) - (*paxis)(2L); |
double nlx = normv(lx); |
if (nlx < zero){ |
lx(0L) = 1.0; |
lx(1L) = lx(2L) = 0.0; |
} |
double aux; |
scprd(lx, lz, aux); |
lx(0L) -= aux*lz(0L); |
lx(1L) -= aux*lz(1L); |
lx(2L) -= aux*lz(2L); |
normalize(lx); |
crprd(lx, lz, ly); |
normalize(ly); |
// assemble transformation matrix from the base vectors |
for (long i=0L; i<3L; i++){ |
t(i, 0L) = lx(i); |
t(i, 1L) = ly(i); |
t(i, 2L) = lz(i); |
} |
} |
/trunk/SIFEL/GEFEL/lcoordsys.h |
---|
0,0 → 1,58 |
#ifndef LCOORDSYS_H |
#define LCOORDSYS_H |
#include "galias.h" |
#include <stdio.h> |
class gfmatrix; |
class matrix; |
class gnode; |
class vector; |
struct XFILE; |
class lcoordsys |
{ |
public: |
/// default constructor |
lcoordsys (void); |
/// constructor with problem dimension specified |
lcoordsys (long pdim); |
/// destructor |
~lcoordsys (void); |
/// function reads definition of a local coordinate system from the opened text file |
void read (XFILE *in); |
/// function prints definition of a local coordinate system from the opened text file |
void print (FILE *out); |
/// function assembles transformation matrix |
void give_transfmat(matrix &t, vector &pc, double time); |
/// function assembles transformation matrix for a cylindrical domain |
void give_cyl_transfmat(matrix &t, vector &pc); |
static const double zero; |
static const char *namepar[]; |
/// dimensions of the transformation matrix |
long dim; |
/// transformation matrix type |
tmat_type tt; |
/// base vector in the direction of cylinder axis (for a cylindrical domains, tm = gen_tr) |
vector *caxis; |
/// a point on the cylinder axis |
vector *paxis; |
/// transformation matrix from the local to global coordinate system for general case (tm = gen_tr) |
matrix *tmat; |
/// transformation matrix from the local to global coordinate system for general case (tm = gfgen_tr) |
gfmatrix *gftmat; |
}; |
#endif |
/trunk/SIFEL/GEFEL/matrix.cpp |
---|
3260,7 → 3260,7 |
with size (dim,dim) |
@param a - local %matrix (during input), global %matrix (during output) |
@param t - transformation %matrix |
@param t - transformation %matrix T |
Created by JK, |
*/ |
3299,6 → 3299,56 |
/** |
The function transforms %matrix expressed in global coordinate |
system to %matrix expressed in local coordinate system A_l = T^T . A_g . T. |
Thus the transformation %matrix T is defined as v_g = T * v_l, where v_l is the |
%vector in the given local coordinate system and v_g is the %vector in the global |
coordinate system. |
The dimension (dim) of the problem is determined from the size of |
the transformation %matrix T. The %matrix A may contain several blocks |
with size (dim,dim) |
@param a - local %matrix (during input), global %matrix (during output) |
@param t - transformation %matrix T |
Created by TKo according to JK, 09.2023 |
*/ |
void glmatrixtransfblock (matrix &a, const matrix &t) |
{ |
long i,j,k,ii,jj; |
double s; |
// problem dimension, 2D or 3D |
long dim=t.n; |
matrix b(ASTCKMAT(dim, dim)); |
for (ii=0;ii<a.n;ii+=dim){ |
for (jj=0;jj<a.n;jj+=dim){ |
for (i=0;i<dim;i++){ |
for (j=0;j<dim;j++){ |
s=0.0; |
for (k=0;k<dim;k++){ |
s+=a[ii+i][jj+k]*t[k][j]; |
} |
b[i][j]=s; |
} |
} |
for (i=0;i<dim;i++){ |
for (j=0;j<dim;j++){ |
s=0.0; |
for (k=0;k<dim;k++){ |
s+=t[k][i]*b[k][j]; |
} |
a[ii+i][jj+j]=s; |
} |
} |
} |
} |
} |
/** |
The function transforms %vector v expressed in global coordinate |
system to %vector expressed in local coordinate system v_l = T^T . v_g |
3422,9 → 3472,9 |
if (j<1) continue; |
else{ |
j--; |
#ifdef INC_OPENMP |
#pragma omp atomic update |
#endif |
//#ifdef INC_OPENMP |
//#pragma omp atomic update |
//#endif |
gv[j]+=lv[i]; |
} |
} |
3582,7 → 3632,7 |
Function computes principal values and vectors of |
tensors of 2D and 3D problems . |
@param v - matrix of second or third order tensor |
@param v - matrix of second order tensor |
@param pval - vector of sorted principal values (from min to max) |
@param pvect - matrix of principal direction vectors stored in columns |
@param ni - number of iterations in jacobi method |
/trunk/SIFEL/GEFEL/matrix.h |
---|
479,6 → 479,8 |
/// transforms block %matrix a given in the local coordinate system to the global one (A_g := T . A_l . T^T) (number of blocks is given by dimension of T) |
void lgmatrixtransfblock (matrix &a, const matrix &t); |
/// transforms block %matrix a given in the global coordinate system to the local one (A_l := T^T . A_g . T) (number of blocks is given by dimension of T) |
void glmatrixtransfblock (matrix &a, const matrix &t); |
/// transforms block %vector v given in the global coordinate system to the local one (v_l := T^T . v_g) (number of blocks is given by dimension of T) |
void glvectortransfblock (vector &v, const matrix &t); |
/// transforms block %vector v given in the local coordinate system to the global one (v_g := T^T . v_l) (number of blocks is given by dimension of T) |
/trunk/SIFEL/GEFEL/selection.cpp |
---|
81,10 → 81,22 |
ncomp[0] = 1; |
if (xfscanf(in, "%ld", id1) != 1) |
{ |
print_err("cannot read reading period", __FILE__, __LINE__, __func__); |
print_err("cannot read period", __FILE__, __LINE__, __func__, seltype_kwdset.get_str(st)); |
return 2; |
} |
return 0; |
case sel_single: |
n = 1; |
id1 = new long [1]; |
ncomp = new long [1]; |
ncomp[0] = 1; |
if (xfscanf(in, "%ld", id1) != 1) |
{ |
print_err("cannot read single selection", __FILE__, __LINE__, __func__, seltype_kwdset.get_str(st)); |
return 2; |
} |
id1[0]--; |
return 0; |
case sel_realperiod: |
if (xfscanf(in, "%k%le%k%le%k%le%k%le", "ini_time", &initime, |
"fin_time", &fintime, "period", &r, "err", &err) != 8) |
345,6 → 357,8 |
fprintf(out, "\n"); |
} |
break; |
case sel_single: |
fprintf(out, " %ld\n", id1[0]+1); |
default: |
print_err("unknown type of selection is required", __FILE__, __LINE__, __func__); |
} |
372,6 → 386,7 |
case sel_all: |
case sel_range: |
case sel_period: |
case sel_single: |
case sel_impvalues: |
case sel_mtx: |
case sel_range_vec: |
527,6 → 542,10 |
} |
} |
break; |
case sel_single: |
if (id1[0] == id) |
return 1; |
break; |
default: |
print_err("unknown type of selection is required", __FILE__, __LINE__, __func__); |
} |
1061,6 → 1080,14 |
if (id1[i] < tncomp) ret++; |
} |
break; |
case sel_single: |
ret = 1; |
break; |
case sel_period: |
ret = 0; |
for (i=0; i<tncomp; i+=id1[0]) |
ret++; |
break; |
default: |
print_err("unknown type of selection is required", __FILE__, __LINE__, __func__); |
} |
1208,6 → 1235,119 |
/** |
The function converts selection of nodes/elements according to given property |
id and entity type to selection types list or range. |
@param[in] top - mesh topology with defined properties of nodes and elements |
@param[in] ot - object type indicator for the given property selection |
it specifies whether the given selection by property id is related |
to nodes or elements |
@retval 0 - on success |
@retval 1 - in case of unknown type of object |
@retval 2 - no edge or surface property ids were specified on elements in the given topology |
Created by Tomas Koudelka, 09.2023 |
*/ |
long sel::conv_selprop(siftop *top, objtype ot) |
{ |
long i,j; |
long nlit, nrit, nold; |
long *nlitent, *nritent; |
long ret; |
long **selobjent; |
long nobj; |
long *entid; |
long nentid; |
switch (ot) |
{ |
case gelem: |
nobj = top->ne; |
break; |
case gnod: |
nobj = top->nn; |
break; |
default: |
print_err("unknown type of object(%d) is required", __FILE__, __LINE__, __func__, ot); |
return 1; |
} |
nlitent = new long[n]; |
memset(nlitent, 0, sizeof(*nlitent)*n); |
nritent = new long[n]; |
memset(nritent, 0, sizeof(*nritent)*n); |
nold = n; |
selobjent = new long*[n]; |
memset(selobjent, 0, sizeof(*selobjent)*n); |
for (i=0; i<n; i++) // loop for particular specified entities |
{ |
selobjent[i] = new long[nobj]; |
memset(selobjent[i], 0, sizeof(*selobjent[i])*nobj); |
switch (ot) |
{ |
case gelem: |
for (j=0; j<top->ne; j++){ |
entid = NULL; |
nentid = 0; |
ret = top->elements[j].searchprop(id1[i], ent[i], NULL, j, top->edges, top->surfaces, entid, nentid); |
if (ret < 0){ |
print_err("no edge or surface properties are given on elements", __FILE__, __LINE__, __func__); |
return 2; |
} |
selobjent[i][j] += ret; |
} |
break; |
case gnod: |
for (j=0; j<top->nn; j++){ |
entid = NULL; |
nentid = 0; |
top->get_propent_nodes(id1[i], ent[i], selobjent[i]); |
} |
break; |
default: |
print_err("unknown type of object(%d) is required", __FILE__, __LINE__, __func__, ot); |
return 1; |
} |
nlitent[i] = give_num_lst_items(nobj, selobjent[i]); // number of selected objects of the given entity |
nritent[i] = give_num_range_items(nobj, selobjent[i]); // number of ranges in the selection of objects of the given entity |
} |
// compute total number of records for the resulting list and range selection types |
nlit = nrit = 0; |
for (j=0; j<n; j++){ |
nlit += nlitent[j]; |
nrit += nritent[j]; |
} |
delete [] id1; |
delete [] ncomp; |
delete [] ent; |
ent = NULL; |
if (2*nrit < nlit){ |
// range needs two numbers for the specification |
// conversion to the range type selection is more favourable |
conv2range(nrit, nobj, selobjent); |
} |
else{ |
// conversion to the list type selection is more favourable |
conv2lst(nlit, nobj, selobjent); |
} |
for (i=0; i < nold; i++) // n was changed in course of conversion to new range or list selection => nold must be used |
delete [] selobjent[i]; |
delete [] selobjent; |
delete [] nlitent; |
delete [] nritent; |
return 0; |
} |
/** |
The function returns number of selected objects given in the array selobj. |
@param nobj - length of the array selobj, i.e. the total number of selectable objects |
1412,6 → 1552,107 |
It is supposed that the number of selected ranges was detected by call of give_num_range_items. |
The list of selected objects is represented by the array selobj with length nobj. Selected |
object is indicated by nonzero selobj component while the remaining components are zero. |
The function is used for the selection of nodes or elements according to property id in the |
outdriver class. |
@param nit - number of detected ranges |
@param nobj - length of array selobj, i.e. the total number of selectable objects |
@param selobj - 2D array of indicators for particular entities whether the given j-th object |
is selected for i-th entity (selobj[i][j] != 0) or not (selobj[i][j] = 0) |
@return The function does not return anything but it changes internal parameters of the class |
to the range selection type. |
Created by Tomas Koudelka, 09.2023 |
*/ |
void sel::conv2range(long nit, long nobj, long **selobj) |
{ |
long i, j, k, start_r, nold = n; |
st = sel_range; |
n = nit; |
id1 = new long[n]; |
ncomp = new long[n]; |
memset(id1, 0, sizeof(*id1)*n); |
memset(ncomp, 0, sizeof(*ncomp)*n); |
j = 0; |
for (i=0; i < nold; i++){ |
start_r = 0; |
for(k=0; k<nobj; k++){ |
if (selobj[i][k]){ |
// k-th object is selected |
if (start_r == 0){ |
// no range is started => start new range |
id1[j] = k; |
start_r = 1; // set indicator that we have started new range |
} |
continue; |
} |
else{ |
// k-th object is not selected |
if (start_r){ |
// a range has been started => finish the range |
ncomp[j] = k-id1[j]; // number of components in the range |
j++; // increase range index |
start_r = 0; // switch off the new range indicator |
} |
} |
} |
if (start_r) // a range has been started => finish the range |
ncomp[j] = k-id1[j]; // number of components in the range |
} |
} |
/** |
The function converts list of selected objects to the list type of selection. |
It is supposed that the number of selected items was detected by call of give_num_lst_items. |
The list of selected objects is represented by the array selobj with length nobj. Selected |
object is indicated by nonzero selobj component while the remaining components are zero. |
The function is used for the selection of nodes or elements according to property id in the |
outdriver class. |
@param nit - number of list items |
@param nobj - length of array selobj, i.e. the total number of selectable objects |
@param selobj - 2D array of indicators for particular entities whether the given j-th object |
is selected for i-th entity (selobj[i][j] != 0) or not (selobj[i][j] = 0) |
@return The function does not return anything but it changes internal parameters of the class |
to the list selection type. |
Created by Tomas Koudelka, 9.1.2015 |
*/ |
void sel::conv2lst(long nit, long nobj, long **selobj) |
{ |
long i, j, k, nold = n; |
st = sel_list; |
n = nit; |
id1 = new long[n]; |
ncomp = NULL; |
memset(id1, 0, sizeof(*id1)*n); |
j = 0; |
for (k=0; k<nold; k++){ |
for (i=0; i<nobj; i++){ |
if (selobj[k][i]){ |
id1[j]=i; |
j++; |
} |
} |
} |
} |
/** |
The function converts list of selected objects to the range type of selection. |
It is supposed that the number of selected ranges was detected by call of give_num_range_items. |
The list of selected objects is represented by the array selobj with length nobj. Selected |
object is indicated by nonzero selobj component while the remaining components are zero. |
The function is used for the selection of nodes with prescribed initial displacements by the given rotation |
in gradual construction problems. |
/trunk/SIFEL/GEFEL/selection.h |
---|
62,8 → 62,14 |
void conv2range(long nit, long nobj, long **selobj, sel *conselent, sel *conselr, long *transent, long *transr); |
/// convert the given list of objects to the list selection type |
void conv2lst(long nit, long nobj, long **selobj, sel *conselent, sel *consell, long *transent, long *transl); |
/// convert the given list of objects to the range selection type |
void conv2range(long nit, long nobj, long **selobj); |
/// convert the given list of objects to the list selection type |
void conv2lst(long nit, long nobj, long **selobj); |
/// converts selection type of property to selection type of list |
long conv_selprop(siftop *top, objtype ot, sel *conselent, sel *&consel, long *transent, long *&trans); |
/// converts selection type of property to selection type of list |
long conv_selprop(siftop *top, objtype ot); |
/// converts list of the selected objects to the range type of selection |
void conv2range(long nit, long nobj, ivector &selobj); |
/// converts list of the selected objects to the list type of selection |
/trunk/SIFEL/GEFEL/stackdef.h |
---|
1,7 → 1,7 |
#ifndef STACKDEF_H |
#define STACKDEF_H |
#ifdef __linux__ // Linux GCC compiler |
#if defined(__linux__) || defined(__APPLE__) // Linux or Apple GCC compiler |
#define DEFALLOCA <alloca.h> |
#define ALLOCAF alloca |
#else // Open Watcom, Borland C++, MS Visual C++ |
/trunk/SIFEL/GEFEL/vector.cpp |
---|
1322,6 → 1322,35 |
/** |
The function adds %vector given by argument b to the vector given by argument a. |
@param[in,out] a is the structure of the first vector which will be added to. |
@param[in] b is the structure of the second added vector. |
@b Requests : |
a and b have to be same dimensions |
@retval 0 : on succes |
@retval 1 : in case incompatibility sizes of a and b. |
Created by Tomas Koudelka, tomas.koudelka@fsv.cvut.cz, 09.2023 |
*/ |
long addv(vector &a, const vector &b) |
{ |
if (a.n != b.n) |
{ |
print_err("cannot add vectors due to their incompatible dimensions\n" |
"a(%ld) X b(%ld)", __FILE__, __LINE__, __func__, a.n, b.n); |
return (1); |
} |
for (long i = 0; i < a.n; i++) |
a.a[i] += b.a[i]; |
return(0); |
} |
/** |
The function adds vector given by a to %vector given by b, the result is stored in c. |
@param a is the structure of the first added vector |
/trunk/SIFEL/GEFEL/vector.h |
---|
445,6 → 445,8 |
/// adds 2 vectors c = a+b |
long addv(const vector &a, const vector &b, vector &c); |
/// adds vectors a = a+b |
long addv(const vector &a, const vector &b); |
/// adds 2 double arrays, 2nd array is multplied by constant c = a + bc*b |
void addmultv(const vector &a, const vector &b, double bc, vector &c); |
/// adds 2 double arrays, 2nd array is multplied by constant a = a + bc*b |
/trunk/SIFEL/MEFEL/PREP/hngen.cpp |
---|
0,0 → 1,13 |
#include <float.h> |
#include "hngen.h" |
#include "vector.h" |
hngen::hngen() |
{ |
x = y = z = 0.0; |
xi = eta = zeta = 0.0; |
cerr = DBL_MAX; |
eid = -1; |
et = gtypel(-1); |
} |
/trunk/SIFEL/MEFEL/PREP/hngen.h |
---|
0,0 → 1,20 |
#ifndef HNGEN_H |
#define HNGEN_H |
#include "galias.h" |
#include "vector.h" |
class hngen |
{ |
public: |
double x, y, z; // global coordinates of hanging node |
double xi, eta, zeta; // natural coordinates of hanging node on element eid |
double cerr; // error of computed natural coordinates if they are not in range [-1.0;1.0] exactly |
long eid; // master element id on which the hanging node is located eid >=0, |
gtypel et; // general element type used for the hanging node assignment |
ivector mnodes; /// array of master nodes |
hngen(); |
}; |
#endif |
/trunk/SIFEL/MEFEL/SRC/Makefile |
---|
40,8 → 40,8 |
SRCS += dloadn.cpp dloadel.cpp dloadpd.cpp drprag.cpp doubdp.cpp drprag2.cpp dsm.cpp dst.cpp edgem.cpp edsolver.cpp effstress.cpp eigvalsol.cpp elastgmat2d.cpp elastgmat3d.cpp |
SRCS += elastisomat.cpp elastisopdmat.cpp elastortomat.cpp elasttime.cpp element.cpp elemparticle.cpp elemswitch.cpp endnodem.cpp epsolver.cpp fdsolver.cpp flsubdom.cpp fixortodam.cpp |
SRCS += generalmod.cpp |
SRCS += geoelast.cpp glasgmech.cpp glasgowdam.cpp global.cpp globmat.cpp |
SRCS += graphmat.cpp hardsoft.cpp hissplas.cpp homog.cpp homogmatm.cpp homogmech.cpp hvisolver.cpp inicd.cpp intpoints.cpp isoviscous.cpp hypoplunsatexptherm2.cpp |
SRCS += geoelast.cpp glasgmech.cpp glasgowdam.cpp global.cpp globmat.cpp gnodvalvm.cpp |
SRCS += graphmat.cpp hardsoft.cpp hissplas.cpp hexiface.cpp homog.cpp homogmatm.cpp homogmech.cpp hvisolver.cpp inicd.cpp intpoints.cpp isoviscous.cpp hypoplunsatexptherm2.cpp |
SRCS += j2flow.cpp layplate.cpp lbsolver.cpp lemaitre.cpp lenjonesmat.cpp lfssolver.cpp lhsrhs.cpp |
SRCS += linhex.cpp linhexrot.cpp lintet.cpp lintetrot.cpp linwedge.cpp llssolver.cpp loadcase.cpp |
49,12 → 49,12 |
SRCS += mechtop.cpp mefelinit.cpp meshtransfer.cpp microfiber.cpp microM4.cpp microSIM.cpp |
SRCS += mohrc.cpp mohrcparab.cpp mtglvec.cpp mtsolver.cpp ndsolver.cpp newtonraph.cpp nfssolver.cpp node.cpp |
SRCS += nonlocdamg2.cpp nonlinman.cpp nonlocmicroM4.cpp nonlocplast.cpp nssolver.cpp ortodam.cpp ortodam2.cpp ortodamrot.cpp |
SRCS += outdiagm.cpp outdriverm.cpp plelemlq.cpp plelemlt.cpp plelemqq.cpp plelemqt.cpp plelemrotlq.cpp |
SRCS += outdiagm.cpp outdriverm.cpp outquantm.cpp outresfilem.cpp plelemlq.cpp plelemlt.cpp plelemqq.cpp plelemqt.cpp plelemrotlq.cpp |
SRCS += plelemrotlt.cpp plelemsubqt.cpp plquadiface.cpp probdesc.cpp problem.cpp q4plate.cpp quadhex.cpp quadrilatkirch.cpp |
SRCS += quadtet.cpp quadwedge.cpp relaxeuroc.cpp scaldam.cpp scaldamcc.cpp seismtool.cpp sequent.cpp |
SRCS += shefplast.cpp shellq.cpp shelltr.cpp shelltrm.cpp shrinkmat.cpp simviscous.cpp slipsurf.cpp slopesol.cpp slsolver.cpp |
SRCS += soilbeam.cpp soilplateq.cpp soilplatetr.cpp solverm.cpp splas1d.cpp springel.cpp stochdriver.cpp strretalg.cpp |
SRCS += tetralattice.cpp therisomat.cpp thervolisomat.cpp timeswmat.cpp varelastisomat.cpp vecttens.cpp viselast.cpp visplast.cpp |
SRCS += soilbeam.cpp soilplateq.cpp soilplatetr.cpp solverm.cpp splas1d.cpp springel.cpp stochdriver.cpp strretalg.cpp tensorcname.cpp |
SRCS += tetralattice.cpp therisomat.cpp thervolisomat.cpp timeswmat.cpp varelastisomat.cpp vectorcnamem.cpp vecttens.cpp viselast.cpp visplast.cpp |
SRCS += winpast.cpp z2_smoothing.cpp umatunsat2.cpp |
/trunk/SIFEL/MEFEL/SRC/alias.h |
---|
108,7 → 108,7 |
axisymmlt=60,axisymmqt=61,axisymmlq=63,axisymmqq=64,axisymmcq=65, |
shelltrelem=80,shellqelem=81,shelltrmelem=82, |
lineartet=100,quadrtet=101,linearhex=102,quadrhex=103,lineartetrot=104,linearhexrot=105, |
linearwed=106,quadrwed=107, |
linearwed=106,quadrwed=107,hexintface=111, |
particleelem=200,tetralatt=250}; |
const enumstr elemtypestr[] = {{"bar2d",1}, {"beam2d",2}, {"bar3d",3}, {"beam3d",4}, {"beamg3d",5}, |
{"barq2d",6},{"barq3d",7}, {"subsoilbeam",8}, |
123,7 → 123,7 |
{"shelltrelem",80}, {"shellqelem",81}, {"shelltrmelem",82}, |
{"lineartet",100}, {"quadrtet",101}, {"linearhex",102}, {"quadrhex",103}, |
{"lineartetrot",104}, {"linearhexrot",105}, |
{"linearwed",106}, {"quadrwed",107}, |
{"linearwed",106}, {"quadrwed",107}, {"hexintface",111}, |
{"particleelem",200}, {"tetralatt",250}}; |
const kwdset elemtype_kwdset(sizeof(elemtypestr)/sizeof(*elemtypestr), elemtypestr); |
220,8 → 220,8 |
// aliases for quantity types |
enum strastre {strain=0,stress=1,other=2,pstrain=3, pstress=4}; |
const enumstr strastrestr[] = {{"strain",0}, {"stress",1}, {"other",2}, {"pstrain",3}, {"pstress",4}}; |
enum strastre {undef_strastre=-1,strain=0,stress=1,other=2,pstrain=3, pstress=4}; |
const enumstr strastrestr[] = {{"undef_strastre",-1}, {"strain",0}, {"stress",1}, {"other",2}, {"pstrain",3}, {"pstress",4}}; |
const kwdset strastre_kwdset(sizeof(strastrestr)/sizeof(*strastrestr), strastrestr); |
418,78 → 418,115 |
// aliases for type of mechanical quantities |
enum mechquant {nomech_q=0, |
displ_q=1, // displacement vector |
strain_q=2, // strain tensor |
stress_q=3, // stress tensor |
other_q=4, // other array values as scalar |
other_vec_q=5, // other array values as vector |
other_tens_q=6, // other array values as tensor |
react_q=7, // reactions vector at nodes |
load_vect_q=8, // load vector at nodes |
int_force_q=9, // internal force vector |
resid_vec_q=10, // residual vector |
tempr_strain_q=11, // temperature strain tensor |
eig_strain_q=12, // eigenstrain tensor |
eig_stress_q=13, // eigenstress tensor |
time_q=14, // time (constant scalar quantity at whole domain) |
step_id_q=15, // step id (constant scalar quantity at whole domain) |
load_fact_q=16, // load factor in nonlinear statics problem type (constant scalar quantity at whole domain) |
eigval_q=17, // eigen values in eigenvalue problem type (constant scalar quantity at whole domain) |
macrostrain_q=18, // macrostrain (constant tensor quantity at whole domain) |
macrostress_q=19, // macrostress (constant tensor quantity at whole domain) |
nonmech_q=20, // nonmechanical quantities at ip |
eps_x=21, eps_y=22, eps_z=23, eps_yz=24, eps_xz=25, eps_xy=26, // strain components as scalars |
sig_x=27, sig_y=28, sig_z=29, sig_yz=30, sig_xz=31, sig_xy=32, // stress components as scalars |
first_inv=33, // A11 + A22 + A33 |
second_inv=34, // A11*A22 + A11*A33 + A22*A33 - A12^2 - A13^2 - A23^2 |
third_inv=35, // det|A| |
tensor_norm=36, // ||A|| = sqrt(a_ij*a_ij) |
tensdeviator=37, // D_ij = A_ij - delta_ij*A_kk/3 |
strain_vol=38, // eps_v = eps_x + eps_y + eps_z |
mean_stress=39, // sig_m = (sig_x + sig_y + sig_z)/3 |
j2=41, // negative value of the second invariant of stress deviator, i.e. J2 = 1/2 s_ij s_ij |
von_mises_stress=40,// sig_eff = sqrt(3*J2) |
strain_deviator=42, // s_ij = sig_ij - delta_ij*sig_m |
stress_deviator=42, // e_ij = eps_ij - delta_ij*eps_v/3 |
strain_pl=43, // plastic strain tensor |
cons_param=44, // consistency parameter gamma |
damage_scal=45, // scalar damage (omega) |
damaget_scal=46, // scalar damage (omega_t) in tension |
damagec_scal=47, // scalar damage (omega_c) in compression |
damage_tens=48, // damage tensor (Omega) |
damaget_tens=49, // damage tensor (Omega_t) in tension |
damagec_tens=50, // damage tensor (Omega_c) in compression |
eps_px=51, eps_py=52, eps_pz=53, eps_pyz=54, eps_pxz=55, eps_pxy=56 // components of plastic strains considered as scalars |
enum mechquant { |
nomech_q=0, |
displ_q=1, // displacement vector (r) |
strain_q=2, // strain tensor (eps) |
stress_q=3, // stress tensor (sig) |
other_q=4, // other array values as a vector (other) |
react_q=5, // reactions vector at nodes (R) |
load_vect_q=6, // load vector at nodes (f_l) |
int_force_q=7, // internal force vector (f_i) |
resid_vect_q=8, // residual vector (f_r) |
tempr_strain_q=9, // temperature strain tensor (epst) |
eig_strain_q=10, // eigenstrain tensor (eps0) |
eig_stress_q=11, // eigenstress tensor (sig0) |
time_q=12, // time (constant scalar quantity at whole domain) |
step_id_q=13, // step id (constant scalar quantity at whole domain) |
load_fact_q=14, // load factor in nonlinear statics problem type (constant scalar quantity at whole domain) |
eigval_q=15, // eigen values in eigenvalue problem type (constant scalar quantity at whole domain) |
macrostrain_q=16, // macrostrain (constant tensor quantity at whole domain) (Sig) |
macrostress_q=17, // macrostress (constant tensor quantity at whole domain) (Eps) |
nonmech_q=18, // nonmechanical quantities at ip |
first_inv=19, // A11 + A22 + A33 (I_1) |
second_inv=20, // A11*A22 + A11*A33 + A22*A33 - A12^2 - A13^2 - A23^2 (I_2) |
third_inv=21, // det|A| (I_3) |
tensor_norm=22, // ||A|| = sqrt(a_ij*a_ij) (||.||) |
tensdeviator=23, // D_ij = A_ij - delta_ij*A_kk/3 (d) |
strain_vol=24, // eps_v = eps_x + eps_y + eps_z (eps_v) |
mean_stress=25, // sig_m = (sig_x + sig_y + sig_z)/3 (sig_m) |
j2inv=26, // negative value of the second invariant of stress deviator, i.e. J2 = 1/2 s_ij s_ij (J2) |
von_mises_stress=27,// sig_eff = sqrt(3*J2) (sig_vM) |
strain_deviator=28, // e_ij = eps_ij - delta_ij*eps_v/3 (e) |
stress_deviator=29, // s_ij = sig_ij - delta_ij*sig_m (s) |
strain_pl=30, // plastic strain tensor (epsp) |
cons_param=31, // consistency parameter gamma |
damage_scal=32, // scalar damage (omega) |
damaget_scal=33, // scalar damage (omega_t) in tension |
damagec_scal=34, // scalar damage (omega_c) in compression |
damage_tens=35, // damage tensor (Omega) |
damaget_tens=36, // damage tensor (Omega_t) in tension |
damagec_tens=37, // damage tensor (Omega_c) in compression |
eps_x=38, eps_y=39, eps_z=40, gamma_yz=41, gamma_xz=42, gamma_xy=43, eps_yz=44, eps_xz=45, eps_xy=46, // strain components as scalars |
sig_x=47, sig_y=48, sig_z=49, tau_yz=50, tau_xz=51, tau_xy=52, // stress components as scalars |
epsp_x=53, epsp_y=54, epsp_z=55, gammap_yz=56, gammap_xz=57, gammap_xy=58, epsp_yz=59, epsp_xz=60, epsp_xy=61 // components of plastic strains considered as scalars |
}; |
const enumstr mechquantstr[] = {{"nomech_q", 0}, |
{"displ_q",1}, |
{"strain_q",2}, |
{"stress_q",3}, |
{"other_q",4}, |
{"other_vec_q",5}, |
{"other_tens_q",6}, |
{"react_q",7}, |
{"load_vect_q",8}, |
{"int_force_q",9}, |
{"resid_vec_q",10}, |
{"tempr_strain_q",11}, |
{"eig_strain_q",12}, |
{"eig_stress_q",13}, |
{"time_q",14}, |
{"step_id_q",15}, |
{"load_fact_q",16}, |
{"eigval_q",17}, |
{"macrostrain_q",18}, |
{"macrostress_q",19}, |
{"nonmech_q",20}, |
{"eps_x",21}, {"eps_y",22}, {"eps_z",23}, {"eps_yz",24}, {"eps_xz",25}, {"eps_xy",26}, |
{"sig_x",27}, {"sig_y",28}, {"sig_z",29}, {"sig_yz",30}, {"sig_xz",31}, {"sig_xy",32}, |
{"first_inv",33}, {"second_inv",34}, {"third_inv",35}, {"tensor_norm",36}, |
{"tensdeviator",37},{"strain_vol",38}, {"mean_stress",39}, {"j2",41}, {"von_mises_stress",40}, |
{"strain_deviator",42}, {"stress_deviator",42}, {"strain_pl",43}, {"cons_param",44}, {"damage_scal",45}, |
{"damaget_scal",46}, {"damagec_scal",47}, {"damage_tens",48}, {"damaget_tens",49}, {"damagec_tens",50}, |
{"eps_px",51}, {"eps_py",52}, {"eps_pz",53}, {"eps_pyz",54}, {"eps_pxz",55}, {"eps_pxy",56} |
const enumstr mechquantstr[] = { |
{"nomech_q", 0}, |
{"displ_q", 1}, // displacement vector |
{"strain_q", 2}, // strain tensor |
{"stress_q", 3}, // stress tensor |
{"other_q", 4}, // other array values as scalar |
{"react_q", 5}, // reactions vector at nodes |
{"load_vect_q", 6}, // load vector at nodes |
{"int_force_q", 7}, // internal force vector |
{"resid_vect_q", 8}, // residual vector |
{"tempr_strain_q", 9}, // temperature strain tensor |
{"eig_strain_q", 10}, // eigenstrain tensor |
{"eig_stress_q", 11}, // eigenstress tensor |
{"time_q", 12}, // time (constant scalar quantity at whole domain) |
{"step_id_q", 13}, // step id (constant scalar quantity at whole domain) |
{"load_fact_q", 14}, // load factor in nonlinear statics problem type (constant scalar quantity at whole domain) |
{"eigval_q", 15}, // eigen values in eigenvalue problem type (constant scalar quantity at whole domain) |
{"macrostrain_q", 16}, // macrostrain (constant tensor quantity at whole domain) |
{"macrostress_q", 17}, // macrostress (constant tensor quantity at whole domain) |
{"nonmech_q", 18}, // nonmechanical quantities at ip as a vector |
{"first_inv", 19}, // A11 + A22 + A33 |
{"second_inv", 20}, // A11*A22 + A11*A33 + A22*A33 - A12^2 - A13^2 - A23^2 |
{"third_inv", 21}, // det|A| |
{"tensor_norm", 22}, // ||A|| = sqrt(a_ij*a_ij) |
{"tensdeviator", 23}, // D_ij = A_ij - delta_ij*A_kk/3 |
{"strain_vol", 24}, // eps_v = eps_x + eps_y + eps_z |
{"mean_stress", 25}, // sig_m = (sig_x + sig_y + sig_z)/3 |
{"j2inv", 26}, // negative value of the second invariant of stress deviator}, i.e. J2 = 1/2 s_ij s_ij |
{"von_mises_stress", 27},// sig_eff = sqrt(3*J2) |
{"strain_deviator", 28}, // e_ij = eps_ij - delta_ij*eps_v/3 |
{"stress_deviator", 29}, // s_ij = sig_ij - delta_ij*sig_m |
{"strain_pl", 30}, // plastic strain tensor |
{"cons_param", 31}, // consistency parameter gamma |
{"damage_scal", 32}, // scalar damage (omega) |
{"damaget_scal", 33}, // scalar damage (omega_t) in tension |
{"damagec_scal", 34}, // scalar damage (omega_c) in compression |
{"damage_tens", 35}, // damage tensor (Omega) |
{"damaget_tens", 36}, // damage tensor (Omega_t) in tension |
{"damagec_tens", 37}, // damage tensor (Omega_c) in compression |
{"eps_x", 38}, // strain components as scalars |
{"eps_y", 39}, |
{"eps_z", 40}, |
{"gamma_yz", 41}, |
{"gamma_xz", 42}, |
{"gamma_xy", 43}, |
{"eps_yz", 44}, |
{"eps_xz", 45}, |
{"eps_xy", 46}, |
{"sig_x", 47}, // stress components as scalars |
{"sig_y", 48}, |
{"sig_z", 49}, |
{"tau_yz", 50}, |
{"tau_xz", 51}, |
{"tau_xy", 52}, |
{"epsp_x", 53}, // components of plastic strains considered as scalars |
{"epsp_y", 54}, |
{"epsp_z", 55}, |
{"gammap_yz", 56}, |
{"gammap_xz", 57}, |
{"gammap_xy", 58}, |
{"epsp_yz", 59}, |
{"epsp_xz", 60}, |
{"epsp_xy", 61} |
}; |
const kwdset mechquant_kwdset(sizeof(mechquantstr)/sizeof(*mechquantstr), mechquantstr); |
#endif |
/trunk/SIFEL/MEFEL/SRC/bbm.cpp |
---|
189,9 → 189,9 |
Mm->ip[ipp].other[ido+ncompstr+12] = Mm->ip[ipp].eqother[ido+ncompstr+12] = Mm->givenonmechq(suction, ipp); // suction |
} |
// set inital value of Young's modulus |
long idem = Mm->ip[ipp].gemid(); |
long ncompo = Mm->givencompeqother(ipp, im); |
Mm->ip[ipp].other[ido+ncompstr+13] = Mm->ip[ipp].eqother[ido+ncompstr+13] = comp_actual_ym(ipp, im, ido); |
//long idem = Mm->ip[ipp].gemid(); |
//long ncompo = Mm->givencompeqother(ipp, im); |
//double e_ini = Mm->give_initial_ym(ipp, idem, ido+ncompo); |
//Mm->ip[ipp].other[ido+ncompstr+13] = Mm->ip[ipp].eqother[ido+ncompstr+13] = e_ini; |
// time step scaling factor |
1614,6 → 1614,7 |
long ncompo = Mm->givencompeqother(ipp, im)-Mm->givencompeqother(ipp, idem); |
// actual Young modulus from elastic material |
double e_ini = Mm->give_actual_ym(ipp, idem, ido+ncompo); |
// actual Young modulus calculated from Cam-clay swelling line |
double e = give_actual_ym(ipp, im, ido); |
Mm->elmatstiff(d, ipp); |
cmulm(e/e_ini, d); |
1654,9 → 1655,6 |
double bbmmat::dstep_red(long ipp, long im, long ido) |
{ |
long ncomp = Mm->ip[ipp].ncompstr; |
if (ido != 1) |
return (Mm->ip[ipp].other[ido+ncomp+14]); |
return (Mm->ip[ipp].other[ido+ncomp+14]); |
} |
/trunk/SIFEL/MEFEL/SRC/contactmat.cpp |
---|
10,6 → 10,8 |
contactmat::contactmat (void) |
{ |
slip = 0.0; normal = 0.0; limitn=0.0; limits=0.0; |
eps_slip_lim = 0.0; |
eps_norm_lim = 0.0; |
} |
contactmat::~contactmat (void) |
{ |
19,6 → 21,8 |
void contactmat::read (XFILE *in) |
{ |
xfscanf (in,"%lf %lf %lf %lf",&slip,&normal,&limits,&limitn); |
eps_slip_lim = limits/slip; |
eps_norm_lim = limitn/normal; |
} |
/** |
28,99 → 32,99 |
JK, 11.6.2006 |
*/ |
void contactmat::matstiff (matrix &d,long ipp) |
void contactmat::matstiff(matrix &d, long ipp) |
{ |
long n = Mm->ip[ipp].ncompstr; |
vector eps(n),sig(n); |
d[0][0] = slip; |
d[1][1] = normal; |
switch(n){ |
case 2: // 2D interface element |
d[0][0] = slip; |
d[1][1] = normal; |
break; |
case 3: // 3D interface element |
d[0][0] = slip; |
d[1][1] = slip; |
d[2][2] = normal; |
break; |
default: |
print_err("unknown number of strain array components (%ld), only values in range [2;3] are allowed.", |
__FILE__, __LINE__,__func__, n); |
abort(); |
} |
} |
/** |
function computes nodal forces in contact problems |
nodal forces are computed from difference of nodal displacements |
at appropriate nodes |
the name nlstresses is used only with respect to other |
"classical" material models which work with stresses |
The function computes nodal forces in contact problems. |
Nodal forces are computed from difference of nodal displacements |
at appropriate nodes. |
@param ipp - integration point id |
@param im - index of material type |
@param ido - index in array other |
@param[in] ipp - integration point id |
@param[in] im - index of material type |
@param[in] ido - index in array other |
JF, 04/2013 |
JF, 04/2013 |
TKo, 10/2023 |
*/ |
void contactmat::nlstresses (long ipp, long /*im*/, long /*ido*/) |
void contactmat::nlstresses (long ipp, long /*im*/, long ido) |
{ |
long i, n = Mm->ip[ipp].ncompstr; |
vector eps(n),sig(n),dpp(n),dpmax(n); |
double dlim; |
vector eps(ASTCKVEC(n)), sig(ASTCKVEC(n)), epsp(ASTCKVEC(n)); |
// slip components |
vector seps(ASTCKVEC(n-1)), sepsp(ASTCKVEC(n-1)), dsepsp(ASTCKVEC(n-1)), sepst(ASTCKVEC(n-1)); |
double epst, epsn, epsnp, depsp=0.0; |
// initial values |
for (i=0;i<n;i++) |
{ |
eps[i]=Mm->ip[ipp].strain[i]; |
dpmax[i]=Mm->ip[ipp].eqother[i]; |
for (i=0; i<n-1; i++){ |
// slip components |
eps[i] = seps[i] = Mm->ip[ipp].strain[i]; // total |
epsp[i] = sepsp[i] = Mm->ip[ipp].eqother[ido+i]; // plastic |
} |
// normal strain components |
eps[n-1] = epsn = Mm->ip[ipp].strain[n-1]; // total |
epsp[n-1] = epsnp = Mm->ip[ipp].eqother[n-1]; // plastic |
// slip |
// maximum elastic deformation |
dlim=limits/slip; |
// compute trial slip strain increment |
subv(seps, sepsp, sepst); |
// division of the deformation |
if (fabs(eps[0]-dpmax[0]) > dlim) dpp[0]=sgn(eps[0]-dpmax[0])*(fabs(eps[0]-dpmax[0])-dlim); |
if (fabs(eps[0]-dpmax[0]) < dlim) dpp[0]=0.0; |
epst = normv(sepst); |
if (epst > eps_slip_lim){ |
// compute increment of the slip plastic strains |
cmulv(1.0/epst, sepst); // normalize epst vector |
cmulv(epst-eps_slip_lim, sepst, dsepsp); // compute plastic strain increments |
} |
// slip stress calculation |
sig[0]=slip*(eps[0]-(dpmax[0]+dpp[0])); |
// compute trial normal strain increment |
epst = fabs(epsn - epsnp); |
if (epst > eps_norm_lim){ |
// compute plastic strain increment in the normal direction |
depsp = sgn(epsn-epsnp)*(epst - eps_norm_lim); |
} |
// normal |
// maximum elastic deformation |
//dlim=limitn/normal; |
sig[1]=eps[1]*normal; |
if (sig[1]>limitn) |
sig[1]=limitn; |
if (sig[1]<-limitn) |
sig[1]=-limitn; |
/* // division of the deformation |
if ((dpmax[1] == 0) && (eps[1]<dlim)) dp[1]=0.0; // elastic branch |
if ((eps[1]-dpmax[1]) > dlim) dp[1]=eps[1]-dlim; // plastic branch, adding load |
if ((dpmax[1] > 0) && ((eps[1]-dpmax[1]) < dlim)) dp[1]=dpmax[1]; // plastic branch, unloading |
// normal stress calculation |
sig[1]=normal*(eps[1]-dp[1]); |
*/ |
// saving the dp values into "other" array |
for (i=0;i<n;i++) |
{ |
Mm->ip[ipp].other[i] = dpmax[i]+dpp[i]; |
// actualize plastic strains and compute stresses |
for(i=0; i<n-1; i++){ |
// plastic slip strains |
epsp[i] += dsepsp[i]; |
sig[i] = slip*(eps[i]-epsp[i]); |
} |
// normal plastic strain |
epsp[n-1] += depsp; |
sig[n-1] = normal*(eps[i]-epsp[i]); |
/* |
sig[1]=eps[1]*normal; |
if (sig[1]>limitn) |
sig[1]=limitn; |
if (sig[1]<-limitn) |
sig[1]=-limitn; |
Mm->storeother(ipp, ido, epsp.n, epsp.a); |
sig[0]=eps[0]*slip; |
if (sig[0]>limits) |
sig[0]=limits; |
if (sig[0]<-limits) |
sig[0]=-limits; |
*/ |
for (i=0;i<n;i++){ |
Mm->ip[ipp].stress[i]=sig[i]; |
} |
} |
void contactmat::changeparam (atsel &atm,vector &val) |
{ |
long i; |
142,23 → 146,27 |
} |
} |
/** |
function copies array other to the array eqother |
The function copies array other to the array eqother. |
@param ipp - number of integration point |
@param im - index of material type |
@param ido - index in array other |
@param[in] ipp - number of integration point |
@param[in] im - index of material type |
@param[in] ido - index in array other |
*/ |
void contactmat::updateval (long ipp, long im, long ido) |
{ |
long i,n = Mm->givencompeqother(ipp, im); |
long i, n = Mm->givencompeqother(ipp, im); |
for (i=0;i<n;i++){ |
Mm->ip[ipp].eqother[ido+i]=Mm->ip[ipp].other[ido+i]; |
Mm->ip[ipp].eqother[ido+i] = Mm->ip[ipp].other[ido+i]; |
} |
} |
long contactmat::sgn (double a) |
{ |
long b; |
/trunk/SIFEL/MEFEL/SRC/contactmat.h |
---|
35,7 → 35,10 |
double limits; |
/// limit force in normal direction |
double limitn; |
/// limit elastic strain in the slip direction |
double eps_slip_lim; |
/// limit elastic strain in the direction orthogonal to slip |
double eps_norm_lim; |
}; |
#endif |
/trunk/SIFEL/MEFEL/SRC/damplastifacemat.cpp |
---|
85,10 → 85,13 |
Created by Tomas Koudelka, koudelka@cml.fsv.cvut.cz, 17.12.2015 |
*/ |
void damplastifacemat::elmatstiff(matrix &d,long /*ipp*/) |
void damplastifacemat::elmatstiff(matrix &d, long ipp) |
{ |
d(0,0) = ks; |
d(1,1) = kn; |
long i, nc = Mm->ip[ipp].ncompstr; |
for (i=0; i<nc-1; i++){ |
d(i,i) = ks; |
} |
d(nc-1,nc-1) = kn; |
} |
106,6 → 109,7 |
*/ |
void damplastifacemat::matstiff(matrix &d,long ipp,long ido) |
{ |
long i, nc = Mm->ip[ipp].ncompstr; |
double omega; |
switch (Mp->nlman->stmat) |
121,10 → 125,12 |
omega=Mm->ip[ipp].eqother[ido+1]; |
if (omega > 0.999999) |
omega = 0.999999; |
d(1,1) *= (1-omega); |
d(nc-1,nc-1) *= (1-omega); |
// if plasticity has evolved (actual gamma - previous gamma > 0) then reduce shear stiffness |
if (Mm->ip[ipp].other[ido+3] - Mm->ip[ipp].eqother[ido+3] > 0.0) |
d(0,0) *= 0.001; |
if (Mm->ip[ipp].other[ido+3] - Mm->ip[ipp].eqother[ido+3] > 0.0){ |
for (i=0; i<nc-1; i++) |
d(i,i) *= 0.001; |
} |
break; |
default: |
print_err("unknown type of stifness matrix is required", __FILE__, __LINE__, __func__); |
149,29 → 155,53 |
{ |
long i, nc = Mm->ip[ipp].ncompstr; |
double omega, w, kappa, aft; |
double gamma, dup; |
vector sigma(ASTCKVEC(nc)), dd(ASTCKVEC(nc)); |
double gamma, dup, epst, tau; |
vector sigma(ASTCKVEC(nc)), dd(ASTCKVEC(nc)), dds(ASTCKVEC(nc-1)); |
vector sepst(ASTCKVEC(nc-1)), sepsp(ASTCKVEC(nc-1)), dsepsp(ASTCKVEC(nc-1)), aux; |
// restore actual relative displacements |
for(i=0; i<nc; i++) |
// restore actual relative displacements and irreversible relative shear displacements sepsp |
for(i=0; i<nc; i++){ |
dd(i) = Mm->ip[ipp].strain[i]; |
if (i<nc-1){ |
dds(i) = dd(i); |
sepsp(i) = Mm->ip[ipp].eqother[ido+4+i]; |
} |
} |
// calculate trial increment of relative displacements in slip directions, sepst |
subv(dds, sepsp, sepst); |
epst = normv(sepst); |
// restore state variables |
kappa = Mm->ip[ipp].eqother[ido+0]; |
omega = Mm->ip[ipp].eqother[ido+1]; |
w = Mm->ip[ipp].eqother[ido+2]; |
gamma = Mm->ip[ipp].eqother[ido+3]; |
dup = Mm->ip[ipp].eqother[ido+4]; |
// actual tensile strength |
aft = Mm->give_actual_ft(ipp); |
// first calculate normal stress component that will be used in the yield condition for the shear stress component |
sigma(1) = compute_normal_stress(dd(1), aft, kappa, omega, w); |
sigma(nc-1) = compute_normal_stress(dd(nc-1), aft, kappa, omega, w); |
// calculate shear stress component |
sigma(0) = compute_shear_stress(dd(0), aft, omega, kappa, sigma(1), dup, gamma); |
// calculate shear stress in the actual shear direction |
dup = 0.0; |
tau = compute_shear_stress(epst, aft, omega, kappa, sigma(nc-1), dup, gamma); |
// calculate base vector of the actual shear direction -> sepst |
if (fabs(epst) > Mp->zero) |
cmulv(1.0/epst, sepst); |
else |
nullv(sepst); |
// calculate increments of plastic shear components |
cmulv(dup, sepst, dsepsp); |
addv(sepsp, dsepsp, sepsp); |
// calcualte shear stress components |
makerefv(aux, sigma.a, nc-1); |
cmulv(tau, sepst, aux); |
// save actual stresses |
Mm->storestress(0, ipp, sigma); |
180,7 → 210,8 |
Mm->ip[ipp].other[ido+1] = omega; |
Mm->ip[ipp].other[ido+2] = w; |
Mm->ip[ipp].other[ido+3] = gamma; |
Mm->ip[ipp].other[ido+4] = dup; |
for(i=0; i<nc-1; i++) |
Mm->ip[ipp].other[ido+4+i] = sepsp(i); |
} |
268,9 → 299,12 |
sig = (1.0-omega)*kn*dv; |
w = omega*dv; |
} |
else // unloading/reloading |
sig = (1.0-omega)*kn*dv; |
else{ // unloading/reloading/compression |
if (dv >= 0.0) // unloading/reloading in tension |
sig = (1.0-omega)*kn*dv; |
else // compression => no stiffness reduction |
sig = kn*dv; |
} |
return sig; |
} |
444,8 → 478,12 |
*/ |
void damplastifacemat::giveirrstrains(long ipp, long ido, vector &ddp) |
{ |
ddp(0) = 0.0; |
ddp(1) = Mm->ip[ipp].eqother[ido+4]; |
long i, nc = Mm->ip[ipp].ncompstr; |
for(i=0; i<nc-1; i++){ |
ddp(i) = Mm->ip[ipp].eqother[ido+4+i]; |
} |
ddp(nc-1) = 0.0; |
} |
/trunk/SIFEL/MEFEL/SRC/dloadcase.cpp |
---|
845,6 → 845,44 |
/** |
Function returns macro-stress %vector. |
@param[in] time - actual time |
@param[out] msig - required macro-stress %vector in Voigt notation. |
@return The function returns the value of macro-stress %vector in the argument msig. |
Created by Tomas Koudelka, 09.2023 |
*/ |
void dloadcase::get_macrostre(double time, vector &msig) |
{ |
double a; |
long i, j; |
switch (tdl) |
{ |
case timeindload: |
nullv(msig); |
for (i=0; i<nslc; i++) |
{ |
// scale factor |
a=gf[i].getval(time); |
for (j=0; j<msig.n; j++){ |
// assembling of contributions |
if (slc[i].mstrastre[j] == stress) |
msig(j) += slc[i].mstress[j]*a; |
} |
} |
default:{ |
print_err("this type of load case is not supported for the macro-stress", __FILE__, __LINE__, __func__); |
abort(); |
} |
} |
} |
/** |
Function returns cn-th component of macro-strain. |
@param time - actual time |
863,8 → 901,7 |
switch (tdl) |
{ |
case timeindload: |
for (i=0; i<nslc; i++) |
{ |
for (i=0; i<nslc; i++){ |
// scale factor |
a=gf[i].getval(time); |
// assembling of contributions |
882,6 → 919,43 |
/** |
Function returns cn-th component of macro-strain. |
@param time - actual time |
@param cn - component number |
@return The function returns the value of macro-strain component. |
Created by Tomas Koudelka, 16.2.2015 |
*/ |
void dloadcase::get_macrostra(double time, vector &meps) |
{ |
double a; |
long i, j; |
switch (tdl) |
{ |
case timeindload: |
nullv(meps); |
for (i=0; i<nslc; i++){ |
// scale factor |
a=gf[i].getval(time); |
for(j=0; j<meps.n; j++){ |
// assembling of contributions |
if (slc[i].mstrastre[j] == strain) |
meps(j) += slc[i].mstrain[j]*a; |
} |
} |
default:{ |
print_err("this type of load case is not supported for the macro-stress", __FILE__, __LINE__, __func__); |
abort(); |
} |
} |
} |
/** |
Function computes contributions from temperature changes |
to the nodal forces. |
/trunk/SIFEL/MEFEL/SRC/dloadcase.h |
---|
55,9 → 55,15 |
/// returns total value of macro-strain component at the given time |
double get_macrostre(double time, long dof); |
/// returns total value of macro-strain %vector at the given time |
void get_macrostre(double time, vector &meps); |
/// returns total value of macro-stress component at the given time |
double get_macrostra(double time, long dof); |
/// returns total value of macro-stress %vector at the given time |
void get_macrostra(double time, vector &msig); |
/// assembles right hand side of the given load case, only temperature loads are taken into account |
void tempercontrib (long lcid,double *rhs,long n,double t); |
/trunk/SIFEL/MEFEL/SRC/elastisomat.cpp |
---|
659,7 → 659,8 |
// volumetric strain rate |
//Mm->ip[ipp].other[ido+1] = (epsv - Mm->ip[ipp].eqother[ido+0])/dtime; |
// the volumetric strain rate is computed via generalized trapesoidal rule |
Mm->ip[ipp].other[ido+1] = 0.5*((epsv - Mm->ip[ipp].eqother[ido+0])/dtime + Mm->ip[ipp].eqother[ido+1]); |
if (dtime > 0.0) |
Mm->ip[ipp].other[ido+1] = 0.5*((epsv - Mm->ip[ipp].eqother[ido+0])/dtime + Mm->ip[ipp].eqother[ido+1]); |
} |
/** |
/trunk/SIFEL/MEFEL/SRC/element.cpp |
---|
144,6 → 144,7 |
case linearhexrot:{ if (Lhexrot==NULL) Lhexrot = new linhexrot; break; } |
case linearwed:{ if (Lwed==NULL) Lwed = new linwedge; break; } |
case quadrwed:{ if (Qwed==NULL) Qwed = new quadwedge; break; } |
case hexintface:{ if (Hexifc==NULL) Hexifc = new hexinterface; break; } |
case particleelem:{ |
if (Pelem==NULL){ |
long nne,dim; |
218,6 → 219,7 |
case linearhexrot:{ get=linhexa; break; } |
case linearwed:{ break; } |
case quadrwed:{ break; } |
case hexintface:{ break; } |
case particleelem:{ break; } |
case tetralatt:{ break; } |
default:{ |
/trunk/SIFEL/MEFEL/SRC/elemhead.h |
---|
49,5 → 49,6 |
#include "quadrilatkirch.h" |
#include "dkq.h" |
#include "tetralattice.h" |
#include "hexiface.h" |
#endif |
/trunk/SIFEL/MEFEL/SRC/elemswitch.cpp |
---|
232,6 → 232,7 |
case lineartet:{ |
Ltet->res_ip_strains (lcid,i); |
break; |
} |
256,6 → 257,11 |
break; |
} |
case hexintface:{ |
Hexifc->res_mainip_strains(lcid, i); |
break; |
} |
case particleelem:{ |
break; |
} |
585,7 → 591,10 |
Lhexrot->res_ip_strains (lcid,i); |
break; |
} |
case hexintface:{ |
Hexifc->res_mainip_strains(lcid, i); |
break; |
} |
case particleelem:{ |
break; |
} |
848,7 → 857,10 |
Lhexrot->nod_strains_ip (lcid,i,0,0); |
break; |
} |
case hexintface:{ |
Hexifc->nod_strains_ip(lcid, i); |
break; |
} |
case particleelem:{ |
break; |
} |
1399,6 → 1411,10 |
Lhexrot->res_ip_stresses (lcid,i); |
break; |
} |
case hexintface:{ |
Hexifc->res_mainip_stresses(lcid, i); |
break; |
} |
case particleelem:{ |
break; |
1881,6 → 1897,10 |
Lhexrot->nod_stresses_ip (lcid,i,0,0); |
break; |
} |
case hexintface:{ |
Hexifc->nod_stresses_ip(lcid, i); |
break; |
} |
case particleelem:{ |
break; |
} |
2367,6 → 2387,10 |
Lhexrot->intpointval (eid,nodval,ipval); |
break; |
} |
case hexintface:{ |
Hexifc->intpointval(eid, nodval, ipval); |
break; |
} |
default:{ |
print_err("unknown element type is required", __FILE__, __LINE__, __func__); |
2876,6 → 2900,9 |
Lhexrot->ipvolume (i,0,0); |
break; |
} |
case hexintface:{ |
break; |
} |
default: |
print_err("unknown element type is required", __FILE__, __LINE__, __func__); |
3087,6 → 3114,10 |
Lhexrot->res_internal_forces (lcid,i,ifor); |
break; |
} |
case hexintface:{ |
Hexifc->res_internal_forces(lcid, i, ifor); |
break; |
} |
case particleelem:{ |
3226,6 → 3257,7 |
break; |
} |
case planequadinterface:{ |
Pqifc->compute_nlstress(lcid, i, 0, 0); |
break; |
} |
case cctel:{ |
3295,6 → 3327,10 |
Lhexrot->compute_nlstress(lcid, i, 0, 0); |
break; |
} |
case hexintface:{ |
Hexifc->compute_nlstress(lcid, i, 0, 0); |
break; |
} |
case particleelem: |
break; |
3447,6 → 3483,9 |
Lhexrot->local_values(lcid, i, 0, 0); |
break; |
} |
case hexintface:{ |
break; |
} |
case particleelem: |
break; |
3562,7 → 3601,6 |
} |
case planequadinterface:{ |
Pqifc->res_internal_forces (lcid,i,ifor); |
break; |
} |
3635,6 → 3673,9 |
Lhexrot->res_nonloc_internal_forces (lcid,i,ifor); |
break; |
} |
case hexintface:{ |
break; |
} |
case particleelem:{ |
break; |
3807,6 → 3848,9 |
Lhexrot->res_incr_internal_forces (lcid,i,ifor); |
break; |
} |
case hexintface:{ |
break; |
} |
/* |
case particleelem:{ |
3946,6 → 3990,9 |
Lhexrot->res_eigstrain_forces (lcid,eid,nfor); |
break; |
} |
case hexintface:{ |
break; |
} |
case spring_1: |
case spring_2: |
case spring_3: |
4179,6 → 4226,10 |
Qwed->res_stiffness_matrix (eid,sm); |
break; |
} |
case hexintface:{ |
Hexifc->res_stiffness_matrix (eid, sm); |
break; |
} |
case particleelem:{ |
Pelem->res_stiffness_matrix (eid,sm); |
4896,6 → 4947,10 |
Qwed->transf_matrix(enodes, tmat); |
break; |
} |
case hexintface:{ |
Hexifc->transf_matrix(enodes, tmat); |
break; |
} |
default: |
print_err("unknown element type is required", __FILE__, __LINE__, __func__); |
} |
5221,6 → 5276,11 |
Qhex->ipcoord (eid,ipp,ri,ci,ipcoord); |
break; |
} |
case hexintface:{ |
Hexifc->ipcoord(eid,ipp, ri, ci, ipcoord); |
break; |
} |
default:{ |
print_err("unknown element type is required", __FILE__, __LINE__, __func__); |
} |
/trunk/SIFEL/MEFEL/SRC/generalmod.cpp |
---|
24,6 → 24,8 |
#include <string.h> |
#include "generalmod.h" |
using namespace std; |
/** |
The function calculates increments of net stress, Sr and state variables dqstatev based on their |
initial values and increments of strains, pore fluid pressures and temperature. Sign convention: compression negative for stresses, strains and pressures. |
/trunk/SIFEL/MEFEL/SRC/generalmod.h |
---|
1,203 → 1,203 |
/* |
Copyright (C) 2003 David Masin |
email: masin@natur.cuni.cz |
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2 of the License, or |
(at your option) any later version. |
This program is distributed in the hope that it will be useful, |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
GNU General Public License for more details. |
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software Foundation |
59 Temple Place, Suite 330, Boston, MA, 02111-1307, USA |
The use of the program is subject to acknowledgement. |
*/ |
#ifndef GENERALMOD_H |
#define GENERALMOD_H |
#include <iostream> |
#include <cmath> |
#include <cstdlib> |
#include "errno.h" |
#ifndef max2 |
#define max2(a,b) ((a)>(b)?(a):(b)) |
#endif |
#ifndef min2 |
#define min2(a,b) ((a)<(b)?(a):(b)) |
#endif |
using namespace std; |
/*****************************General model, main structure***************************************/ |
struct General_model { |
//Numbers of variables |
int nparms, nstatev, ngstrain, ngstress, voidrat_index, Sr_index; |
static const int max_ngstrain = 8; |
static const int max_ngstress = 7; |
static const int max_nstatev = 20; |
static const int max_nparms = 40; |
static const int nrkf_parms = 5; |
static const int nrkf_statev = 4; |
bool debug; |
General_model(int np, int ns, int ngstra, int ngstre, int vri, int Sri) : nparms(np), nstatev(ns), ngstrain(ngstra), ngstress(ngstre), voidrat_index(vri), Sr_index(Sri) {}; |
//Updated soil_model with Runge-Kutta schemes |
virtual long soil_model(double strain_gen[], double stress_gen[], double qstatev[], |
double dstrain_gen[], double dtime, double *DDtan_gen, double parms[], double rkf_statev[], double rkf_parms[], int flag, int kinc=0, int ipp=0) = 0; |
virtual bool calc_fsigq(double signet[9], double suction, double Temper, double *qstatev, |
double deps[9], double dsuction, double dTemper, double dtime, |
double dsignet[9], double &Sr_new, double dqstatev[], int kinc) = 0; |
//Functions for general stress-full 9x9 convention conversion |
void convert_from_general(double general[], double stressstrain[], double othervar[], int nothv, int flag); |
void convert_to_general(double general[], double stressstrain[], double othervar[], int nothv, int flag); |
void convert4th_to_abaqus(double DDfull[3][3][3][3], double DDabq[6][6]); |
void map_indices_fulltoabq(int fulli, int fullj, int &abq); |
void map_indices_abqtofull(int &fulli, int &fullj, int abq); |
//Functions for mathematical operations |
double gscalar_power(double a, double b); |
double gscalar_dabs(double k); |
void garray_set(double *ptr, double value, long int n); |
double garray_size(double a[], long int n); |
void garray_move(double from[], double to[], long int n); |
int garray_copy (double source[], double destination[], int length); |
int garray_rcopy (double source[], int source_index, double destination[], int destination_index, int number_of_elements); |
void garray_add(double a[], double b[], double c[], long int n); |
void garray_subtract (double a[], double b[], double c[], long int n); |
void garray_multiply(double a[], double b[], double c, long int n); |
int garray_addmult (double source1[], double source2[], double multiplier, double destination[], int length); |
int garray_swap (double a[], double b[], int length); |
double garray_snorm(double a[], long fi, long nc); |
double garray_inproduct(double a[], double b[], long int n); |
double gtrace(double a[3][3]); |
double gmatrix_determinant(double a[], long int n); |
void gmatrix_ab(double *a, double *b, double *c, long int n, long int m, long int k); |
void gmatrix_a4b(double a[3][3][3][3], double b[], double c[]); |
double tensor_dbldot_prod (double a[], double b[], double k); |
double round_to_digits(double value, int digits); |
long test_math_err(); |
//Runge-Kutta schemes (functions adapted from SIFEL) |
long calc_rkf(double strain_gen[], double stress_gen[], double qstatev[], double dstrain_gen[], double dtime, |
double parms[], double rkf_statev[], double rkf_parms[], int kinc); |
long adfwdeuler (double strain_gen[], double stress_gen[], double qstatev[], double dstrain_gen[], double dtime, |
double parms[], double rkf_statev[], double rkf_parms[], int kinc); |
long rkf23 (double strain_gen[], double stress_gen[], double qstatev[], double dstrain_gen[], double dtime, |
double parms[], double rkf_statev[], double rkf_parms[], int kinc); |
long rkf23bs (double strain_gen[], double stress_gen[], double qstatev[], double dstrain_gen[], double dtime, |
double parms[], double rkf_statev[], double rkf_parms[], int kinc); |
long rkf34 (double strain_gen[], double stress_gen[], double qstatev[], double dstrain_gen[], double dtime, |
double parms[], double rkf_statev[], double rkf_parms[], int kinc); |
long rkf45 (double strain_gen[], double stress_gen[], double qstatev[], double dstrain_gen[], double dtime, |
double parms[], double rkf_statev[], double rkf_parms[], int kinc); |
long fwdeulerfsub (double strain_gen[], double stress_gen[], double qstatev[], double dstrain_gen[], double dtime, |
double parms[], double rkf_statev[], double rkf_parms[], int kinc); |
//Additional routines |
long rkf_redstep (double rc, double &h, double hmin); |
long check_math_error(); |
virtual long correct_statev_values(double strain_gen[], double stress_gen[], double qstatev[], double dstrain_gen[], int call) = 0; |
virtual long correct_DDtan_gen(double strain_gen[], double stress_gen[], double *DDtan_gen) = 0; |
}; |
/****************** Hypoplasticity for unsaturated soils, expansive soils with *******************/ |
/****************** double-porosity structure, thermal effects. Updated version ***********************************/ |
struct Hypoplasti_unsat_expansive_thermal : General_model { |
Hypoplasti_unsat_expansive_thermal() : General_model(c_nparms, c_nstatev, c_ngstrain, c_ngstress, c_voidrat_index, c_Sr_index){}; |
static const int c_ngstrain = 8; |
static const int c_ngstress = 7; |
static const int c_nstatev = 9; |
static const int c_nparms = 23; |
static const int c_voidrat_index = 0; |
static const int c_Sr_index = 2; |
static const bool debug = false; |
//Model parameters and other constants |
double phic, lambda, kappa, N, nuparam, Ocparam; |
double nparam, lparam, nTparam, lTparam, mparam; |
double alpha_s, kappam, smstar, emstar, mmparam, csh; |
double sairentry0, eM0, Trparam, aTparam, bTparam; |
double lambdap0, aer, pt, alphaG, alphanu, alphaE; |
double rlambdascan; |
//Updated soil_model with Runge-Kutta schemes |
long soil_model(double strain_gen[], double stress_gen[], double qstatev[], |
double dstrain_gen[], double dtime, double *DDtan_gen, double parms[], double rkf_statev[], double rkf_parms[], int flag, int kinc=0, int ipp=0); |
/* functions which distinguish original and updated versions */ |
virtual double give_rlambda(double suction, double a_scan, double dsuction, double sewM, double SrM, double& rlambda_for_ascan, double& rlambda_for_se); |
virtual void give_fm(double& fm, double& fm_lambda_act, double suction, double sewM, double re, bool swelling); |
virtual double give_demdpm(double pefsat, double em); |
virtual double init_em_pefsat(double pefsat); |
//Model-specific routines |
void initialise_variables(double strain_gen[], double stress_gen[], double qstatev[], double dstrain_gen[], double dtime, |
double parms[], int kinc); |
void initialise_parameters(double parms[]); |
bool calc_fsigq(double signet[9], double suction, double Temper, double *qstatev, |
double deps[9], double dsuction, double dTemper, double dtime, |
double dsignet[9], double &Sr_new, double dqstatev[], int kinc); |
void update_hisv(double signet[9], double suction, double Temper, double *qstatev, |
double deps[9], double dsuction, double dTemper, |
double dsignet[9], double &Sr, double *dqstatev, int flag, double fu, int kinc); |
void make_sig_unsat(double sig[3*3], double suction, double SrM, |
double tensor_unsat[3*3], double &scalar_unsat); |
double calc_trdepm(double signet[9], double suction, double Temper, double em, double dsuction, |
double dTemper, double dsignet[9], double fu); |
void calc_N_lambda_dpeds(double &Nuse, double &lambda_use, double &dpeds_divpe, double &dpedT_divpe, |
double signet[9], double suction, double Temper, double *qstatev); |
void give_LNH(double signet[9], double dsuction, double Temper, double qstatev[], |
double hypo_L[3][3][3][3], double hypo_N[3][3], double H_unsat[3][3], double HT_unsat[3][3], bool swelling, |
double &fu); |
void direct_stiffness_matrix(double strain_gen[], double stress_gen[], double qstatev[], double dstrain_gen[], double dtime, double *DDtan_gen, double parms[], int kinc, int flag); |
double give_SrM_new(double suction, double SrM, double eM, double Temper, double sewM, double se, double dsuction, double deM, double dTemper, double a_scan, int flag); |
//Additional routines |
long correct_statev_values(double strain_gen[], double stress_gen[], double qstatev[], double dstrain_gen[], int call); |
long correct_DDtan_gen(double strain_gen[], double stress_gen[], double *DDtan_gen); |
}; |
/****************** Hypoplasticity for unsaturated soils, expansive soils with *******************/ |
/****************** double-porosity structure, thermal effects. ***********************************/ |
/* Version "Mašín, D. (2017). Coupled thermohydromechanical double structure model for expansive soils. ASCE Journal of Engineering Mechanics 143, No. 9." |
*/ |
struct Hypoplasti_unsat_expansive_thermal_2017 : Hypoplasti_unsat_expansive_thermal { |
Hypoplasti_unsat_expansive_thermal_2017() : Hypoplasti_unsat_expansive_thermal(){}; |
/* functions which distinguish original and updated versions */ |
virtual double give_rlambda(double suction, double a_scan, double dsuction, double sewM, double SrM, double& rlambda_for_ascan, double& rlambda_for_se); |
virtual void give_fm(double& fm, double& fm_lambda_act, double suction, double sewM, double re, bool swelling); |
}; |
/****************** Hypoplasticity for unsaturated soils, expansive soils with *******************/ |
/****************** double-porosity structure, thermal effects. ***********************************/ |
/* Version "Svoboda, J., Mašín, D., Najser, J. Vašíček, R., Hanusová, I. and Hausmannová, L. (2022). BCV bentonite hydromechanical behaviour and modelling. Acta Geotechnica (in print). |
" |
*/ |
struct Hypoplasti_unsat_expansive_thermal_2022 : Hypoplasti_unsat_expansive_thermal { |
Hypoplasti_unsat_expansive_thermal_2022() : Hypoplasti_unsat_expansive_thermal(){}; |
/* functions which distinguish original and updated versions */ |
virtual double give_rlambda(double suction, double a_scan, double dsuction, double sewM, double SrM, double& rlambda_for_ascan, double& rlambda_for_se); |
virtual void give_fm(double& fm, double& fm_lambda_act, double suction, double sewM, double re, bool swelling); |
}; |
#endif |
/* |
Copyright (C) 2003 David Masin |
email: masin@natur.cuni.cz |
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2 of the License, or |
(at your option) any later version. |
This program is distributed in the hope that it will be useful, |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
GNU General Public License for more details. |
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software Foundation |
59 Temple Place, Suite 330, Boston, MA, 02111-1307, USA |
The use of the program is subject to acknowledgement. |
*/ |
#ifndef GENERALMOD_H |
#define GENERALMOD_H |
#include <iostream> |
#include <cmath> |
#include <cstdlib> |
#include "errno.h" |
#ifndef max2 |
#define max2(a,b) ((a)>(b)?(a):(b)) |
#endif |
#ifndef min2 |
#define min2(a,b) ((a)<(b)?(a):(b)) |
#endif |
//using namespace std; |
/*****************************General model, main structure***************************************/ |
struct General_model { |
//Numbers of variables |
int nparms, nstatev, ngstrain, ngstress, voidrat_index, Sr_index; |
static const int max_ngstrain = 8; |
static const int max_ngstress = 7; |
static const int max_nstatev = 20; |
static const int max_nparms = 40; |
static const int nrkf_parms = 5; |
static const int nrkf_statev = 4; |
bool debug; |
General_model(int np, int ns, int ngstra, int ngstre, int vri, int Sri) : nparms(np), nstatev(ns), ngstrain(ngstra), ngstress(ngstre), voidrat_index(vri), Sr_index(Sri) {}; |
//Updated soil_model with Runge-Kutta schemes |
virtual long soil_model(double strain_gen[], double stress_gen[], double qstatev[], |
double dstrain_gen[], double dtime, double *DDtan_gen, double parms[], double rkf_statev[], double rkf_parms[], int flag, int kinc=0, int ipp=0) = 0; |
virtual bool calc_fsigq(double signet[9], double suction, double Temper, double *qstatev, |
double deps[9], double dsuction, double dTemper, double dtime, |
double dsignet[9], double &Sr_new, double dqstatev[], int kinc) = 0; |
//Functions for general stress-full 9x9 convention conversion |
void convert_from_general(double general[], double stressstrain[], double othervar[], int nothv, int flag); |
void convert_to_general(double general[], double stressstrain[], double othervar[], int nothv, int flag); |
void convert4th_to_abaqus(double DDfull[3][3][3][3], double DDabq[6][6]); |
void map_indices_fulltoabq(int fulli, int fullj, int &abq); |
void map_indices_abqtofull(int &fulli, int &fullj, int abq); |
//Functions for mathematical operations |
double gscalar_power(double a, double b); |
double gscalar_dabs(double k); |
void garray_set(double *ptr, double value, long int n); |
double garray_size(double a[], long int n); |
void garray_move(double from[], double to[], long int n); |
int garray_copy (double source[], double destination[], int length); |
int garray_rcopy (double source[], int source_index, double destination[], int destination_index, int number_of_elements); |
void garray_add(double a[], double b[], double c[], long int n); |
void garray_subtract (double a[], double b[], double c[], long int n); |
void garray_multiply(double a[], double b[], double c, long int n); |
int garray_addmult (double source1[], double source2[], double multiplier, double destination[], int length); |
int garray_swap (double a[], double b[], int length); |
double garray_snorm(double a[], long fi, long nc); |
double garray_inproduct(double a[], double b[], long int n); |
double gtrace(double a[3][3]); |
double gmatrix_determinant(double a[], long int n); |
void gmatrix_ab(double *a, double *b, double *c, long int n, long int m, long int k); |
void gmatrix_a4b(double a[3][3][3][3], double b[], double c[]); |
double tensor_dbldot_prod (double a[], double b[], double k); |
double round_to_digits(double value, int digits); |
long test_math_err(); |
//Runge-Kutta schemes (functions adapted from SIFEL) |
long calc_rkf(double strain_gen[], double stress_gen[], double qstatev[], double dstrain_gen[], double dtime, |
double parms[], double rkf_statev[], double rkf_parms[], int kinc); |
long adfwdeuler (double strain_gen[], double stress_gen[], double qstatev[], double dstrain_gen[], double dtime, |
double parms[], double rkf_statev[], double rkf_parms[], int kinc); |
long rkf23 (double strain_gen[], double stress_gen[], double qstatev[], double dstrain_gen[], double dtime, |
double parms[], double rkf_statev[], double rkf_parms[], int kinc); |
long rkf23bs (double strain_gen[], double stress_gen[], double qstatev[], double dstrain_gen[], double dtime, |
double parms[], double rkf_statev[], double rkf_parms[], int kinc); |
long rkf34 (double strain_gen[], double stress_gen[], double qstatev[], double dstrain_gen[], double dtime, |
double parms[], double rkf_statev[], double rkf_parms[], int kinc); |
long rkf45 (double strain_gen[], double stress_gen[], double qstatev[], double dstrain_gen[], double dtime, |
double parms[], double rkf_statev[], double rkf_parms[], int kinc); |
long fwdeulerfsub (double strain_gen[], double stress_gen[], double qstatev[], double dstrain_gen[], double dtime, |
double parms[], double rkf_statev[], double rkf_parms[], int kinc); |
//Additional routines |
long rkf_redstep (double rc, double &h, double hmin); |
long check_math_error(); |
virtual long correct_statev_values(double strain_gen[], double stress_gen[], double qstatev[], double dstrain_gen[], int call) = 0; |
virtual long correct_DDtan_gen(double strain_gen[], double stress_gen[], double *DDtan_gen) = 0; |
}; |
/****************** Hypoplasticity for unsaturated soils, expansive soils with *******************/ |
/****************** double-porosity structure, thermal effects. Updated version ***********************************/ |
struct Hypoplasti_unsat_expansive_thermal : General_model { |
Hypoplasti_unsat_expansive_thermal() : General_model(c_nparms, c_nstatev, c_ngstrain, c_ngstress, c_voidrat_index, c_Sr_index){}; |
static const int c_ngstrain = 8; |
static const int c_ngstress = 7; |
static const int c_nstatev = 9; |
static const int c_nparms = 23; |
static const int c_voidrat_index = 0; |
static const int c_Sr_index = 2; |
static const bool debug = false; |
//Model parameters and other constants |
double phic, lambda, kappa, N, nuparam, Ocparam; |
double nparam, lparam, nTparam, lTparam, mparam; |
double alpha_s, kappam, smstar, emstar, mmparam, csh; |
double sairentry0, eM0, Trparam, aTparam, bTparam; |
double lambdap0, aer, pt, alphaG, alphanu, alphaE; |
double rlambdascan; |
//Updated soil_model with Runge-Kutta schemes |
long soil_model(double strain_gen[], double stress_gen[], double qstatev[], |
double dstrain_gen[], double dtime, double *DDtan_gen, double parms[], double rkf_statev[], double rkf_parms[], int flag, int kinc=0, int ipp=0); |
/* functions which distinguish original and updated versions */ |
virtual double give_rlambda(double suction, double a_scan, double dsuction, double sewM, double SrM, double& rlambda_for_ascan, double& rlambda_for_se); |
virtual void give_fm(double& fm, double& fm_lambda_act, double suction, double sewM, double re, bool swelling); |
virtual double give_demdpm(double pefsat, double em); |
virtual double init_em_pefsat(double pefsat); |
//Model-specific routines |
void initialise_variables(double strain_gen[], double stress_gen[], double qstatev[], double dstrain_gen[], double dtime, |
double parms[], int kinc); |
void initialise_parameters(double parms[]); |
bool calc_fsigq(double signet[9], double suction, double Temper, double *qstatev, |
double deps[9], double dsuction, double dTemper, double dtime, |
double dsignet[9], double &Sr_new, double dqstatev[], int kinc); |
void update_hisv(double signet[9], double suction, double Temper, double *qstatev, |
double deps[9], double dsuction, double dTemper, |
double dsignet[9], double &Sr, double *dqstatev, int flag, double fu, int kinc); |
void make_sig_unsat(double sig[3*3], double suction, double SrM, |
double tensor_unsat[3*3], double &scalar_unsat); |
double calc_trdepm(double signet[9], double suction, double Temper, double em, double dsuction, |
double dTemper, double dsignet[9], double fu); |
void calc_N_lambda_dpeds(double &Nuse, double &lambda_use, double &dpeds_divpe, double &dpedT_divpe, |
double signet[9], double suction, double Temper, double *qstatev); |
void give_LNH(double signet[9], double dsuction, double Temper, double qstatev[], |
double hypo_L[3][3][3][3], double hypo_N[3][3], double H_unsat[3][3], double HT_unsat[3][3], bool swelling, |
double &fu); |
void direct_stiffness_matrix(double strain_gen[], double stress_gen[], double qstatev[], double dstrain_gen[], double dtime, double *DDtan_gen, double parms[], int kinc, int flag); |
double give_SrM_new(double suction, double SrM, double eM, double Temper, double sewM, double se, double dsuction, double deM, double dTemper, double a_scan, int flag); |
//Additional routines |
long correct_statev_values(double strain_gen[], double stress_gen[], double qstatev[], double dstrain_gen[], int call); |
long correct_DDtan_gen(double strain_gen[], double stress_gen[], double *DDtan_gen); |
}; |
/****************** Hypoplasticity for unsaturated soils, expansive soils with *******************/ |
/****************** double-porosity structure, thermal effects. ***********************************/ |
/* Version "Mašín, D. (2017). Coupled thermohydromechanical double structure model for expansive soils. ASCE Journal of Engineering Mechanics 143, No. 9." |
*/ |
struct Hypoplasti_unsat_expansive_thermal_2017 : Hypoplasti_unsat_expansive_thermal { |
Hypoplasti_unsat_expansive_thermal_2017() : Hypoplasti_unsat_expansive_thermal(){}; |
/* functions which distinguish original and updated versions */ |
virtual double give_rlambda(double suction, double a_scan, double dsuction, double sewM, double SrM, double& rlambda_for_ascan, double& rlambda_for_se); |
virtual void give_fm(double& fm, double& fm_lambda_act, double suction, double sewM, double re, bool swelling); |
}; |
/****************** Hypoplasticity for unsaturated soils, expansive soils with *******************/ |
/****************** double-porosity structure, thermal effects. ***********************************/ |
/* Version "Svoboda, J., Mašín, D., Najser, J. Vašíček, R., Hanusová, I. and Hausmannová, L. (2022). BCV bentonite hydromechanical behaviour and modelling. Acta Geotechnica (in print). |
" |
*/ |
struct Hypoplasti_unsat_expansive_thermal_2022 : Hypoplasti_unsat_expansive_thermal { |
Hypoplasti_unsat_expansive_thermal_2022() : Hypoplasti_unsat_expansive_thermal(){}; |
/* functions which distinguish original and updated versions */ |
virtual double give_rlambda(double suction, double a_scan, double dsuction, double sewM, double SrM, double& rlambda_for_ascan, double& rlambda_for_se); |
virtual void give_fm(double& fm, double& fm_lambda_act, double suction, double sewM, double re, bool swelling); |
}; |
#endif |
/trunk/SIFEL/MEFEL/SRC/global.cpp |
---|
94,6 → 94,15 |
Neval = 0.0; |
Omp_wtime = 0.0; |
Elemfrc = NULL; |
//#ifndef INC_OPENMP |
// out = NULL; |
// out2 = NULL; |
// in = NULL; |
//#endif |
//#ifdef INC_OPENMP |
// out = NULL; |
// out2 = NULL; |
//#endif |
} |
174,10 → 183,20 |
delete Qwed; Qwed = NULL; |
delete Pelem; Pelem = NULL; |
delete Pqifc; Pqifc = NULL; |
delete Hexifc; Hexifc = NULL; |
delete Tlatt; Tlatt = NULL; |
delete [] Elemfrc; |
// #ifndef INC_OPENMP |
// fclose(in); |
// fclose(out); |
// fclose(out2); |
// #endif |
// #ifdef INC_OPENMP |
// fclose(out); |
// fclose(out2); |
// #endif |
Ndofm = Mespr = 0; |
} |
/trunk/SIFEL/MEFEL/SRC/global.h |
---|
34,6 → 34,7 |
#include "gtopology.h" |
#include "gmatrix.h" |
#include "elemhead.h" |
#include "vector.h" |
#else |
class gtopology; |
class gmatrix; |
89,6 → 90,7 |
class linhexrot; |
class linwedge; |
class quadwedge; |
class hexinterface; |
class elemparticle; |
class plquadinterface; |
class ArgyrisTriangle; |
314,6 → 316,7 |
// threedimensional quadratic wedge finite element |
EXTERN quadwedge *Qwed; |
EXTERN hexinterface *Hexifc; |
// element for particle computation |
EXTERN elemparticle *Pelem; |
332,6 → 335,17 |
// array of element internal force vectors Elemfrc[i][j] means j-th component of internal force vector of i-th element |
EXTERN vector *Elemfrc; |
// following variables are just for the debugging OpenMP |
//#ifndef INC_OPENMP |
//EXTERN FILE *out; |
//EXTERN FILE *out2; |
//EXTERN FILE *in; |
//#endif |
//#ifdef INC_OPENMP |
//EXTERN FILE *out; |
//EXTERN FILE *out2; |
//#endif |
/// function initializes all global variables to null values |
void initnull_glob (void); |
/trunk/SIFEL/MEFEL/SRC/globmat.cpp |
---|
509,25 → 509,23 |
ivector cn; |
int err; |
vector ifor, aifor; |
// vector r, mstr; |
// matrix bd, dd; |
// function computes strains at integration points |
if (Mp->strcomp) |
compute_ipstrains (lcid); |
#ifdef DEBUGELEMFRC |
if (Elemfrc == NULL){ |
Elemfrc = new vector[Mt->ne]; |
for (i=0; i<Mt->ne; i++){ |
ndofe = Mt->give_ndofe (i); |
ndofe = Mt->give_ndofe(i); |
reallocv(ndofe, Elemfrc[i]); |
} |
} |
#endif |
// number of elements |
long ne=Mt->ne; |
long ne=Mt->ne; |
ivector seq(ne); |
long g = 0; |
#ifdef INC_OPENMP |
543,9 → 541,12 |
num_threads(Numth),\ |
private(i, j, ndofe, ndofemn, eid, cn, err, ifor, aifor),\ |
firstprivate(ncomp) |
{ |
#pragma omp for reduction(+:mstresscomp[:6]) |
#ifdef __linux__ |
#pragma omp for reduction(+:mstresscomp[:6]) |
#else |
#pragma omp for |
#endif |
#endif |
for (i=0;i<ne;i++){ |
if (Gtm->leso[i]==1){ |
552,33 → 553,28 |
#ifdef INC_OPENMP |
//eid = Gtm->ompelord[i]; |
eid = i; |
// if (omp_get_thread_num() == 1) |
// std::this_thread::sleep_for(std::chrono::milliseconds(1)); |
#else |
eid = i; |
#endif |
// the number of DOFs on element |
// this number is equal to the number of DOFs without hanging nodes |
ndofe=Mt->give_ndofe (eid); |
reallocv (RSTCKVEC(ndofe,ifor)); |
// the number of DOFs on element |
// this number is equal to the number of DOFs without hanging nodes |
ndofe=Mt->give_ndofe (eid); |
reallocv (RSTCKVEC(ndofe,ifor)); |
elem_internal_forces (eid,lcid,ifor); |
elem_internal_forces (eid,lcid,ifor); |
err = check_math_errel(eid); |
err = check_math_errel(eid); |
if (err) |
{ |
abort(); |
} |
if (err) abort(); |
// the number of DOFs on element |
// this number is equal to the number of DOFs with master nodes generated by hanging nodes |
ndofemn = Gtm->give_ndofe (eid); |
reallocv (RSTCKIVEC(ndofemn,cn)); |
Mt->give_code_numbers (eid,cn.a); |
if (ndofe != ndofemn){ |
// the number of DOFs on element |
// this number is equal to the number of DOFs with master nodes generated by hanging nodes |
ndofemn = Gtm->give_ndofe (eid); |
reallocv (RSTCKIVEC(ndofemn,cn)); |
Mt->give_code_numbers (eid,cn.a); |
if (ndofe != ndofemn){ |
if (Mb->give_num_mstress_comp(lcid)){ |
// this case means homogenization with some prescribed macro-stress components |
if (ncomp == 0L) |
598,15 → 594,24 |
for (j=0; j<ncomp; j++){ |
if (mstress_cn[j]){ |
#ifdef INC_OPENMP |
mstresscomp[j] += ifor[j]; |
//#pragma omp atomic update |
// intfor[mstress_cn[j]-1] += ifor[j]; |
#else |
// OS dependent multithread code |
#ifdef __linux__ |
mstresscomp[j] += ifor[j]; // uses reduction clause for mstresscomp update in the #pragma for loop |
#else |
#pragma omp critical |
// Windows compiler does not support the latest array reduction clause in the for loop, |
// thus the critical section construct must be used |
{ |
mstresscomp[j] += ifor[j]; |
} |
#endif // end of OS dependent multithread code |
#else |
// sequential code |
intfor[mstress_cn[j]-1] += ifor[j]; |
#endif |
#endif |
} |
} |
} |
} |
else{ |
// this case means hanging nodes |
// the element contains hanging node |
613,26 → 618,44 |
// the stiffness matrix has to be transformed |
reallocv (RSTCKVEC(ndofemn,aifor)); |
mtxv (*Mt->elements[eid].tmat,ifor,aifor); |
locglob (intfor,aifor.a,cn.a,ndofemn); |
#if defined(INC_OPENMP) && defined(_WIN32) |
#pragma omp critical |
// Windows compiler do not support latest OpenMP versions with atomic construct, |
// thus the critical section must be used |
{ |
locglob(intfor, aifor.a, cn.a, ndofemn); |
} |
#else // in other cases atomic update of intfor is provided at the level of locglob procedure |
locglob (intfor,aifor.a,cn.a,ndofemn); |
#endif |
} |
} |
else{ |
// the element does not contain hanging node nor homogenization |
#ifdef INC_OPENMP |
#pragma omp critical |
#endif |
{ |
locglob (intfor,ifor.a,cn.a,ndofe); |
seq(i) = g++; |
#if defined(INC_OPENMP) && defined(_WIN32) |
#pragma omp critical |
// Windows compiler do not support latest OpenMP versions with atomic construct, |
// thus the critical section must be used. On Linux systems, the atomic update is provided in locglob. |
#endif |
{ |
locglob(intfor, ifor.a, cn.a, ndofe); |
} |
// the following code is for debugging of possible data races |
#if defined(INC_OPENMP) |
#pragma omp critical |
#endif |
{ |
g++; |
seq(i) = g; |
} |
} |
} |
} // end of leso test |
#ifdef DEBUGELEMFRC |
copyv(ifor, Elemfrc[i]); |
#endif |
} |
}// end element loop |
#ifdef INC_OPENMP |
} |
}// end of #pragma block |
ncomp = Mb->give_num_mstress_comp(lcid); |
if (ncomp){ // homogenization with macrostress approach was detected |
long *mstress_cn = Mb->give_mstress_cn(lcid); |
1781,18 → 1804,17 |
@param lcid - load case id |
@param cn - index of required macro-strain component |
@return The function returns macro-strain components in the argument mstra. |
@return The function returns the given macro-strain component. |
Created by Tomas Koudelka, 20.1.2015 |
*/ |
double macrostrains(long lcid, long cn) |
{ |
long ncomp = Mt->max_ncompstr; |
double *d; |
long ncomp = Mt->max_ncompstr; |
double ret = 0.0; |
long j; |
long *mstress_cn; |
strastre *mstrastre; |
double ret = 0.0; |
switch (Mp->homog){ |
case 3: |
1809,14 → 1831,12 |
if (Mb->dlc) |
ret = Mb->dlc[lcid].get_macrostra(Mp->time, cn); |
else{ |
for (j=0; j<Mb->nlc; j++){ |
if (Mp->tprob == mat_nonlinear_statics){ |
ret = Mb->lc[2*lcid].mstrain[cn]*Mp->lambda; |
ret += Mb->lc[2*lcid+1].mstrain[cn]; |
} |
else |
ret = Mb->lc[lcid].mstrain[cn]; |
if (Mp->tprob == mat_nonlinear_statics){ |
ret = Mb->lc[2*lcid].mstrain[cn]*Mp->lambda; |
ret += Mb->lc[2*lcid+1].mstrain[cn]; |
} |
else |
ret = Mb->lc[lcid].mstrain[cn]; |
} |
break; |
} |
1831,13 → 1851,88 |
if (Mb->dlc) |
ret = Mb->dlc[lcid].get_macrostra(Mp->time, cn); |
else{ |
for (j=0; j<Mb->nlc; j++){ |
if (Mp->tprob == mat_nonlinear_statics){ |
ret = Mb->lc[2*lcid].mstrain[cn]*Mp->lambda; |
ret += Mb->lc[2*lcid+1].mstrain[cn]; |
} |
else |
ret = Mb->lc[lcid].mstrain[cn]; |
} |
} |
break; |
default:{ |
print_err("unknown type of homogenization is required", __FILE__, __LINE__, __func__); |
abort(); |
} |
} |
return ret; |
} |
/** |
The function returns the macro-strain %vector in case of homogeniztaion problem. |
@param lcid - load case id |
@param meps - macro-strain %vector in Voigt notation |
@return The function returns macro-strain in the argument meps. |
Created by Tomas Koudelka, 09.2023 |
*/ |
void macrostrains(long lcid, vector &meps) |
{ |
long ncomp = Mt->max_ncompstr; |
double *d; |
long *mstress_cn; |
strastre *mstrastre; |
long i; |
switch (Mp->homog){ |
case 3: |
case 5: |
case 7: {// macro-stress approach - |
// components of the macro-strains are at last positions in the %vector of unknowns |
d = Lsrs->give_lhs(lcid); |
copyv(d+Ndofm-ncomp, meps); |
break; |
} |
case 4: |
case 6: |
case 8: { // macro-strain approach - macro-strains are defined in the particular load cases |
if (Mb->dlc) |
Mb->dlc[lcid].get_macrostra(Mp->time, meps); |
else{ |
if (Mp->tprob == mat_nonlinear_statics){ |
copyv(Mb->lc[2*lcid].mstrain, meps); |
cmulv(Mp->lambda, meps); |
vector aux; |
makerefv(aux, Mb->lc[2*lcid+1].mstrain, ncomp); |
addv(meps, aux, meps); |
} |
else |
copyv(Mb->lc[lcid].mstrain, meps); |
} |
break; |
} |
case 9: |
mstrastre = Mb->give_mstrastre(lcid); |
for(i=0; i<ncomp; i++){ |
if (mstrastre[i] == stress){// macro-stress has been applied in the i-th direction |
mstress_cn = Mb->give_mstress_cn(lcid); |
d = Lsrs->give_lhs(lcid); |
meps(i) = d[mstress_cn[i]-1]; |
} |
else{ |
if (Mb->dlc) |
meps(i) = Mb->dlc[lcid].get_macrostra(Mp->time, i); |
else{ |
if (Mp->tprob == mat_nonlinear_statics){ |
ret = Mb->lc[2*lcid].mstrain[cn]*Mp->lambda; |
ret += Mb->lc[2*lcid+1].mstrain[cn]; |
meps(i) = Mb->lc[2*lcid].mstrain[i]*Mp->lambda; |
meps(i) += Mb->lc[2*lcid+1].mstrain[i]; |
} |
else |
ret = Mb->lc[lcid].mstrain[cn]; |
meps(i) = Mb->lc[lcid].mstrain[i]; |
} |
} |
} |
1847,7 → 1942,6 |
abort(); |
} |
} |
return ret; |
} |
1858,7 → 1952,7 |
@param lcid - load case id |
@param cn - index of required macro-strain component |
@return The function returns macro-strain components in the argument mstra. |
@return The function returns the given macro-stress component. |
Created by Tomas Koudelka, 20.1.2015 |
*/ |
1865,7 → 1959,6 |
double macrostresses(long lcid, long cn) |
{ |
double ret = 0.0; |
long j; |
strastre *mstrastre; |
1876,14 → 1969,12 |
if (Mb->dlc) |
ret = Mb->dlc[lcid].get_macrostre(Mp->time, cn); |
else{ |
for (j=0; j<Mb->nlc; j++){ |
if (Mp->tprob == mat_nonlinear_statics){ |
ret = Mb->lc[2*lcid].mstress[cn]*Mp->lambda; |
ret += Mb->lc[2*lcid+1].mstress[cn]; |
} |
else |
ret = Mb->lc[lcid].mstress[cn]; |
if (Mp->tprob == mat_nonlinear_statics){ |
ret = Mb->lc[2*lcid].mstress[cn]*Mp->lambda; |
ret += Mb->lc[2*lcid+1].mstress[cn]; |
} |
else |
ret = Mb->lc[lcid].mstress[cn]; |
} |
break; |
} |
1899,14 → 1990,12 |
if (Mb->dlc) |
ret = Mb->dlc[lcid].get_macrostre(Mp->time, cn); |
else{ |
for (j=0; j<Mb->nlc; j++){ |
if (Mp->tprob == mat_nonlinear_statics){ |
ret = Mb->lc[2*lcid].mstress[cn]*Mp->lambda; |
ret += Mb->lc[2*lcid+1].mstress[cn]; |
} |
else |
ret = Mb->lc[lcid].mstress[cn]; |
if (Mp->tprob == mat_nonlinear_statics){ |
ret = Mb->lc[2*lcid].mstress[cn]*Mp->lambda; |
ret += Mb->lc[2*lcid+1].mstress[cn]; |
} |
else |
ret = Mb->lc[lcid].mstress[cn]; |
} |
} |
else{// macro-strain approach - components of the macro-stresses are stored in mechmat::mstress |
1925,6 → 2014,82 |
/** |
The function returns the macro-stress %vector in case of homogeniztaion problem. |
@param lcid - load case id |
@param msig - macro-stress %vector in Voigt notation |
@return The function returns macro-stress %vector in the argument msig. |
Created by Tomas Koudelka, 09.2023 |
*/ |
void macrostresses(long lcid, vector &msig) |
{ |
long i, j; |
strastre *mstrastre; |
long ncomp = Mt->max_ncompstr; |
switch (Mp->homog){ |
case 3: |
case 5: |
case 7:{ // macro-stress approach - macro-stresses are defined in the particular load cases |
if (Mb->dlc) |
Mb->dlc[lcid].get_macrostre(Mp->time, msig); |
else{ |
for (j=0; j<Mb->nlc; j++){ |
if (Mp->tprob == mat_nonlinear_statics){ |
copyv(Mb->lc[2*lcid].mstress, msig); |
cmulv(Mp->lambda, msig); |
vector aux; |
makerefv(aux, Mb->lc[2*lcid+1].mstress, ncomp); |
addv(msig, aux, msig); |
} |
else |
copyv(Mb->lc[lcid].mstress, msig); |
} |
} |
break; |
} |
case 4: |
case 6: |
case 8:{// macro-strain approach - components of the macro-stresses are stored in mechmat::mstress |
copyv(Mm->mstress, msig); |
break; |
} |
case 9:{ // mixed macro-stress/strain approach |
mstrastre = Mb->give_mstrastre(lcid); |
for(i=0; i<ncomp; i++){ |
if (mstrastre[i] == stress){ // macro-stress approach - macro-stresses are defined in the particular load cases |
if (Mb->dlc) |
msig(i) = Mb->dlc[lcid].get_macrostre(Mp->time, i); |
else{ |
for (j=0; j<Mb->nlc; j++){ |
if (Mp->tprob == mat_nonlinear_statics){ |
msig(i) = Mb->lc[2*lcid].mstress[i]*Mp->lambda; |
msig(i) += Mb->lc[2*lcid+1].mstress[i]; |
} |
else |
msig(i) = Mb->lc[lcid].mstress[i]; |
} |
} |
} |
else{// macro-strain approach - components of the macro-stresses are stored in mechmat::mstress |
msig(i) = Mm->mstress[i]; |
} |
} |
break; |
} |
default:{ |
print_err("unknown type of homogenization is required", __FILE__, __LINE__, __func__); |
abort(); |
} |
} |
} |
/** |
The function extracts nodal force components on one node. |
@param f - array of components for all nodal forces, it is input parameter |
2220,7 → 2385,7 |
// function assemble adds contributions to the input vector |
nullv (rhs+(lcid*2+0)*Ndofm, Ndofm); |
nullv (rhs+(lcid*2+1)*Ndofm, Ndofm); |
if (flv) |
if (flv) |
nullv (flv+(lcid*2+1)*Ndofm, Ndofm); |
Mb->lc[lcid*2+0].assemble (lcid*2,rhs+(lcid*2+0)*Ndofm,flv+(lcid*2+0)*Ndofm,1.0); |
Mb->lc[lcid*2+1].assemble (lcid*2,rhs+(lcid*2+1)*Ndofm,flv+(lcid*2+1)*Ndofm,1.0); |
2370,6 → 2535,9 |
// indicator of computation of other array |
// it means, stresses at integration points have not been computed |
Mp->otherstate=1; |
if (Mp->tprob == linear_statics){ |
Mm->updateipval(); |
} |
} |
if (Mp->stresspos == 2) |
compute_nodestresses (lcid); |
2427,6 → 2595,9 |
// indicator of computation of other array |
// it means, stresses at integration points have not been computed |
Mp->otherstate=1; |
if (Mp->tprob == linear_statics){ |
Mm->updateipval(); |
} |
} |
aux = Mp->strcomp; |
Mp->strcomp = 0; // stresses have been already computed, no stress computation |
/trunk/SIFEL/MEFEL/SRC/globmat.h |
---|
34,7 → 34,9 |
void nodforce (double *f, double *nf, long nid); |
double macrostrains(long lcid, long cn); |
void macrostrains(long lcid, vector &meps); |
double macrostresses(long lcid, long cn); |
void macrostresses(long lcid, vector &msig); |
void nodforce (double *f, long nid, vector &nf); |
/trunk/SIFEL/MEFEL/SRC/gnodvalvm.cpp |
---|
0,0 → 1,13 |
#include "gnodvalvm.h" |
#include <stdlib.h> |
gnodvalvm::gnodvalvm() : displv{NULL}, loadv{NULL}, iforv{NULL}, residv{NULL} |
{ |
} |
gnodvalvm::gnodvalvm(double *d, double *fl, double *fi, double *fr) : displv{d}, loadv{fl}, iforv{fi}, residv{fr} |
{ |
} |
/trunk/SIFEL/MEFEL/SRC/gnodvalvm.h |
---|
0,0 → 1,28 |
#ifndef GNODVALVM_H |
#define GNODVALVM_H |
/** |
The class stores pointers to the global vectors with nodal values. |
The dimensions of all %vector stored must be the toatl number of DOFs in the problem, i.e Ndofm. |
The instances of the class are used in functions for the quantity retrieving. |
Created by Tomas Koudelka, 09.2023 |
*/ |
class gnodvalvm |
{ |
public: |
gnodvalvm(); |
gnodvalvm(double *d, double *fl, double *fi, double *fr); |
/// %vector of nodal displacements |
double *displv; |
/// load %vector |
double *loadv; |
/// internal force %vector |
double *iforv; |
/// residual %vector |
double *residv; |
}; |
#endif |
/trunk/SIFEL/MEFEL/SRC/hexiface.cpp |
---|
0,0 → 1,883 |
#include "hexiface.h" |
#include "global.h" |
#include "probdesc.h" |
#include "mechtop.h" |
#include "mechmat.h" |
#include "globmat.h" |
#include "element.h" |
#include "node.h" |
#include "intp.h" |
#include "basefun.h" |
#include "difcalc.h" |
#include "vector.h" |
#include "matrix.h" |
#include "ordering.h" |
#include "math.h" |
// initialization of the array with the order/names of the strain components |
const mechquant hexinterface::stra_comp_ord[] = {eps_x, eps_y, eps_z, gamma_yz, gamma_xz, gamma_xy}; |
hexinterface::hexinterface(void) |
{ |
long i; |
// the numner of nodes |
nne=8; |
// the number of DOFs |
ndofe=24; |
// the number of blocks |
nb=1; |
// the number of components |
tncomp=3; |
// stress-strain state |
ssst = planecontact; |
ncomp = new long [nb]; |
ncomp[0]=3; |
// cumulative number of components approximated |
cncomp = new long [nb]; |
cncomp[0]=0; |
nip = new long* [nb]; |
intordsm = new long* [nb]; |
for (i=0;i<nb;i++){ |
nip[i] = new long [nb]; |
intordsm[i] = new long [nb]; |
} |
nip[0][0]=4; |
intordsm[0][0]=2; |
tnip=4; |
} |
hexinterface::~hexinterface(void) |
{ |
long i; |
for (i=0;i<nb;i++){ |
delete [] nip[i]; |
delete [] intordsm[i]; |
} |
delete [] nip; |
delete [] intordsm; |
delete [] ncomp; |
delete [] cncomp; |
} |
/** |
The function approximates value at the given point with the help of |
its nodal values. |
@param[in] xi, eta - natrual coordinates of the required point |
@param[in] nodval - nodal values of the approximated quantity |
@return The function returns approximated value at the given point. |
Created by JK. 10.2023 |
*/ |
double hexinterface::approx(double xi, double eta, vector &nodval) |
{ |
double f; |
vector bf(ASTCKVEC(nne)); |
bf_lin_4_2d (bf.a,xi,eta); |
nodval[4]= 0.0; |
nodval[5]= 0.0; |
nodval[6]= 0.0; |
nodval[7]= 0.0; |
scprd (bf,nodval,f); |
return f; |
} |
/** |
The function assembles global coordinates of integration point. |
@param eid - element id (input) |
@param ipp - integration point pointer (input) |
@param ri - row index of integration point block (input) |
@param ci - column index of integration point block (input) |
@param coord - %vector with global coordinates of integration point (ouput) |
@return The function returns global coordinates in the argument coord. |
10.1.2002 |
*/ |
void hexinterface::ipcoord (long eid,long ipp,long ri,long ci,vector &coord) |
{ |
long i,j,ii,jj,kk; |
double xi, eta; |
vector x(ASTCKVEC(nne)), y(ASTCKVEC(nne)), z(ASTCKVEC(nne)), w(ASTCKVEC(intordsm[ri][ci])), gp(ASTCKVEC(intordsm[ri][ci])); |
gauss_points (gp.a,w.a,intordsm[ri][ci]); |
Mt->give_node_coord3d (x,y,z,eid); |
kk=Mt->elements[eid].ipp[ri][ci]; |
for (ii = 0; ii < nb; ii++){ |
for (jj = 0; jj < nb; jj++){ |
if (intordsm[ii][jj] == 0) |
continue; |
reallocv(RSTCKVEC(intordsm[ii][jj], gp)); |
reallocv(RSTCKVEC(intordsm[ii][jj], w)); |
gauss_points (gp.a, w.a, intordsm[ii][jj]); |
for (i = 0; i < intordsm[ii][jj]; i++){ |
xi = gp[i]; |
for (j = 0; j < intordsm[ii][jj]; j++){ |
eta = gp[j]; |
if (kk==ipp){ |
coord[0]=approx (xi,eta,x); |
coord[1]=approx (xi,eta,y); |
coord[2]=approx (xi,eta,z); |
return; |
} |
kk++; |
} |
} |
} |
} |
} |
/** |
The function computes integration point values from the given nodal |
values of selected quantity. |
@param[in] eid - number of element |
@param[in] nodval - %vector of nodal values of the given quantity |
@param[out] ipval - %vector of integration point values approximated form |
the nodval. |
@return The function returns calculated int. point values in the argument ipval. |
Created by Tomas Koudelka, 10.2023 |
*/ |
void hexinterface::intpointval(long eid, vector &nodval, vector &ipval) |
{ |
long ii, jj, i, j, k; |
double xi, eta; |
vector w,gp; |
k=0; |
for (ii = 0; ii < nb; ii++){ |
for (jj = 0; jj < nb; jj++){ |
if (intordsm[ii][jj] == 0) |
continue; |
reallocv(RSTCKVEC(intordsm[ii][jj], gp)); |
reallocv(RSTCKVEC(intordsm[ii][jj], w)); |
gauss_points (gp.a, w.a, intordsm[ii][jj]); |
for (i = 0; i < intordsm[ii][jj]; i++){ |
xi = gp[i]; |
for (j = 0; j < intordsm[ii][jj]; j++){ |
eta = gp[j]; |
// value in integration point |
ipval[k] = approx (xi, eta, nodval); |
k++; |
} |
} |
} |
} |
} |
/** |
The function assembles transformation %matrix between coordinate system |
defined on element and global coordinate system. |
Transformation deals with coordinates. |
The transformation %matrix is from local element system to global system x_g = T x_e. |
@param[out] tran - transformation %matrix from local element system to the global coordinate system |
@param[in] gx,gy,gz - coordinates of nodes in the global coordinate system |
JK, 8. 7. 2023 |
*/ |
void hexinterface::coord_transf_matrix(matrix &tran, vector &gx, vector &gy, vector &gz) |
{ |
double norm,alpha,zero=1.0e-8; |
vector bv1(ASTCKVEC(3)),bv2(ASTCKVEC(3)),bv3(ASTCKVEC(3)); |
// first nonscaled basis vector (in the xi direction) |
bv1[0] = 0.5*(gx[7]+gx[3]-gx[2]-gx[6]); |
bv1[1] = 0.5*(gy[7]+gy[3]-gy[2]-gy[6]); |
bv1[2] = 0.5*(gz[7]+gz[3]-gz[2]-gz[6]); |
// norm of the first basis vector |
norm = sqrt(bv1[0]*bv1[0]+bv1[1]*bv1[1]+bv1[2]*bv1[2]); |
if (norm<zero){ |
print_err("nonpositive length of the first basis vector in hexahedral interface element", __FILE__, __LINE__, __func__); |
} |
// first scaled basis vector (in the xi direction) |
bv1[0] = bv1[0]/norm; |
bv1[1] = bv1[1]/norm; |
bv1[2] = bv1[2]/norm; |
// second nonscaled basis vector (in the eta direction) |
bv2[0] = 0.5*(gx[1]+gx[5]-gx[2]-gx[6]); |
bv2[1] = 0.5*(gy[1]+gy[5]-gy[2]-gy[6]); |
bv2[2] = 0.5*(gz[1]+gz[5]-gz[2]-gz[6]); |
alpha = bv1[0]*bv2[0] + bv1[1]*bv2[1] + bv1[2]*bv2[2]; |
// second vector orthogonal to the first vector |
bv2[0] = bv2[0] - alpha*bv1[0]; |
bv2[1] = bv2[1] - alpha*bv1[1]; |
bv2[2] = bv2[2] - alpha*bv1[2]; |
// norm of the second basis vector |
norm = sqrt(bv2[0]*bv2[0]+bv2[1]*bv2[1]+bv2[2]*bv2[2]); |
if (norm<zero){ |
print_err("nonpositive length of the second basis vector in hexahedral interface element", __FILE__, __LINE__, __func__); |
} |
// second scaled basis vector (in the eta direction) |
bv2[0] = bv2[0]/norm; |
bv2[1] = bv2[1]/norm; |
bv2[2] = bv2[2]/norm; |
// third basis vector |
bv3[0] = bv1[1]*bv2[2] - bv1[2]*bv2[1]; |
bv3[1] = bv1[2]*bv2[0] - bv1[0]*bv2[2]; |
bv3[2] = bv1[0]*bv2[1] - bv1[1]*bv2[0]; |
// transformation matrix from the element coordinate system to the global coordinate system |
tran[0][0] = bv1[0]; |
tran[1][0] = bv1[1]; |
tran[2][0] = bv1[2]; |
tran[0][1] = bv2[0]; |
tran[1][1] = bv2[1]; |
tran[2][1] = bv2[2]; |
tran[0][2] = bv3[0]; |
tran[1][2] = bv3[1]; |
tran[2][2] = bv3[2]; |
} |
/** |
The function assembles transformation %matrix from local nodal coordinate |
system to the global coordinate system x_g = T x_l |
@param nodes - nodes of element |
@param tmat - transformation %matrix |
JK, 8. 7. 2023 |
*/ |
void hexinterface::transf_matrix(ivector &nodes, matrix &tmat) |
{ |
long i,n,m; |
nullm (tmat); |
n=nodes.n; |
m=tmat.m; |
for (i=0;i<m;i++){ |
tmat[i][i]=1.0; |
} |
for (i=0;i<n;i++){ |
if (Mt->nodes[nodes[i]].transf>0){ |
tmat[i*3+0][i*3]=Mt->nodes[nodes[i]].e1[0]; |
tmat[i*3+1][i*3]=Mt->nodes[nodes[i]].e1[1]; |
tmat[i*3+2][i*3]=Mt->nodes[nodes[i]].e1[2]; |
tmat[i*3+0][i*3+1]=Mt->nodes[nodes[i]].e2[0]; |
tmat[i*3+1][i*3+1]=Mt->nodes[nodes[i]].e2[1]; |
tmat[i*3+2][i*3+1]=Mt->nodes[nodes[i]].e2[2]; |
tmat[i*3+0][i*3+2]=Mt->nodes[nodes[i]].e3[0]; |
tmat[i*3+1][i*3+2]=Mt->nodes[nodes[i]].e3[1]; |
tmat[i*3+2][i*3+2]=Mt->nodes[nodes[i]].e3[2]; |
} |
} |
} |
/** |
The function assembles strain-displacement (geometric) %matrix. |
@param[out] gm - resulting geometric %matrix (output) |
@param[in] gx,gy,gz - nodal coordinates in the global system |
@param[in] xi,eta - natural coordinate of required integration point |
@param[out] jac - Jacobian of transformation (output) |
@return The function returns resulting geometric %matrix in the parameter gm. |
JK, 8. 7. 2023 |
*/ |
void hexinterface::geom_matrix(matrix &gm, vector &gx, vector &gy, vector &gz, |
double xi, double eta, double &jac) |
{ |
long i; |
matrix transf(ASTCKMAT(3,3)); |
matrix aux(ASTCKMAT(3,3)); |
vector bf(ASTCKVEC(nne)); |
vector dx(ASTCKVEC(4)),dy(ASTCKVEC(4)); |
dx_bf_lin_4_2d (dx.a,eta); |
dy_bf_lin_4_2d (dy.a,xi); |
derivatives_2d (dx,dy,jac,gy,gz,xi,eta); |
fillm(0.0,gm); |
fillm(0.0,transf); |
fillm(0.0,aux); |
// transformation matrix from element coordintae system to the global system |
coord_transf_matrix (transf,gx,gy,gz); |
// basis functions on a quadrilateral element |
bf_lin_4_2d (bf.a,xi,eta); |
for (i=0;i<4;i++){ |
// B_i T |
cmulm(bf[i], transf, aux); |
// fisrt half of the geometric matrix |
gm[0][0+i*3] = aux[0][0]; |
gm[0][1+i*3] = aux[1][0]; |
gm[0][2+i*3] = aux[2][0]; |
gm[1][0+i*3] = aux[0][1]; |
gm[1][1+i*3] = aux[1][1]; |
gm[1][2+i*3] = aux[2][1]; |
gm[2][0+i*3] = aux[0][2]; |
gm[2][1+i*3] = aux[1][2]; |
gm[2][2+i*3] = aux[2][2]; |
// second half of the geometrix matrix |
gm[0][0+i*3+12] = 0.0 - aux[0][0]; |
gm[0][1+i*3+12] = 0.0 - aux[1][0]; |
gm[0][2+i*3+12] = 0.0 - aux[2][0]; |
gm[1][0+i*3+12] = 0.0 - aux[0][1]; |
gm[1][1+i*3+12] = 0.0 - aux[1][1]; |
gm[1][2+i*3+12] = 0.0 - aux[2][1]; |
gm[2][0+i*3+12] = 0.0 - aux[0][2]; |
gm[2][1+i*3+12] = 0.0 - aux[1][2]; |
gm[2][2+i*3+12] = 0.0 - aux[2][2]; |
} |
} |
/** |
The function computes stiffness %matrix of hexahedral |
interface finite element |
@param[in] eid - number of element |
@param[out] sm - resulting stiffness %matrix |
@return The function returns resulting stiffnes %matrix in the parameter sm. |
JK, 8. 7. 2023 |
*/ |
void hexinterface::stiffness_matrix(long eid, matrix &sm) |
{ |
long ii, jj, i, j, ipp; |
double xi, eta, jac; |
vector x(ASTCKVEC(nne)), y(ASTCKVEC(nne)), z(ASTCKVEC(nne)); |
matrix gm(ASTCKMAT(ncomp[0], ndofe)), d(ASTCKMAT(tncomp,tncomp)); |
vector gp, w; |
nullm (sm); |
Mt->give_node_coord3d (x,y,z,eid); |
ipp=Mt->elements[eid].ipp[0][0]; |
for (ii = 0; ii < nb; ii++){ |
for (jj = 0; jj < nb; jj++){ |
if (intordsm[ii][jj] == 0) |
continue; |
reallocv(RSTCKVEC(intordsm[ii][jj], gp)); |
reallocv(RSTCKVEC(intordsm[ii][jj], w)); |
gauss_points (gp.a,w.a,intordsm[ii][jj]); |
ipp=Mt->elements[eid].ipp[ii][jj]; |
for (i=0;i<intordsm[ii][jj];i++){ |
xi=gp[i]; |
for (j=0;j<intordsm[ii][jj];j++){ |
eta=gp[j]; |
// geometric matrix |
geom_matrix (gm,x,y,z,xi,eta,jac); |
// stiffness matrix of the material |
Mm->matstiff (d,ipp); |
// wieghts of the integration point |
jac *= w[i]*w[j]; |
// contribution to the stiffness matrix of the element due to one integration point |
bdbjac (sm,gm,d,gm,jac); |
ipp++; |
} |
} |
} |
} |
} |
/** |
Function computes stiffness %matrix of one element. If it is required, nodal values |
are transformed to the local nodal coordinate systems. |
@param eid - number of element |
@param sm - stiffness %matrix (output) |
@return The function returns required stiffness %matrix in the parameter sm. |
JK, 8. 7. 2023 |
*/ |
void hexinterface::res_stiffness_matrix(long eid, matrix &sm) |
{ |
long transf; |
ivector nodes(ASTCKIVEC(nne)); |
stiffness_matrix(eid, sm); |
// transformation of stiffness matrix |
// (in the case of nodal coordinate systems) |
Mt->give_elemnodes(eid,nodes); |
transf = Mt->locsystems(nodes); |
if (transf>0){ |
matrix tmat(ASTCKMAT(ndofe,ndofe)); |
transf_matrix(nodes,tmat); |
glmatrixtransf(sm,tmat); |
} |
} |
/** |
The function computes strains at integration points. If there are |
defined loacal nodal coordinate systems then the corresponding |
components of the dislacement %vector are transformed. |
@param[in] lcid - load case id |
@param[in] eid - element id |
@return The function stores resulting strains in the array strains |
of the element integration points. |
TKo, 10.2023 |
*/ |
void hexinterface::res_mainip_strains(long lcid, long eid) |
{ |
vector aux, r(ASTCKVEC(ndofe)); |
ivector nodes(ASTCKIVEC(nne)); |
matrix tmat; |
// nodal displacements |
eldispl (lcid,eid,r.a); |
// transformation of displacement vector |
long transf = Mt->locsystems(nodes); |
if (transf>0) { |
reallocv(RSTCKVEC(ndofe, aux)); |
reallocm(RSTCKMAT(ndofe, ndofe, tmat)); |
transf_matrix(nodes, tmat); |
lgvectortransf(aux, r, tmat); |
copyv(aux, r); |
} |
mainip_strains(lcid, eid, r); |
} |
/** |
The function computes strains at integration points of element. |
It is used in geometrically linear problems. |
@param[in] lcid - load case id |
@param[in] eid - element id |
@param[in] r - %vector of nodal displacements |
@return The function stores resulting strains in the array strains |
of the element integration points. |
TKo, 10.2023 |
*/ |
void hexinterface::mainip_strains(long lcid, long eid, vector &r) |
{ |
long ii, i, j, ipp; |
double xi, eta, jac; |
ivector nodes(ASTCKIVEC(nne)); |
vector w, gp; |
vector x(ASTCKVEC(nne)), y(ASTCKVEC(nne)), z(ASTCKVEC(nne)); |
matrix gm; |
vector eps; |
nullm(gm); |
Mt->give_node_coord3d(x, y, z, eid); |
Mt->give_elemnodes (eid, nodes); |
ipp=Mt->elements[eid].ipp[0][0]; |
for (ii=0;ii<nb;ii++){ |
reallocv(RSTCKVEC(intordsm[ii][ii], gp)); |
reallocv(RSTCKVEC(intordsm[ii][ii], w)); |
reallocv(RSTCKVEC(ncomp[ii], eps)); |
reallocm(RSTCKMAT(ncomp[ii], ndofe, gm)); |
gauss_points(gp.a, w.a, intordsm[ii][ii]); |
ipp = Mt->elements[eid].ipp[ii][ii]; |
for(i=0; i<intordsm[ii][ii]; i++){ |
xi=gp[i]; |
for (j=0;j<intordsm[ii][ii];j++){ |
eta=gp[j]; |
geom_matrix(gm, x, y, z, xi, eta, jac); |
mxv(gm, r, eps); |
Mm->storestrain(lcid, ipp, cncomp[ii], eps); |
ipp++; |
} |
} |
} |
} |
/** |
The function computes stresses at element integration points |
@param[in] lcid - load case id |
@param[in] eid - element id |
@return The function stores resulting stresses in the stress array |
of the element integration points. |
Created by TKo, 10.2023 |
*/ |
void hexinterface::res_mainip_stresses(long lcid, long eid) |
{ |
long ri,ci; |
ri=0; |
ci=0; |
compute_nlstress (lcid,eid,ri,ci); |
} |
/** |
The function computes strains in nodes of element, nodal values are taken |
from the closest integration point. |
@param[in] lcid - load case id |
@param[in] eid - element id |
JK, 10.5.2002 |
*/ |
void hexinterface::nod_strains_ip (long lcid, long eid) |
{ |
long i,j,ipp; |
ivector ipnum(ASTCKIVEC(nne)), nod(ASTCKIVEC(nne)), auxiv; |
vector eps(ASTCKVEC(tncomp)); |
// numbers of integration points closest to nodes |
// (function is from the file GEFEL/ordering.cpp) |
ipp=Mt->elements[eid].ipp[0][0]; |
nodip_planelq(ipp, intordsm[0][0], ipnum); |
// repeat ip num extraction for remaining element nodes |
makerefv(auxiv, ipnum.a+4, 4); |
nodip_planelq(ipp, intordsm[0][0], ipnum); |
// node numbers of the element |
Mt->give_elemnodes (eid,nod); |
for (i=0;i<nne;i++){ |
// strains at the closest integration point |
Mm->givestrain (lcid,ipnum[i],eps); |
// storage of strains to the node |
j=nod[i]; |
Mt->nodes[j].storestrain (lcid,0,eps); |
} |
} |
/** |
The function computes nodal strains directly. |
@param[in] lcid - load case id |
@param[in] eid - element id |
@param[in] stra - array for strain components |
stra[i][j] - the j-th strain component at the i-th node |
JK, 26.9.2004 |
*/ |
void hexinterface::nod_strains_comp (long lcid,long eid,double **stra) |
{ |
long i,j; |
double jac; |
ivector nodes(ASTCKIVEC(nne)); |
vector x(ASTCKVEC(nne)), y(ASTCKVEC(nne)), z(ASTCKVEC(nne)), nxi(ASTCKVEC(nne)), neta(ASTCKVEC(nne)); |
vector r(ASTCKVEC(ndofe)), eps(ASTCKVEC(tncomp)), aux; |
matrix tmat, gm(ASTCKMAT(tncomp,ndofe)); |
// node coordinates |
Mt->give_node_coord3d(x, y, z, eid); |
// node numbers |
Mt->give_elemnodes(eid, nodes); |
// nodal displacements |
eldispl(lcid, eid, r.a); |
// transformation of displacement vector |
long transf = Mt->locsystems (nodes); |
if (transf>0){ |
reallocv(RSTCKVEC(ndofe, aux)); |
reallocm(RSTCKMAT(ndofe, ndofe, tmat)); |
transf_matrix(nodes, tmat); |
lgvectortransf(aux, r, tmat); |
copyv(aux, r); |
} |
// natural coordinates of element nodes |
// (function is from the file GEFEL/ordering.cpp) |
nodcoord_planelq(nxi, neta); |
// loop over nodes |
for (i=0; i<nne; i++){ |
// geometric matrix |
geom_matrix(gm, x, y, z, nxi[i], neta[i], jac); |
// strain computation |
mxv(gm, r, eps); |
for (j=0; j<eps.n; j++){ |
stra[i][j] = eps[j]; |
} |
} |
} |
/** |
The function computes stresses at nodes, nodal values are taken from the closest integration point. |
@param[in] lcid - load case id |
@param[in] eid - element id |
10.5.2002, JK |
*/ |
void hexinterface::nod_stresses_ip (long lcid,long eid) |
{ |
long i,j,ipp; |
ivector ipnum(ASTCKIVEC(nne)), nod(ASTCKIVEC(nne)), auxiv; |
vector sig(ASTCKVEC(tncomp)); |
// numbers of integration points closest to nodes |
// (function is from the file GEFEL/ordering.cpp) |
ipp=Mt->elements[eid].ipp[0][0]; |
nodip_planelq(ipp, intordsm[0][0], ipnum); |
// repeat ip num extraction for remaining element nodes |
makerefv(auxiv, ipnum.a+4, 4); |
nodip_planelq(ipp, intordsm[0][0], ipnum); |
// node numbers of the element |
Mt->give_elemnodes (eid, nod); |
for (i=0;i<nne;i++){ |
// stresses at the closest integration point |
Mm->givestress(lcid, ipnum[i], sig); |
// storage of stresses to the node |
j=nod[i]; |
Mt->nodes[j].storestress(lcid, 0, sig); |
} |
} |
/** |
Function computes actual stresses at integration points on element. |
@param lcid - number of load case |
@param eid - element id |
@param ri,ci - row and column indices |
@return The function stores resulting stresses in the stress array |
of the element integration points. |
Created by Tomas Koudelka, 10.2023 |
*/ |
void hexinterface::compute_nlstress(long lcid, long eid, long ri, long ci) |
{ |
long ii, jj, i, j, ipp; |
ipp = Mt->elements[eid].ipp[ri][ci]; |
for (ii=0; ii<nb; ii++){ |
for (jj=0; jj<nb; jj++){ |
for(i=0; i<intordsm[ii][jj]; i++){ |
for (j=0; j<intordsm[ii][jj]; j++){ |
// computation of actual stresses |
if (Mp->strcomp==1) |
Mm->computenlstresses(ipp, Mm->ip[ipp]); |
ipp++; |
} |
} |
} |
} |
} |
/** |
The function computes resulting internal forces due to actual stresses |
@param lcid - number of load case |
@param eid - element id |
@param ifor - %vector of internal forces |
@return The function returns resulting %vector of internal forces in the parameter ifor. |
Created by Tomas Koudelka, 10.2023 |
*/ |
void hexinterface::internal_forces(long lcid, long eid, long ri, long ci, |
vector &ifor, vector &x, vector &y, vector &z) |
{ |
integratedquant iq; |
iq=locstress; |
// computation of stresses |
compute_nlstress(lcid, eid, ri, ci); |
// integration of stresses over the element |
elem_integration(iq, lcid, eid, ri, ci, ifor, x, y, z); |
} |
/** |
The function computes resulting internal forces from actual stresses. If required, the transformation |
to the nodal coordinate system is performed. |
@param[in] lcid - number of load case |
@param[in] eid - element id |
@param[out] ifor - %vector of internal forces |
@return The function returns resulting %vector of internal forces in the parameter ifor. |
Created by Tomas Koudelka, 10.2023 |
*/ |
void hexinterface::res_internal_forces (long lcid,long eid,vector &ifor) |
{ |
long transf; |
ivector nodes(ASTCKIVEC(nne)); |
vector v(ASTCKVEC(ndofe)), x(ASTCKVEC(nne)), y(ASTCKVEC(nne)), z(ASTCKVEC(nne)); |
Mt->give_node_coord3d(x, y, z, eid); |
internal_forces(lcid, eid, 0, 0, ifor, x, y, z); |
// transformation of nodal forces |
// (in the case of nodal coordinate systems) |
Mt->give_elemnodes(eid, nodes); |
transf = Mt->locsystems(nodes); |
if (transf>0){ |
matrix tmat(ndofe, ndofe); |
transf_matrix(nodes, tmat); |
glvectortransf(ifor, v, tmat); |
copyv(v, ifor); |
} |
} |
/** |
The function integrates selected quantity on the selected finite element, i.e. \int B^T q dV. |
It results in nodal values. |
@param[in] iq - type of integrated quantity (see alias.h) |
@param[in] lcid - number of load case |
@param[in] eid - element id |
@param[in] ri,ci - row and column indices |
@param[out] nv - nodal values |
@param[in] x,y,z - nodal coordinates |
@return The function returns nodal values of the integrated quantity in the parameter nv. |
Created by Tomas Koudelka, 10.2023 |
*/ |
void hexinterface::elem_integration(integratedquant iq, long lcid, long eid, long ri, long ci, |
vector &nv, vector &x, vector &y, vector &z) |
{ |
long ii, jj, i, j, ipp; |
double xi, eta, jac; |
vector w, gp, ipv(ASTCKVEC(tncomp)), contr(ASTCKVEC(ndofe)); |
matrix gm(ASTCKMAT(tncomp,ndofe)); |
nullv (nv); |
ipp=Mt->elements[eid].ipp[ri][ci]; |
for (ii=0; ii<nb; ii++){ |
for (jj=0; jj<nb; jj++){ |
if (intordsm[ii][jj] == 0) |
continue; |
reallocv(RSTCKVEC(intordsm[ii][jj],gp)); |
reallocv(RSTCKVEC(intordsm[ii][jj],w)); |
gauss_points (gp.a,w.a,intordsm[ii][jj]); |
for (i=0;i<intordsm[ii][jj];i++){ |
xi=gp[i]; |
for (j=0;j<intordsm[ii][jj];j++){ |
eta=gp[j]; |
// function assembles required quantity at integration point |
Mm->givequantity(iq, lcid, ipp, cncomp[ii], ipv); |
// strain-displacement (geometric) matrix |
geom_matrix(gm, x, y, z, xi, eta, jac); |
// contribution to the nodal values |
mtxv(gm, ipv, contr); |
cmulv(jac*w[i]*w[j], contr); |
// summation |
addv(contr, nv, nv); |
ipp++; |
} |
} |
} |
} |
} |
/trunk/SIFEL/MEFEL/SRC/hexiface.h |
---|
0,0 → 1,81 |
#ifndef HEXINTERFACE_H |
#define HEXINTERFACE_H |
#include "alias.h" |
struct matrix; |
struct vector; |
struct ivector; |
/** |
Class hexinterface is hexahedral element for simulation of interface between surfaces of |
linear 3D elements. |
basic data |
nne = 8 - number nodes on element |
ndofe = 24 - number of DOFs on element |
JK, 8. 7. 2023 |
*/ |
class hexinterface |
{ |
public: |
hexinterface(void); |
~hexinterface(void); |
double approx(double xi, double eta, vector &nodval); |
void ipcoord (long eid,long ipp,long ri,long ci,vector &coord); |
void intpointval(long eid, vector &nodval, vector &ipval); |
void coord_transf_matrix(matrix &tran, vector &gx, vector &gy, vector &gz); |
void transf_matrix(ivector &nodes, matrix &tmat); |
void geom_matrix(matrix &gm, vector &gx, vector &gy, vector &gz, double xi, double eta, double &jac); |
void stiffness_matrix(long eid, matrix &sm); |
void res_stiffness_matrix(long eid, matrix &sm); |
void res_mainip_strains(long lcid, long eid); |
void mainip_strains(long lcid, long eid, vector &r); |
void res_mainip_stresses(long lcid, long eid); |
void nod_strains_ip (long lcid, long eid); |
void nod_strains_comp (long lcid,long eid,double **stra); |
void nod_stresses_ip (long lcid,long eid); |
void compute_nlstress(long lcid, long eid, long ri, long ci); |
void internal_forces(long lcid, long eid, long ri, long ci, vector &ifor, vector &x, vector &y, vector &z); |
void res_internal_forces(long lcid, long eid, vector &ifor); |
void elem_integration(integratedquant iq, long lcid, long eid, long ri, long ci, |
vector &nv, vector &x, vector &y, vector &z); |
/// number of DOFs on the element |
long ndofe; |
/// number of nodes on one element |
long nne; |
/// total number of components of stress and strain tensors |
long tncomp; |
/// total number of integration points on element |
long tnip; |
/// array containing cumulative numbers of components of stress and strain tensors |
long *cncomp; |
/// array containing numbers of components of stress and strain tensors |
long *ncomp; |
/// number of approximated functions on the element |
//long napfun; |
/// number of edges |
//long ned; |
/// number of nodes on one edge |
//long nned; |
/// array containing orders of numerical integration of stiffness matrix |
long **intordsm; |
/// order of integration of mass matrix |
//long intordmm; |
/// order of integration on edges |
//long intordb; |
/// array of numbers of integration points in sets |
long **nip; |
/// number of blocks |
long nb; |
/// stress/strain state |
strastrestate ssst; |
// array with the order/names of the strain components |
static const mechquant stra_comp_ord[]; |
}; |
#endif |
/trunk/SIFEL/MEFEL/SRC/hypoplunsatexptherm2.cpp |
---|
1,1212 → 1,1212 |
#include <stdlib.h> |
#include <float.h> |
#include "generalmod.h" |
#include "global.h" |
#include "probdesc.h" |
#include "mechmat.h" |
#include "mechtop.h" |
#include "intpoints.h" |
#include "element.h" |
#include "tensor.h" |
#include "vecttens.h" |
#include "mathem.h" |
#include "vector.h" |
#include "vecttens.h" |
#include "hypoplunsatexptherm2.h" |
#define nijac 200 |
#define limit 1.0e-15 // zero limit for principal values of tensors (Jacobi method) |
hypoplast_unsat_exp_therm::hypoplast_unsat_exp_therm() |
{ |
phideg = lam_star = kap_star = n_star = 0.0; |
nu = n = l = nt = lt = m = alpha_s = kap_m = sm_star = 0.0; |
em_star = s_airentry0 = em0 = tr = at = bt = lambdap0 = aer = p_t = 0.0; |
// retrieve number of parameters, number of state variables and number of generalized vector components |
nparams=huet.nparms; // number of parameters |
nstatev=huet.nstatev; // number of state variables (10 for actual implementation, see constructor in generalmod.h) |
ngstrain=huet.ngstrain; // number of generalised strain tensor components (8 for actual implementation, see constructor in generalmod.h) |
ngstress=huet.ngstress; // number of generalised stress tensor components (7 for actual implementation, see constructor in generalmod.h) |
nrkfparams=huet.nrkf_parms; // number of RKF method parameters |
nrkfstatev=huet.nrkf_statev; // number of RKF method parameters |
params = new double[nparams]; |
rkfparams = new double[nrkfparams]; |
pr_suc_fl = no; |
pr_tempr_fl = no; |
// maximum value of 'zero' level of state variables for RKF time integration |
// it may be rewritten by RKF tolerance if its value is less than the value specified here |
sv_rkf_zero = 1.0e-3; |
} |
hypoplast_unsat_exp_therm::~hypoplast_unsat_exp_therm() |
{ |
delete [] params; |
delete [] rkfparams; |
} |
/** |
The function reads material parameters from the opened text file given |
by the parameter in. |
@param in - pointer to the opened input text file |
@return The function does not return anything. |
Created by Tomas Koudelka, 30.1.2014 |
*/ |
void hypoplast_unsat_exp_therm::read(XFILE *in) |
{ |
xfscanf(in, "%k %le %k %le %k %le %k %le", |
"phi", &phideg, "lam_star", &lam_star, |
"kap_star", &kap_star, "N_star", &n_star); |
xfscanf(in, "%k %le %k %le %k %le %k %le %k %le %k %le", |
"nu", &nu, "n", &n, "l", &l, "nT", &nt, "lT", <, "m", &m); |
xfscanf(in, "%k %le %k %le %k %le %k %le %k %le %k %le %k %le", |
"alpha_s", &alpha_s, "kap_m", &kap_m, "sm_star", &sm_star, |
"em_star", &em_star, "csh", &csh, "s_airentry0", &s_airentry0, "em0", &em0); |
xfscanf(in, "%k %le %k %le %k %le %k %le %k %le %k %le", |
"tr", &tr, "at", &at, "bt", &bt, |
"aer", &aer, "lambdap0", &lambdap0, "p_t", &p_t); |
// xfscanf(in, "%k %le %k %le","einit", &einit, "ascaninit", &ascaninit); |
xfscanf(in, "%k%m", "presc_suction", &answertype_kwdset, &pr_suc_fl); |
if (pr_suc_fl == yes) |
suc_fn.read(in); |
xfscanf(in, "%k%m", "presc_tempr", &answertype_kwdset, &pr_tempr_fl); |
if (pr_tempr_fl == yes) |
tempr_fn.read(in); |
sra.read(in); |
if (sv_rkf_zero > sra.err) |
sv_rkf_zero = sra.err; |
if (phideg <= 0.0) |
{ |
print_err("phi must be positive (phi = %le)", __FILE__, __LINE__, __func__, phideg); |
abort(); |
} |
if (p_t < 0.0) |
{ |
print_err("p_t must not be negative (p_t = %le)", __FILE__, __LINE__, __func__, p_t); |
abort(); |
} |
if (lam_star <= 0.0) |
{ |
print_err("lam_star must be positive (lam_star = %le)", __FILE__, __LINE__, __func__, lam_star); |
abort(); |
} |
if (kap_star <= 0.0) |
{ |
print_err("kap_star must be positive (kap_star = %le)", __FILE__, __LINE__, __func__, kap_star); |
abort(); |
} |
if (n_star <= 0.0) |
{ |
print_err("n_star must be positive (n_star = %le)", __FILE__, __LINE__, __func__, n_star); |
abort(); |
} |
// temporary check for Mock-up test |
if (aer != 1.0) |
{ |
print_err("temporary check for Mock-up experiment - aer is not set to 1.0 (aer = %le)", __FILE__, __LINE__, __func__, aer); |
abort(); |
} |
// temporary check for Mock-up test |
if (aer != 1.0) |
{ |
print_err("temporary check for Mock-up experiment - aer is not set to 1.0 (aer = %le)", __FILE__, __LINE__, __func__, aer); |
abort(); |
} |
/* |
if (rr <= 0.0) |
{ |
print_err("rr must be positive (rr = %le)", __FILE__, __LINE__, __func__, rr); |
abort(); |
} |
if (s_e0 < 0.0) |
{ |
print_err("s_e0 must not be negative (s_e0 = %le)", __FILE__, __LINE__, __func__, s_e0); |
abort(); |
} |
*/ |
params[0] = phideg; |
params[1] = lam_star; |
params[2] = kap_star; |
params[3] = n_star; |
params[4] = nu; |
params[5] = n; |
params[6] = l; |
params[7] = nt; |
params[8] = lt; |
params[9] = m; |
params[10] = alpha_s; |
params[11] = kap_m; |
params[12] = sm_star; |
params[13] = em_star; |
params[14] = csh; |
params[15] = s_airentry0; |
params[16] = em0; |
params[17] = tr; |
params[18] = at; |
params[19] = bt; |
params[20] = aer; |
params[21] = lambdap0; |
params[22] = p_t; |
//params[21] = einit; |
//params[22] = ascaninit; |
rkfparams[0] = sra.give_err_sig(); |
rkfparams[1] = sra.give_hmin(); |
rkfparams[2] = sra.give_ni(); |
rkfparams[3] = sv_rkf_zero; |
rkfparams[4] = (int)sra.give_rkt(); |
} |
/** |
The function prints material parameters into the opened text file given |
by the parameter out. |
@param out - pointer to the opened output text file |
@return The function does not return anything. |
Created by Tomas Koudelka, koudelka@cml.fsv.cvut.cz, 17.12.2015 |
*/ |
void hypoplast_unsat_exp_therm::print(FILE *out) |
{ |
fprintf(out, "%le %le %le %le\n", |
phideg, lam_star, kap_star, n_star); |
fprintf(out, "%le %le %le %le %le %le\n", |
nu, n, l, nt, lt, m); |
fprintf(out, "%le %le %le %le %le %le %le\n", |
alpha_s, kap_m, sm_star, em_star, csh, s_airentry0, em0); |
fprintf(out, "%le %le %le %le %le %le\n",tr, at, bt, aer, lambdap0, p_t); |
fprintf(out, "%d ", int(pr_suc_fl)); |
if (pr_suc_fl == yes) |
suc_fn.print(out); |
fprintf(out, "%d ", int(pr_tempr_fl)); |
if (pr_tempr_fl == yes) |
tempr_fn.print(out); |
fprintf(out, "\n"); |
sra.print(out); |
} |
/** |
The function initializes material model. Retrieves initial values of the following |
quantities |
@param ipp - integration point number |
@param ido - index of internal variables for given material in the ipp other array |
@return The function does not return anything but updates initial value of Sr and stress vector |
in eqother array. |
Created by Tomas Koudelka, 1.10.2015 |
*/ |
void hypoplast_unsat_exp_therm::initval (long ipp,long ido) |
{ |
// data handled by MEFEL |
long ncomp = Mm->ip[ipp].ncompstr; // number of reduced stress/strain components |
strastrestate ssst = Mm->ip[ipp].ssst; // stress/strain state indicator |
vector sig(ASTCKVEC(ngstress)), eps(ASTCKVEC(ngstrain)); |
vector deps(ASTCKVEC(ngstrain)), dstatev(ASTCKVEC(nstatev)); |
matrix dd_gen(ASTCKMAT(ngstress,ngstrain)); |
double *statev = Mm->ip[ipp].eqother+ido+2*ncomp+3; |
int herr; |
if (statev[0] == 0.0) // initial void ratio was not set => model has not been initialized yet |
{ |
statev[0] = Mm->ic[ipp][0]; // initialize actual value of void ratio |
statev[7] = Mm->ic[ipp][1]; // initialize actual value of ascan |
// set initial value of effective stresses from eigenstresses |
// eigenstress is assumed to be net stress, i.e. sig_{net} = sig_{tot} - u_a.I |
if ((Mp->eigstrains == 4) || (Mp->eigstrains == 5)) |
{ |
for (long i=0; i<ncomp; i++) |
{ |
Mm->ip[ipp].eqother[ido+ncomp+i] = Mm->eigstresses[ipp][i]; |
Mm->ip[ipp].stress[i] = Mm->eigstresses[ipp][i]; |
} |
} |
} |
if (pr_suc_fl == yes) |
statev[1] = suc_fn.getval(Mp->time); //initial prescribed suction pressure s (positive) |
else |
statev[1] = Mm->givenonmechq(suction, ipp); // initial suction pressure s (positive) |
statev[2] = 0.0; // initial degree of saturation S_r |
if (pr_tempr_fl == yes) |
statev[3] = tempr_fn.getval(Mp->time); //initial prescribed temperature |
else |
statev[3] = Mm->givenonmechq(temperature, ipp); // initial temperature T |
give_full_vector(sig.a, Mm->ip[ipp].stress, ssst); |
give_full_vector(eps.a, Mm->ip[ipp].strain, ssst); |
// set remaining components of generalized strain vector |
eps(6) = statev[1]; // set suction to the corresponding component of generalized strain vector |
eps(7) = statev[3]; // set temperature to the corresponding component of generalized strain vector |
// initialize model |
herr = huet.soil_model(eps.a, sig.a, statev, deps.a, 1.0, NULL, params, NULL, rkfparams, 0, Mp->jstep, ipp); |
if (herr) |
{ |
print_err("hypoplasticity model cannot be initialized on element %ld (ip=%ld)", __FILE__, __LINE__, __func__, Mm->elip[ipp]+1, ipp+1); |
abort(); |
} |
statev[2] = sig(6); // store computed initial Sr |
// prepare working copy of array of internal variables |
// eqother values have been already set because statev array is a reference to the eqother array |
copyv(statev, Mm->ip[ipp].other+ido+2*ncomp+3, nstatev); |
// set initial values for dSr/ds and dSr/dT according to generalized stiffness matrix |
herr = huet.soil_model(eps.a, sig.a, statev, NULL, 1.0, dd_gen.a, params, NULL, rkfparams, 3, Mp->jstep, ipp); |
if (herr) |
{ |
print_err("generalized stiffness matrix cannot be initialized on element %ld (ip=%ld)", __FILE__, __LINE__, __func__, Mm->elip[ipp]+1, ipp+1); |
abort(); |
} |
Mm->ip[ipp].eqother[2*ncomp+3+nstatev+8] = dd_gen(ngstress-1, ngstrain-2); // store dSr/ds matrix component |
Mm->ip[ipp].eqother[2*ncomp+3+nstatev+9] = dd_gen(ngstress-1, ngstrain-1); // store dSr/dT matrix component |
Mm->ip[ipp].eqother[ido+2*ncomp+3+nstatev+11] = dd_gen(ngstress-1, 0);//+dd_gen(ngstress-1, 1)+dd_gen(ngstress-1, 2); // compute and store dSr/depsv from matrix components |
// actualize 'consistent' material stiffness matrix |
copym(dd_gen, Mm->ip[ipp].eqother+ido+2*ncomp+3+nstatev+12); |
// actualize other array by the computed values |
memcpy(Mm->ip[ipp].other, Mm->ip[ipp].eqother, sizeof(*Mm->ip[ipp].other)*Mm->ip[ipp].ncompother); |
} |
/** |
The function computes material stiffnes %matrix. |
@param d - allocated matrix structure for material stiffness %matrix (output) |
@param ipp - integration point number |
@param ido - index of internal variables for given material in the ipp other array |
@return The function returns stiffness %matrix in the parameter d. |
Created by Tomas Koudelka, 1.10.2015 |
*/ |
void hypoplast_unsat_exp_therm::matstiff (matrix &d,long ipp,long /*ido*/) |
{ |
long i; |
// data handled by MEFEL |
long ncomp = Mm->ip[ipp].ncompstr; |
strastrestate ssst = Mm->ip[ipp].ssst; |
double aux; |
matrix dd_gen(ASTCKMAT(ngstress,ngstrain)), dd(ASTCKMAT(6,6)); |
/* |
vector sig(ASTCKVEC(ngstress)), eps(ASTCKVEC(ngstrain)), deps(ASTCKVEC(ngstrain)); |
vector statev(ASTCKVEC(nstatev)); |
int herr; |
long j; |
// convert stress and strain vectors to full 6 component vectors |
give_full_vector(sig.a, Mm->ip[ipp].stress, ssst); |
give_full_vector(eps.a, Mm->ip[ipp].strain, ssst); |
// stress vector must be reoredred |
// SIFEL ordering is sig11, sig22, sig33, sig23, sig13, sig12 |
// ABAQUS ordering is sig11, sig22, sig33, sig12, sig13, sig23 |
aux = sig(3); |
sig(3) = sig(5); |
sig(5) = aux; |
// strain vector must be reoredred |
// SIFEL ordering is eps11, eps22, eps33, gamma23, gamma13, gamma12 |
// ABAQUS ordering is eps11, eps22, eps33, gamma12, gamma13, gamma23 |
aux = eps(3); |
eps(3) = eps(5); |
eps(5) = aux; |
// assemble generalized strain, stress and strain increment vectors |
eps(6) = Mm->ip[ipp].other[ido+2*ncomp+3+1]; // suction from the actual time step |
eps(7) = Mm->ip[ipp].other[ido+2*ncomp+3+3]; // temperature from the actual time step |
sig(6) = Mm->ip[ipp].other[ido+2*ncomp+3+2]; // degree of saturation Sr from the actual time step |
// prepare working copy of internal variables |
for (i=ido+2*ncomp+3, j=0; i<ido+2*ncomp+3+nstatev; i++, j++) |
statev(j) = Mm->ip[ipp].other[i]; |
herr = huet.soil_model(eps.a, sig.a, statev.a, NULL, NULL, NULL, dd_gen.a, NULL, 1, Mp->jstep); |
if (herr) |
{ |
print_err("math error detected in hypoplastic model on element %ld (ip=%ld)", __FILE__, __LINE__, __func__, Mm->elip[ipp]+1, ipp+1); |
abort(); |
} |
*/ |
// retrieve actual generalized material stiffness matrix from the other array |
makerefm(dd_gen, Mm->ip[ipp].other+2*ncomp+3+nstatev+12, ngstress, ngstrain); |
// reorder stiffness matrix in the full-length format |
// |
// swap the fourth and sixth columns except of the fourth and sixth elements |
for (i=0; i<ngstress; i++) |
{ |
if ((i == 3) || (i==5)) |
continue; |
aux = dd_gen(i,3); |
dd_gen(i,3) = dd_gen(i,5); |
dd_gen(i,5) = aux; |
} |
// swap the fourth and sixth rows except of the fourth and sixth elements |
for (i=0; i<ngstrain; i++) |
{ |
if ((i == 3) || (i==5)) |
continue; |
aux = dd_gen(3,i); |
dd_gen(3,i) = dd_gen(5,i); |
dd_gen(5,i) = aux; |
} |
// swap elements on intersections of the fourth and sixth columns and rows |
aux = dd_gen(3,3); |
dd_gen(3,3) = dd_gen(5,5); |
dd_gen(5,5) = aux; |
aux = dd_gen(3,5); |
dd_gen(3,5) = dd_gen(5,3); |
dd_gen(5,3) = aux; |
// extract the stiffness matrix for the mechanics |
extractm(dd, dd_gen, 0, 6); |
// convert stiffness matrix to the reduced format suitable for element stiffness matrix |
tensor4_ematrix (d, dd, ssst); |
} |
/** |
The function computes stress increments due to pore pressure change in the integration point and stores |
them into eqother array. |
@param ipp - integration point pointer |
@param im - index of material type for given ip |
@param ido - index of internal variables for given material in the ipp other array |
@return The function does not return anything but stores the resulting values in the eqother array. |
Created by Tomas Koudelka, 11.2015 |
*/ |
void hypoplast_unsat_exp_therm::nlstressesincr (long ipp, long /*im*/, long ido) |
{ |
long i, j; |
long ncomp = Mm->ip[ipp].ncompstr; |
strastrestate ssst = Mm->ip[ipp].ssst; |
double aux; |
double ds; |
vector sig(ASTCKVEC(ngstress)), eps(ASTCKVEC(ngstrain)); |
vector statev(ASTCKVEC(nstatev)); |
matrix dd_gen; |
//int herr; |
// This procedure is supposed to be called at the beginning of the actual time step |
// and therefore the ip.stress and ip.strain arrays must contain values |
// from the last equilibrium step |
// convert stress and strain vectors to full 6 component vectors |
give_full_vector(sig.a, Mm->ip[ipp].stress, ssst); |
give_full_vector(eps.a, Mm->ip[ipp].strain, ssst); |
// stress vector must be reoredred |
// SIFEL ordering is sig11, sig22, sig33, sig23, sig13, sig12 |
// ABAQUS ordering is sig11, sig22, sig33, sig12, sig13, sig23 |
aux = sig(3); |
sig(3) = sig(5); |
sig(5) = aux; |
// strain vector must be reoredred |
// SIFEL ordering is eps11, eps22, eps33, gamma23, gamma13, gamma12 |
// ABAQUS ordering is eps11, eps22, eps33, gamma12, gamma13, gamma23 |
aux = eps(3); |
eps(3) = eps(5); |
eps(5) = aux; |
// assemble generalized strain, stress and strain increment vectors |
eps(6) = Mm->ip[ipp].eqother[ido+2*ncomp+3+1]; // suction from the previous time step |
eps(7) = Mm->ip[ipp].eqother[ido+2*ncomp+3+3]; // temperature from the previous time step |
sig(6) = Mm->ip[ipp].eqother[ido+2*ncomp+3+2]; // degree of saturation Sr from the previous time step |
// prepare working copy of internal variables |
for (i=ido+2*ncomp+3, j=0; i<ido+2*ncomp+3+nstatev; i++, j++) |
statev(j) = Mm->ip[ipp].eqother[i]; |
// retrieve actual generalized material stiffness matrix from the other array |
makerefm(dd_gen, Mm->ip[ipp].other+2*ncomp+3+nstatev+12, ngstress, ngstrain); |
/* |
reallocm(RSTCKMAT(dd_gen, ngstress,ngstrain)); |
herr = huet.soil_model(eps.a, sig.a, statev.a, NULL, NULL, NULL, dd_gen.a, NULL, 3, Mp->jstep); |
if (herr) |
{ |
print_err("math error detected in hypoplastic model on element %ld (ip=%ld)", __FILE__, __LINE__, __func__, Mm->elip[ipp]+1, ipp+1); |
abort(); |
} |
*/ |
if (pr_suc_fl == yes) //prescribed suction pressure s |
ds = (suc_fn.getval(Mp->time)-Mm->ip[ipp].eqother[ido+2*ncomp+3+1]); //suction pressure increment ds = du_a - du_w |
else // suction is obtained from METR |
ds = Mm->givenonmechq(suction, ipp) - Mm->ip[ipp].eqother[ido+2*ncomp+3+1]; |
// calculate negative increment of stresses due to change in suction (-du = -ds*chi) |
// which will be used in calculation of nodal forces and added to the right hand side vector |
// K*dr = df_e - \int B^T*du dV |
for (i=0;i<3;i++) |
Mm->ip[ipp].eqother[ido+2*ncomp+i] = -ds*dd_gen(i,6); |
//Mm->ip[ipp].eqother[ido+2*ncomp+i] = 0.0; |
} |
/** |
The function computes stress increment due to pore pressure change in the integration point and stores |
them into ip stress array. |
@param lcid - load case id |
@param ipp - integration point number |
@param im - index of the material in the tm and idm arrays on integration point |
@param ido - index of internal variables in the ip's ipp eqother array |
@param fi - first index of the required stress increment component |
@param sig - %vector containing stress increment components (output) |
@return The function returns %vector of stress increments in the parameter sig. |
Created by Tomas Koudelka, 11.2015 |
*/ |
void hypoplast_unsat_exp_therm::givestressincr (long /*lcid*/, long ipp, long /*im*/, long ido, long fi, vector &sig) |
{ |
nullv(sig); |
long i, j, ncomp = Mm->ip[ipp].ncompstr; |
for (i=fi, j=0; i<3 && j<sig.n; i++, j++) |
sig(j) = Mm->ip[ipp].eqother[ido+2*ncomp+i]; |
} |
/** |
The function computes correct stresses in the integration point and stores |
them into ip stress array. |
@param ipp - integration point pointer |
@param im - index of material type for given ip |
@param ido - index of internal variables for given material in the ipp other array |
@return The function does not return anything. |
Created by Tomas Koudelka, 1.10.2015 |
*/ |
void hypoplast_unsat_exp_therm::nlstresses (long ipp, long /*im*/, long ido) |
{ |
long i, j, rkf_stat; |
// long herr; |
// data handled by MEFEL |
long ncomp = Mm->ip[ipp].ncompstr; |
long neval = long(Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+5]); |
strastrestate ssst = Mm->ip[ipp].ssst; |
double aux, dtsub, sro; |
double pnewdt = 1.0; // reduction coefficient for new time step |
double dtime = Mp->timecon.actualforwtimeincr(); |
vector sig(ASTCKVEC(ngstress)), eps(ASTCKVEC(ngstrain)), deps(ASTCKVEC(ngstrain)); |
vector statev(ASTCKVEC(nstatev)); |
vector epseq(ASTCKVEC(ngstrain)); |
vector sigeq(ASTCKVEC(ngstress)); |
vector stateveq(ASTCKVEC(nstatev)); |
// rktype rkt = sra.give_rkt(); // type of Runge-Kutta method |
matrix dd_gen(ASTCKMAT(ngstress,ngstrain)); |
// counter of number of steps performed in RKF method within one time step |
long nstep = long(Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+6]); |
// the minimum step length attained in RKF method within one time step |
double mindt = Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+7]; |
// stress array have to contain values from the last attained equilibrium state |
for (i=0; i<ncomp; i++) |
Mm->ip[ipp].stress[i] = Mm->ip[ipp].eqother[ido+ncomp+i]; |
// calculate strain increments and store them in eps temporarily |
for (i=0; i<ncomp; i++) |
eps(i) = Mm->ip[ipp].strain[i]-Mm->ip[ipp].eqother[ido+i]; |
// convert stress, strain and strain increment vectors to full 6 componet vectors |
give_full_vector(sig.a, Mm->ip[ipp].stress, ssst); |
give_full_vector(deps.a, eps.a, ssst); |
nullv(eps); |
give_full_vector(eps.a, Mm->ip[ipp].eqother+ido, ssst); |
// stress vector must be reoredred |
// SIFEL ordering is sig11, sig22, sig33, sig23, sig13, sig12 |
// ABAQUS ordering is sig11, sig22, sig33, sig12, sig13, sig23 |
aux = sig(3); |
sig(3) = sig(5); |
sig(5) = aux; |
// strain vector must be reoredred |
// SIFEL ordering is eps11, eps22, eps33, gamma23, gamma13, gamma12 |
// ABAQUS ordering is eps11, eps22, eps33, gamma12, gamma13, gamma23 |
aux = eps(3); |
eps(3) = eps(5); |
eps(5) = aux; |
// strain increment vector must be reoredred |
// SIFEL ordering is deps11, deps22, deps33, dgamma23, dgamma13, dgamma12 |
// ABAQUS ordering is deps11, deps22, deps33, dgamma12, dgamma13, dgamma23 |
aux = deps(3); |
deps(3) = deps(5); |
deps(5) = aux; |
// assemble generalized strain |
eps(6) = Mm->ip[ipp].eqother[ido+2*ncomp+3+1]; // suction from the previous time step |
eps(7) = Mm->ip[ipp].eqother[ido+2*ncomp+3+3]; // temperature from the previous time step |
// assemble generalized stress vector |
sro = sig(6) = Mm->ip[ipp].eqother[ido+2*ncomp+3+2]; // degree of saturation Sr from the previous time step |
// assemble generalized strain increment vector |
if (pr_suc_fl == yes) //prescribed suction pressure s (positive) |
deps(6) = suc_fn.getval(Mp->time) - Mm->ip[ipp].eqother[ido+2*ncomp+3+1]; // suction increment ds |
else |
deps(6) = Mm->givenonmechq(suction, ipp) - Mm->ip[ipp].eqother[ido+2*ncomp+3+1]; // suction pressure increment ds |
if (pr_tempr_fl == yes) //prescribed temperature T |
deps(7) = tempr_fn.getval(Mp->time) - Mm->ip[ipp].eqother[ido+2*ncomp+3+3]; // temperature increment dT |
else |
deps(7) = Mm->givenonmechq(temperature, ipp) - Mm->ip[ipp].eqother[ido+2*ncomp+3+3]; // temperature increment dT |
// prepare working copy of internal variables from the last equilibrium state |
for (i=ido+2*ncomp+3, j=0; i<ido+2*ncomp+3+nstatev; i++, j++) |
statev(j) = Mm->ip[ipp].eqother[i]; |
dtsub = Mm->ip[ipp].eqother[ido+2*ncomp+3+nstatev]; |
// create copy of strain, stress and state variable vectors from the last equilibrium state |
copyv(eps, epseq); |
copyv(sig, sigeq); |
copyv(statev, stateveq); |
// compute new values of stress vector and state variable increments |
vector rkf_statev(ASTCKVEC(nrkfstatev)); |
rkf_statev[0] = Mm->ip[ipp].eqother[ido+2*ncomp+3+nstatev+5]; |
rkf_statev[1] = Mm->ip[ipp].eqother[ido+2*ncomp+3+nstatev+6]; |
rkf_statev[2] = Mm->ip[ipp].eqother[ido+2*ncomp+3+nstatev+7]; |
rkf_statev[3] = Mm->ip[ipp].eqother[ido+2*ncomp+3+nstatev]; |
rkf_stat = huet.soil_model(eps.a, sig.a, statev.a, deps.a, dtime, dd_gen.a, NULL, rkf_statev.a, rkfparams, 1, Mp->jstep, ipp); |
// actualize RKF state variables |
neval = long(rkf_statev[0]); |
nstep = long(rkf_statev[1]); |
mindt = rkf_statev[2]; |
dtsub = rkf_statev[3]; |
// store 'consistent' material stiffness matrix |
copym(dd_gen, Mm->ip[ipp].other+ido+2*ncomp+3+nstatev+12); |
/* |
switch (rkt) |
{ |
case fwdeulert: |
{ |
vector dsig(ASTCKVEC(ngstress)); |
vector dstatev(ASTCKVEC(nstatev)); |
rkf_stat = huet.soil_model(eps.a, sig.a, statev.a, deps.a, dsig.a, dstatev.a, NULL, NULL, 2, Mp->jstep); |
addv(sig, dsig, sig); |
addv(statev, dstatev, statev); |
neval += 1; |
nstep += 1; |
mindt = 1.0; |
break; |
} |
case heunt: |
rkf_stat = adfwdeuler(eps, sig, statev, deps, dtsub, neval, nstep, mindt); |
break; |
case rkf23t: |
rkf_stat = rkf23(ipp, eps, sig, statev, deps, dtsub, neval, nstep, mindt); |
break; |
case rkf23bst: |
rkf_stat = rkf23bs(eps, sig, statev, deps, dtsub, neval, nstep, mindt); |
break; |
case rkf34t: |
rkf_stat = rkf34(eps, sig, statev, deps, dtsub, neval, nstep, mindt); |
break; |
case rkf45t: |
rkf_stat = rkf45(eps, sig, statev, deps, dtsub, neval, nstep, mindt); |
break; |
default: |
print_err("unknown Runge-Kutta method is required", __FILE__, __LINE__, __func__); |
} |
*/ |
if (rkf_stat){ |
fprintf(Out, "\nRKF failed - rkf_stat=%ld, element=%ld, ip=%ld, loc_ip=%ld, istep=%ld, jstep=%ld, dt=%le", |
rkf_stat, Mm->elip[ipp], ipp, ipp-Mt->elements[Mm->elip[ipp]].ipp[0][0]+1, Mp->istep, Mp->jstep, Mp->timecon.actualforwtimeincr()); |
fprintf(Out, "\nsig\n"); |
printv(Out, sig); |
fprintf(Out, "\neps\n"); |
printv(Out, eps); |
fprintf(Out, "\ndeps\n"); |
printv(Out, deps); |
fprintf(Out, "\nstatev\n"); |
printv(Out, statev); |
fprintf(Out, "\n\n"); |
pnewdt = 0.5; // RKF was not able integrate quantities with required error => decrease time step in the solver |
} |
// stress vector must be reoredred to SIFEL notation |
// SIFEL ordering is sig11, sig22, sig33, sig23, sig13, sig12 |
// ABAQUS ordering is sig11, sig22, sig33, sig12, sig13, sig23 |
aux = sig(3); |
sig(3) = sig(5); |
sig(5) = aux; |
// store stress in reduced notation to the integration point |
give_red_vector(sig.a, Mm->ip[ipp].stress, ssst); |
// actual value of generalized strain vector |
// addv(eps,deps,eps); |
// store actual value of strain vector |
Mm->storeother(ipp, ido, ncomp, Mm->ip[ipp].strain); |
// store actual value of stress vector |
Mm->storeother(ipp, ido+ncomp, ncomp, Mm->ip[ipp].stress); |
// store actual value of state variables |
Mm->storeother(ipp, ido+2*ncomp+3, nstatev, statev.a); |
// store actual value of suction |
Mm->ip[ipp].other[ido+2*ncomp+3+1] = eps(6); |
// store actual value of temperature |
Mm->ip[ipp].other[ido+2*ncomp+3+3] = eps(7); |
// store actual value of RK substep coefficient |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev]= dtsub; |
// store actual value of time step coefficient |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+1]= pnewdt; |
// store actual number of model evaluation - only for testing purposes |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+5]= neval; |
// store actual number of performed RKF steps - only for testing purposes |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+6]= nstep; |
// store the minimum RKF step length - only for testing purposes |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+7]= mindt; |
// volumetric strain rate is computed via generalized trapesoidal rule |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+10]= 0.5*((deps(0)+deps(1)+deps(2))/dtime + Mm->ip[ipp].eqother[ido+2*ncomp+3+nstatev+10]); |
// volumetric strain rate |
//Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+10]= (deps(0)+deps(1)+deps(2))/dtime; |
/* |
// assemble non-mechanical blocks (all except of sig-eps block) of generalized stiffness matrix |
herr = huet.soil_model(epseq.a, sigeq.a, stateveq.a, NULL, NULL, NULL, dd_gen.a, NULL, 3, Mp->jstep); |
if (herr) |
{ |
print_err("generalized stiffness matrix cannot be assembled on element %ld (ip=%ld)", __FILE__, __LINE__, __func__, Mm->elip[ipp]+1, ipp+1); |
abort(); |
} |
// store derivatives of degree of saturation Sr |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+8] = dd_gen(ngstress-1, ngstrain-2); // store dSr/ds matrix component |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+9] = dd_gen(ngstress-1, ngstrain-1); // store dSr/dT matrix component |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+11] = dd_gen(ngstress-1, 0)+dd_gen(ngstress-1, 1)+dd_gen(ngstress-1, 2); // compute and store dSr/depsv from matrix components |
*/ |
// calculate additional quantities used for output of results |
double epsv; |
// calculate volumetric strain |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+2]= epsv = eps(0)+eps(1)+eps(2); |
// suction increment |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+3]= eps(6)-Mm->ip[ipp].eqother[ido+2*ncomp+3+1]; |
// depsV |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+4]= deps(0)+deps(1)+deps(2); |
/* |
// calculate strain deviator |
epsv *= 1.0/3.0; |
eps(0) -= epsv; |
eps(1) -= epsv; |
eps(2) -= epsv; |
deviator(eps, eps); |
// vertical strain deviator component |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+3]= eps(1); |
// calculate stress deviator |
deviator(sig, sig); |
// vertical stress deviator component |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+4]= sig(1); |
*/ |
} |
/** |
The function reduces step length in Runge-Kutta-Fehlberg methods according to given |
coefficient and minimum step length. |
@param rc - reduction coefficient of step length (input) |
@param h - actual/modified step length (input/output) |
@param hmin - minimum step length (input) |
@retval 0 - On sucessfull step reduction. |
@retval 1 - The minimum step length has been attained and the step cannot be reduced further. |
Created by Tomas Koudelka, 24.5.2016 |
*/ |
long hypoplast_unsat_exp_therm::rkf_redstep(double rc, double &h, double hmin) |
{ |
if (h > hmin) |
{ |
h *= rc; |
if (h < hmin) |
h = hmin; |
return 0; |
} |
else |
return 1; |
} |
/** |
The function returns time step size required by the hypoplsaticity model. It is represented by ratio |
of required time step size to the actual one or 1.0 for no change in time step size. |
@param ipp - integration point number in the mechmat ip array. |
@param im - index of material type for given ip |
@param ido - index of internal variables for given material in the ipp other array |
@return The function returns required time step size provided by the hypoplasticity model |
Created by Tomas Koudelka, 1.10.2015 |
*/ |
double hypoplast_unsat_exp_therm::dstep_red(long ipp, long /*im*/, long ido) |
{ |
long ncomp = Mm->ip[ipp].ncompstr; |
return (Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+1]); |
} |
/** |
Function updates values in the other array reached in the previous equlibrium state to |
values reached in the new actual equilibrium state. |
@param ipp - integration point number in the mechmat ip array. |
@param im - index of material type for given ip |
@param ido - index of internal variables for given material in the ipp other array |
@return The function does not return anything. |
Created by Tomas Koudelka, 1.10.2015 |
*/ |
void hypoplast_unsat_exp_therm::updateval (long ipp,long im,long ido) |
{ |
long i, j; |
// long herr; |
long n = Mm->givencompeqother(ipp,im); |
long ncomp = Mm->ip[ipp].ncompstr; |
strastrestate ssst = Mm->ip[ipp].ssst; |
double aux; |
vector sigeq(ASTCKVEC(ngstress)); |
vector epseq(ASTCKVEC(ngstrain)); |
vector stateveq(ASTCKVEC(nstatev)); |
// matrix dd_gen(ASTCKMAT(ngstress,ngstrain)); |
// convert stress, strain and strain increment vectors to full 6 componet vectors |
give_full_vector(epseq.a, Mm->ip[ipp].strain, ssst); |
give_full_vector(sigeq.a, Mm->ip[ipp].stress, ssst); |
// stress vector must be reoredred |
// SIFEL ordering is sig11, sig22, sig33, sig23, sig13, sig12 |
// ABAQUS ordering is sig11, sig22, sig33, sig12, sig13, sig23 |
aux = sigeq(3); |
sigeq(3) = sigeq(5); |
sigeq(5) = aux; |
// strain vector must be reoredred |
// SIFEL ordering is eps11, eps22, eps33, gamma23, gamma13, gamma12 |
// ABAQUS ordering is eps11, eps22, eps33, gamma12, gamma13, gamma23 |
aux = epseq(3); |
epseq(3) = epseq(5); |
epseq(5) = aux; |
// assemble generalized strain increment vector |
if (pr_suc_fl == yes) //prescribed suction pressure s (positive) |
epseq(6) = suc_fn.getval(Mp->time); // suction s defined by user function |
else |
epseq(6) = Mm->givenonmechq(suction, ipp); // suction s from TRFEL |
if (pr_tempr_fl == yes) //prescribed temperature T |
epseq(7) = tempr_fn.getval(Mp->time); // temperature T defined by user function |
else |
epseq(7) = Mm->givenonmechq(temperature, ipp); // temperature T from TRFEL |
// assemble generalized stress vector |
sigeq(6) = Mm->ip[ipp].other[ido+2*ncomp+3+2]; // actual degree of saturation Sr |
// prepare working copy of internal variables from the last equilibrium state |
for (i=ido+2*ncomp+3, j=0; i<ido+2*ncomp+3+nstatev; i++, j++) |
stateveq(j) = Mm->ip[ipp].other[i]; |
/* |
// assemble non-mechanical blocks (all except of sig-eps block) of generalized stiffness matrix |
herr = huet.soil_model(epseq.a, sigeq.a, stateveq.a, NULL, NULL, NULL, dd_gen.a, NULL, 3, Mp->jstep); |
if (herr) |
{ |
print_err("generalized stiffness matrix cannot be assembled on element %ld (ip=%ld)", __FILE__, __LINE__, __func__, Mm->elip[ipp]+1, ipp+1); |
abort(); |
} |
// store derivatives of degree of saturation Sr |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+8] = dd_gen(ngstress-1, ngstrain-2); // store dSr/ds matrix component |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+9] = dd_gen(ngstress-1, ngstrain-1); // store dSr/dT matrix component |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+11] = dd_gen(ngstress-1, 0)+dd_gen(ngstress-1, 1)+dd_gen(ngstress-1, 2); // compute dSr/depsv from matrix components |
*/ |
matrix dd_gen; |
makerefm(dd_gen, Mm->ip[ipp].other+ido+2*ncomp+3+nstatev+12, ngstress, ngstrain); |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+8] = dd_gen(ngstress-1, ngstrain-2); // store dSr/ds matrix component |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+9] = dd_gen(ngstress-1, ngstrain-1); // store dSr/dT matrix component |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+11] = dd_gen(ngstress-1, 0);//+dd_gen(ngstress-1, 1)+dd_gen(ngstress-1, 2); // compute dSr/depsv from matrix components |
// copy internal variables from working array to the equilibrium array |
for (i=0;i<n;i++) |
Mm->ip[ipp].eqother[ido+i]=Mm->ip[ipp].other[ido+i]; |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+5] = 0; // zero neval at the end of actual time step |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+6] = 0; // zero nstep at the end of actual time step |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+7] = 1.0; // set mindt to 1 at the end of actual time step |
} |
/** |
The funtion marks required non-mechanical quantities in the array anmq. |
@param anmq - array with flags for used material types |
anmq[i] = 1 => qunatity type nonmechquant(i+1) is required |
anmq[i] = 0 => qunatity type nonmechquant(i+1) is not required |
@return The function does not return anything, but it may change content of anmq array. |
Created by Tomas Koudelka, 1.10.2015 |
*/ |
void hypoplast_unsat_exp_therm::give_reqnmq(long *anmq) |
{ |
// anmq[saturation_degree-1] = 1; |
if (pr_suc_fl == no) |
anmq[suction-1] = 1; |
if (pr_tempr_fl == no) |
anmq[temperature-1] = 1; |
} |
/** |
The function returns the number of eqother array componets of the material model. |
@param ipp - integration point number in the mechmat ip array. |
@retval The function returns value of |
Created by Tomas Koudelka, 4.3.2019 |
*/ |
long hypoplast_unsat_exp_therm::givencompeqother(long ipp) |
{ |
long ncompstr = Mm->ip[ipp].ncompstr; |
return 2*ncompstr+3+nstatev+12+ngstress*ngstrain; |
} |
/** |
The function extracts actual degree of saturation for the actual attained state. |
@param ipp - integration point number in the mechmat ip array. |
@param ido - index of internal variables for given material in the ipp other array |
@retval The function returns value of actual degree of saturation Sr. |
Created by Tomas Koudelka, 25.5.2016 |
*/ |
double hypoplast_unsat_exp_therm::give_sr(long ipp, long ido) |
{ |
long ncompstr = Mm->ip[ipp].ncompstr; |
return Mm->ip[ipp].other[ido+2*ncompstr+3+2]; |
} |
/** |
The function computes actual derivative of degree of saturation with respect to suction |
for the actual attained state. |
@param ipp - integration point number in the mechmat ip array. |
@param ido - index of internal variables for given material in the ipp other array |
@retval The function returns value of derivative of actual degree of saturation with respect to suction dSr/ds. |
Created by Tomas Koudelka, 25.5.2016 |
*/ |
double hypoplast_unsat_exp_therm::give_dsr_ds(long ipp, long ido) |
{ |
long ncomp = Mm->ip[ipp].ncompstr; |
double dsr = Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+8]; |
return dsr; |
} |
/** |
The function computes actual derivative of degree of saturation with respect to temperature |
for the actual attained state. |
@param ipp - integration point number in the mechmat ip array. |
@param ido - index of internal variables for given material in the ipp other array |
@retval The function returns value of derivative of actual degree of saturation with respect to suction dSr/ds. |
Created by Tomas Koudelka, 29.6.2017 |
*/ |
double hypoplast_unsat_exp_therm::give_dsr_dtemp(long ipp, long ido) |
{ |
long ncomp = Mm->ip[ipp].ncompstr; |
double dsr = Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+9]; |
return dsr; |
} |
/** |
The function computes actual derivative of degree of saturation with respect to volumetric strain |
for the attained equilibrium state. |
@param ipp - integration point number in the mechmat ip array. |
@param ido - index of internal variables for given material in the ipp other array |
@retval The function returns value of derivative of actual degree of saturation with respect to suction dSr/ds. |
Created by Tomas Koudelka, 29.6.2018 |
*/ |
double hypoplast_unsat_exp_therm::give_dsr_depsv(long ipp, long ido) |
{ |
long ncomp = Mm->ip[ipp].ncompstr; |
double dsr = Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+11]; |
return dsr; |
} |
/** |
The function extracts actual porosity for the actual attained state. |
@param ipp - integration point number in the mechmat ip array. |
@param ido - index of internal variables for given material in the ipp other array |
@retval The function returns value of actual porosity. |
Created by Tomas Koudelka, 25.5.2016 |
*/ |
double hypoplast_unsat_exp_therm::give_porosity(long ipp, long ido) |
{ |
long ncompstr = Mm->ip[ipp].ncompstr; |
double e = Mm->ip[ipp].other[ido+2*ncompstr+3]; // actual void ratio |
return (e/(1.0+e)); |
} |
/** |
The function extracts actual void ratio for the actual attained state. |
@param ipp - integration point number in the mechmat ip array. |
@param ido - index of internal variables for given material in the ipp other array |
@retval The function returns value of actual porosity e. |
Created by Tomas Koudelka, 25.5.2016 |
*/ |
double hypoplast_unsat_exp_therm::give_void_ratio(long ipp, long ido) |
{ |
long ncompstr = Mm->ip[ipp].ncompstr; |
return Mm->ip[ipp].other[ido+2*ncompstr+3]; |
} |
/** |
The function returns rate of the volumetric strain at the given integration point. |
@param ipp - integration point number in the mechmat ip array. |
@param ido - index of internal variables for given material in the ipp other array |
@return The function returns rate of the volumetric strain. |
Created by Tomas Koudelka 05.2018 |
*/ |
double hypoplast_unsat_exp_therm::give_strain_vol_rate(long ipp, long ido) |
{ |
long ncomp = Mm->ip[ipp].ncompstr; |
return Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+10]; |
} |
/** |
The function returns the bulk modulus from the stored |
tangent stiffness %matrix. |
@param ipp - integration point number in the mechmat ip array. |
@param ido - index of internal variables for given material in the ipp other array |
@return The function returns value of the bulk modulus. |
Created by Tomas Koudelka 09.2023 |
*/ |
double hypoplast_unsat_exp_therm::give_bulk_modulus(long ipp, long ido) |
{ |
long i, ncomp = Mm->ip[ipp].ncompstr; |
matrix d; |
makerefm(d, Mm->ip[ipp].other+ido+2*ncomp+3+nstatev+12, ngstress, ngstrain); |
double k = 0.0; // take average value of oedometric moduli |
for(i=0; i<3; i++) |
k += d(i,0) + d(i,1) + d(i,2); |
k *= 1.0/9.0; |
return k; |
} |
/** |
The function changes material parameters for stochastic analysis. |
@param atm - selected material parameters (parameters which are changed) |
@param val - array containing new values of parameters |
@return The function does not return anything. |
Created by Tomas Koudelka, 30.1.2014 |
*/ |
void hypoplast_unsat_exp_therm::changeparam (atsel &atm,vector &val) |
{ |
long i; |
for (i=0;i<atm.num;i++){ |
switch (atm.atrib[i]){ |
case 0:{ |
phideg=val[i]; |
break; |
} |
case 1:{ |
lam_star=val[i]; |
break; |
} |
case 2:{ |
kap_star=val[i]; |
break; |
} |
case 3:{ |
n_star=val[i]; |
break; |
} |
case 4:{ |
nu=val[i]; |
break; |
} |
case 5:{ |
n=val[i]; |
break; |
} |
case 6:{ |
l=val[i]; |
break; |
} |
case 7:{ |
nt=val[i]; |
break; |
} |
case 8:{ |
lt=val[i]; |
break; |
} |
case 9:{ |
m=val[i]; |
break; |
} |
case 10:{ |
alpha_s=val[i]; |
break; |
} |
case 11:{ |
kap_m=val[i]; |
break; |
} |
case 12:{ |
sm_star=val[i]; |
break; |
} |
case 13:{ |
em_star=val[i]; |
break; |
} |
case 14:{ |
s_airentry0=val[i]; |
break; |
} |
case 15:{ |
em0=val[i]; |
break; |
} |
case 16:{ |
tr=val[i]; |
break; |
} |
case 17:{ |
at=val[i]; |
break; |
} |
case 18:{ |
bt=val[i]; |
break; |
} |
case 19:{ |
aer=val[i]; |
break; |
} |
case 20:{ |
p_t=val[i]; |
break; |
} |
default:{ |
fprintf (stderr,"\n\n wrong number of atribute in function changeparam (file %s, line %d).\n",__FILE__,__LINE__); |
} |
} |
} |
} |
#include <stdlib.h> |
#include <float.h> |
#include "generalmod.h" |
#include "global.h" |
#include "probdesc.h" |
#include "mechmat.h" |
#include "mechtop.h" |
#include "intpoints.h" |
#include "element.h" |
#include "tensor.h" |
#include "vecttens.h" |
#include "mathem.h" |
#include "vector.h" |
#include "vecttens.h" |
#include "hypoplunsatexptherm2.h" |
#define nijac 200 |
#define limit 1.0e-15 // zero limit for principal values of tensors (Jacobi method) |
hypoplast_unsat_exp_therm::hypoplast_unsat_exp_therm() |
{ |
phideg = lam_star = kap_star = n_star = 0.0; |
nu = n = l = nt = lt = m = alpha_s = kap_m = sm_star = 0.0; |
em_star = s_airentry0 = em0 = tr = at = bt = lambdap0 = aer = p_t = 0.0; |
// retrieve number of parameters, number of state variables and number of generalized vector components |
nparams=huet.nparms; // number of parameters |
nstatev=huet.nstatev; // number of state variables (10 for actual implementation, see constructor in generalmod.h) |
ngstrain=huet.ngstrain; // number of generalised strain tensor components (8 for actual implementation, see constructor in generalmod.h) |
ngstress=huet.ngstress; // number of generalised stress tensor components (7 for actual implementation, see constructor in generalmod.h) |
nrkfparams=huet.nrkf_parms; // number of RKF method parameters |
nrkfstatev=huet.nrkf_statev; // number of RKF method parameters |
params = new double[nparams]; |
rkfparams = new double[nrkfparams]; |
pr_suc_fl = no; |
pr_tempr_fl = no; |
// maximum value of 'zero' level of state variables for RKF time integration |
// it may be rewritten by RKF tolerance if its value is less than the value specified here |
sv_rkf_zero = 1.0e-3; |
} |
hypoplast_unsat_exp_therm::~hypoplast_unsat_exp_therm() |
{ |
delete [] params; |
delete [] rkfparams; |
} |
/** |
The function reads material parameters from the opened text file given |
by the parameter in. |
@param in - pointer to the opened input text file |
@return The function does not return anything. |
Created by Tomas Koudelka, 30.1.2014 |
*/ |
void hypoplast_unsat_exp_therm::read(XFILE *in) |
{ |
xfscanf(in, "%k %le %k %le %k %le %k %le", |
"phi", &phideg, "lam_star", &lam_star, |
"kap_star", &kap_star, "N_star", &n_star); |
xfscanf(in, "%k %le %k %le %k %le %k %le %k %le %k %le", |
"nu", &nu, "n", &n, "l", &l, "nT", &nt, "lT", <, "m", &m); |
xfscanf(in, "%k %le %k %le %k %le %k %le %k %le %k %le %k %le", |
"alpha_s", &alpha_s, "kap_m", &kap_m, "sm_star", &sm_star, |
"em_star", &em_star, "csh", &csh, "s_airentry0", &s_airentry0, "em0", &em0); |
xfscanf(in, "%k %le %k %le %k %le %k %le %k %le %k %le", |
"tr", &tr, "at", &at, "bt", &bt, |
"aer", &aer, "lambdap0", &lambdap0, "p_t", &p_t); |
// xfscanf(in, "%k %le %k %le","einit", &einit, "ascaninit", &ascaninit); |
xfscanf(in, "%k%m", "presc_suction", &answertype_kwdset, &pr_suc_fl); |
if (pr_suc_fl == yes) |
suc_fn.read(in); |
xfscanf(in, "%k%m", "presc_tempr", &answertype_kwdset, &pr_tempr_fl); |
if (pr_tempr_fl == yes) |
tempr_fn.read(in); |
sra.read(in); |
if (sv_rkf_zero > sra.err) |
sv_rkf_zero = sra.err; |
if (phideg <= 0.0) |
{ |
print_err("phi must be positive (phi = %le)", __FILE__, __LINE__, __func__, phideg); |
abort(); |
} |
if (p_t < 0.0) |
{ |
print_err("p_t must not be negative (p_t = %le)", __FILE__, __LINE__, __func__, p_t); |
abort(); |
} |
if (lam_star <= 0.0) |
{ |
print_err("lam_star must be positive (lam_star = %le)", __FILE__, __LINE__, __func__, lam_star); |
abort(); |
} |
if (kap_star <= 0.0) |
{ |
print_err("kap_star must be positive (kap_star = %le)", __FILE__, __LINE__, __func__, kap_star); |
abort(); |
} |
if (n_star <= 0.0) |
{ |
print_err("n_star must be positive (n_star = %le)", __FILE__, __LINE__, __func__, n_star); |
abort(); |
} |
// temporary check for Mock-up test |
if (aer != 1.0) |
{ |
print_err("temporary check for Mock-up experiment - aer is not set to 1.0 (aer = %le)", __FILE__, __LINE__, __func__, aer); |
abort(); |
} |
// temporary check for Mock-up test |
if (aer != 1.0) |
{ |
print_err("temporary check for Mock-up experiment - aer is not set to 1.0 (aer = %le)", __FILE__, __LINE__, __func__, aer); |
abort(); |
} |
/* |
if (rr <= 0.0) |
{ |
print_err("rr must be positive (rr = %le)", __FILE__, __LINE__, __func__, rr); |
abort(); |
} |
if (s_e0 < 0.0) |
{ |
print_err("s_e0 must not be negative (s_e0 = %le)", __FILE__, __LINE__, __func__, s_e0); |
abort(); |
} |
*/ |
params[0] = phideg; |
params[1] = lam_star; |
params[2] = kap_star; |
params[3] = n_star; |
params[4] = nu; |
params[5] = n; |
params[6] = l; |
params[7] = nt; |
params[8] = lt; |
params[9] = m; |
params[10] = alpha_s; |
params[11] = kap_m; |
params[12] = sm_star; |
params[13] = em_star; |
params[14] = csh; |
params[15] = s_airentry0; |
params[16] = em0; |
params[17] = tr; |
params[18] = at; |
params[19] = bt; |
params[20] = aer; |
params[21] = lambdap0; |
params[22] = p_t; |
//params[21] = einit; |
//params[22] = ascaninit; |
rkfparams[0] = sra.give_err_sig(); |
rkfparams[1] = sra.give_hmin(); |
rkfparams[2] = sra.give_ni(); |
rkfparams[3] = sv_rkf_zero; |
rkfparams[4] = (int)sra.give_rkt(); |
} |
/** |
The function prints material parameters into the opened text file given |
by the parameter out. |
@param out - pointer to the opened output text file |
@return The function does not return anything. |
Created by Tomas Koudelka, koudelka@cml.fsv.cvut.cz, 17.12.2015 |
*/ |
void hypoplast_unsat_exp_therm::print(FILE *out) |
{ |
fprintf(out, "%le %le %le %le\n", |
phideg, lam_star, kap_star, n_star); |
fprintf(out, "%le %le %le %le %le %le\n", |
nu, n, l, nt, lt, m); |
fprintf(out, "%le %le %le %le %le %le %le\n", |
alpha_s, kap_m, sm_star, em_star, csh, s_airentry0, em0); |
fprintf(out, "%le %le %le %le %le %le\n",tr, at, bt, aer, lambdap0, p_t); |
fprintf(out, "%d ", int(pr_suc_fl)); |
if (pr_suc_fl == yes) |
suc_fn.print(out); |
fprintf(out, "%d ", int(pr_tempr_fl)); |
if (pr_tempr_fl == yes) |
tempr_fn.print(out); |
fprintf(out, "\n"); |
sra.print(out); |
} |
/** |
The function initializes material model. Retrieves initial values of the following |
quantities |
@param ipp - integration point number |
@param ido - index of internal variables for given material in the ipp other array |
@return The function does not return anything but updates initial value of Sr and stress vector |
in eqother array. |
Created by Tomas Koudelka, 1.10.2015 |
*/ |
void hypoplast_unsat_exp_therm::initval (long ipp,long ido) |
{ |
// data handled by MEFEL |
long ncomp = Mm->ip[ipp].ncompstr; // number of reduced stress/strain components |
strastrestate ssst = Mm->ip[ipp].ssst; // stress/strain state indicator |
vector sig(ASTCKVEC(ngstress)), eps(ASTCKVEC(ngstrain)); |
vector deps(ASTCKVEC(ngstrain)), dstatev(ASTCKVEC(nstatev)); |
matrix dd_gen(ASTCKMAT(ngstress,ngstrain)); |
double *statev = Mm->ip[ipp].eqother+ido+2*ncomp+3; |
int herr; |
if (statev[0] == 0.0) // initial void ratio was not set => model has not been initialized yet |
{ |
statev[0] = Mm->ic[ipp][0]; // initialize actual value of void ratio |
statev[7] = Mm->ic[ipp][1]; // initialize actual value of ascan |
// set initial value of effective stresses from eigenstresses |
// eigenstress is assumed to be net stress, i.e. sig_{net} = sig_{tot} - u_a.I |
if ((Mp->eigstrains == 4) || (Mp->eigstrains == 5)) |
{ |
for (long i=0; i<ncomp; i++) |
{ |
Mm->ip[ipp].eqother[ido+ncomp+i] = Mm->eigstresses[ipp][i]; |
Mm->ip[ipp].stress[i] = Mm->eigstresses[ipp][i]; |
} |
} |
} |
if (pr_suc_fl == yes) |
statev[1] = suc_fn.getval(Mp->time); //initial prescribed suction pressure s (positive) |
else |
statev[1] = Mm->givenonmechq(suction, ipp); // initial suction pressure s (positive) |
statev[2] = 0.0; // initial degree of saturation S_r |
if (pr_tempr_fl == yes) |
statev[3] = tempr_fn.getval(Mp->time); //initial prescribed temperature |
else |
statev[3] = Mm->givenonmechq(temperature, ipp); // initial temperature T |
give_full_vector(sig.a, Mm->ip[ipp].stress, ssst); |
give_full_vector(eps.a, Mm->ip[ipp].strain, ssst); |
// set remaining components of generalized strain vector |
eps(6) = statev[1]; // set suction to the corresponding component of generalized strain vector |
eps(7) = statev[3]; // set temperature to the corresponding component of generalized strain vector |
// initialize model |
herr = huet.soil_model(eps.a, sig.a, statev, deps.a, 1.0, NULL, params, NULL, rkfparams, 0, Mp->jstep, ipp); |
if (herr) |
{ |
print_err("hypoplasticity model cannot be initialized on element %ld (ip=%ld)", __FILE__, __LINE__, __func__, Mm->elip[ipp]+1, ipp+1); |
abort(); |
} |
statev[2] = sig(6); // store computed initial Sr |
// prepare working copy of array of internal variables |
// eqother values have been already set because statev array is a reference to the eqother array |
copyv(statev, Mm->ip[ipp].other+ido+2*ncomp+3, nstatev); |
// set initial values for dSr/ds and dSr/dT according to generalized stiffness matrix |
herr = huet.soil_model(eps.a, sig.a, statev, NULL, 1.0, dd_gen.a, params, NULL, rkfparams, 3, Mp->jstep, ipp); |
if (herr) |
{ |
print_err("generalized stiffness matrix cannot be initialized on element %ld (ip=%ld)", __FILE__, __LINE__, __func__, Mm->elip[ipp]+1, ipp+1); |
abort(); |
} |
Mm->ip[ipp].eqother[2*ncomp+3+nstatev+8] = dd_gen(ngstress-1, ngstrain-2); // store dSr/ds matrix component |
Mm->ip[ipp].eqother[2*ncomp+3+nstatev+9] = dd_gen(ngstress-1, ngstrain-1); // store dSr/dT matrix component |
Mm->ip[ipp].eqother[ido+2*ncomp+3+nstatev+11] = dd_gen(ngstress-1, 0);//+dd_gen(ngstress-1, 1)+dd_gen(ngstress-1, 2); // compute and store dSr/depsv from matrix components |
// actualize 'consistent' material stiffness matrix |
copym(dd_gen, Mm->ip[ipp].eqother+ido+2*ncomp+3+nstatev+12); |
// actualize other array by the computed values |
memcpy(Mm->ip[ipp].other, Mm->ip[ipp].eqother, sizeof(*Mm->ip[ipp].other)*Mm->ip[ipp].ncompother); |
} |
/** |
The function computes material stiffnes %matrix. |
@param d - allocated matrix structure for material stiffness %matrix (output) |
@param ipp - integration point number |
@param ido - index of internal variables for given material in the ipp other array |
@return The function returns stiffness %matrix in the parameter d. |
Created by Tomas Koudelka, 1.10.2015 |
*/ |
void hypoplast_unsat_exp_therm::matstiff (matrix &d,long ipp,long /*ido*/) |
{ |
long i; |
// data handled by MEFEL |
long ncomp = Mm->ip[ipp].ncompstr; |
strastrestate ssst = Mm->ip[ipp].ssst; |
double aux; |
matrix dd_gen(ASTCKMAT(ngstress,ngstrain)), dd(ASTCKMAT(6,6)); |
/* |
vector sig(ASTCKVEC(ngstress)), eps(ASTCKVEC(ngstrain)), deps(ASTCKVEC(ngstrain)); |
vector statev(ASTCKVEC(nstatev)); |
int herr; |
long j; |
// convert stress and strain vectors to full 6 component vectors |
give_full_vector(sig.a, Mm->ip[ipp].stress, ssst); |
give_full_vector(eps.a, Mm->ip[ipp].strain, ssst); |
// stress vector must be reoredred |
// SIFEL ordering is sig11, sig22, sig33, sig23, sig13, sig12 |
// ABAQUS ordering is sig11, sig22, sig33, sig12, sig13, sig23 |
aux = sig(3); |
sig(3) = sig(5); |
sig(5) = aux; |
// strain vector must be reoredred |
// SIFEL ordering is eps11, eps22, eps33, gamma23, gamma13, gamma12 |
// ABAQUS ordering is eps11, eps22, eps33, gamma12, gamma13, gamma23 |
aux = eps(3); |
eps(3) = eps(5); |
eps(5) = aux; |
// assemble generalized strain, stress and strain increment vectors |
eps(6) = Mm->ip[ipp].other[ido+2*ncomp+3+1]; // suction from the actual time step |
eps(7) = Mm->ip[ipp].other[ido+2*ncomp+3+3]; // temperature from the actual time step |
sig(6) = Mm->ip[ipp].other[ido+2*ncomp+3+2]; // degree of saturation Sr from the actual time step |
// prepare working copy of internal variables |
for (i=ido+2*ncomp+3, j=0; i<ido+2*ncomp+3+nstatev; i++, j++) |
statev(j) = Mm->ip[ipp].other[i]; |
herr = huet.soil_model(eps.a, sig.a, statev.a, NULL, NULL, NULL, dd_gen.a, NULL, 1, Mp->jstep); |
if (herr) |
{ |
print_err("math error detected in hypoplastic model on element %ld (ip=%ld)", __FILE__, __LINE__, __func__, Mm->elip[ipp]+1, ipp+1); |
abort(); |
} |
*/ |
// retrieve actual generalized material stiffness matrix from the other array |
makerefm(dd_gen, Mm->ip[ipp].other+2*ncomp+3+nstatev+12, ngstress, ngstrain); |
// reorder stiffness matrix in the full-length format |
// |
// swap the fourth and sixth columns except of the fourth and sixth elements |
for (i=0; i<ngstress; i++) |
{ |
if ((i == 3) || (i==5)) |
continue; |
aux = dd_gen(i,3); |
dd_gen(i,3) = dd_gen(i,5); |
dd_gen(i,5) = aux; |
} |
// swap the fourth and sixth rows except of the fourth and sixth elements |
for (i=0; i<ngstrain; i++) |
{ |
if ((i == 3) || (i==5)) |
continue; |
aux = dd_gen(3,i); |
dd_gen(3,i) = dd_gen(5,i); |
dd_gen(5,i) = aux; |
} |
// swap elements on intersections of the fourth and sixth columns and rows |
aux = dd_gen(3,3); |
dd_gen(3,3) = dd_gen(5,5); |
dd_gen(5,5) = aux; |
aux = dd_gen(3,5); |
dd_gen(3,5) = dd_gen(5,3); |
dd_gen(5,3) = aux; |
// extract the stiffness matrix for the mechanics |
extractm(dd, dd_gen, 0, 6); |
// convert stiffness matrix to the reduced format suitable for element stiffness matrix |
tensor4_ematrix (d, dd, ssst); |
} |
/** |
The function computes stress increments due to pore pressure change in the integration point and stores |
them into eqother array. |
@param ipp - integration point pointer |
@param im - index of material type for given ip |
@param ido - index of internal variables for given material in the ipp other array |
@return The function does not return anything but stores the resulting values in the eqother array. |
Created by Tomas Koudelka, 11.2015 |
*/ |
void hypoplast_unsat_exp_therm::nlstressesincr (long ipp, long /*im*/, long ido) |
{ |
long i, j; |
long ncomp = Mm->ip[ipp].ncompstr; |
strastrestate ssst = Mm->ip[ipp].ssst; |
double aux; |
double ds; |
vector sig(ASTCKVEC(ngstress)), eps(ASTCKVEC(ngstrain)); |
vector statev(ASTCKVEC(nstatev)); |
matrix dd_gen; |
//int herr; |
// This procedure is supposed to be called at the beginning of the actual time step |
// and therefore the ip.stress and ip.strain arrays must contain values |
// from the last equilibrium step |
// convert stress and strain vectors to full 6 component vectors |
give_full_vector(sig.a, Mm->ip[ipp].stress, ssst); |
give_full_vector(eps.a, Mm->ip[ipp].strain, ssst); |
// stress vector must be reoredred |
// SIFEL ordering is sig11, sig22, sig33, sig23, sig13, sig12 |
// ABAQUS ordering is sig11, sig22, sig33, sig12, sig13, sig23 |
aux = sig(3); |
sig(3) = sig(5); |
sig(5) = aux; |
// strain vector must be reoredred |
// SIFEL ordering is eps11, eps22, eps33, gamma23, gamma13, gamma12 |
// ABAQUS ordering is eps11, eps22, eps33, gamma12, gamma13, gamma23 |
aux = eps(3); |
eps(3) = eps(5); |
eps(5) = aux; |
// assemble generalized strain, stress and strain increment vectors |
eps(6) = Mm->ip[ipp].eqother[ido+2*ncomp+3+1]; // suction from the previous time step |
eps(7) = Mm->ip[ipp].eqother[ido+2*ncomp+3+3]; // temperature from the previous time step |
sig(6) = Mm->ip[ipp].eqother[ido+2*ncomp+3+2]; // degree of saturation Sr from the previous time step |
// prepare working copy of internal variables |
for (i=ido+2*ncomp+3, j=0; i<ido+2*ncomp+3+nstatev; i++, j++) |
statev(j) = Mm->ip[ipp].eqother[i]; |
// retrieve actual generalized material stiffness matrix from the other array |
makerefm(dd_gen, Mm->ip[ipp].other+2*ncomp+3+nstatev+12, ngstress, ngstrain); |
/* |
reallocm(RSTCKMAT(dd_gen, ngstress,ngstrain)); |
herr = huet.soil_model(eps.a, sig.a, statev.a, NULL, NULL, NULL, dd_gen.a, NULL, 3, Mp->jstep); |
if (herr) |
{ |
print_err("math error detected in hypoplastic model on element %ld (ip=%ld)", __FILE__, __LINE__, __func__, Mm->elip[ipp]+1, ipp+1); |
abort(); |
} |
*/ |
if (pr_suc_fl == yes) //prescribed suction pressure s |
ds = (suc_fn.getval(Mp->time)-Mm->ip[ipp].eqother[ido+2*ncomp+3+1]); //suction pressure increment ds = du_a - du_w |
else // suction is obtained from METR |
ds = Mm->givenonmechq(suction, ipp) - Mm->ip[ipp].eqother[ido+2*ncomp+3+1]; |
// calculate negative increment of stresses due to change in suction (-du = -ds*chi) |
// which will be used in calculation of nodal forces and added to the right hand side vector |
// K*dr = df_e - \int B^T*du dV |
for (i=0;i<3;i++) |
Mm->ip[ipp].eqother[ido+2*ncomp+i] = -ds*dd_gen(i,6); |
//Mm->ip[ipp].eqother[ido+2*ncomp+i] = 0.0; |
} |
/** |
The function computes stress increment due to pore pressure change in the integration point and stores |
them into ip stress array. |
@param lcid - load case id |
@param ipp - integration point number |
@param im - index of the material in the tm and idm arrays on integration point |
@param ido - index of internal variables in the ip's ipp eqother array |
@param fi - first index of the required stress increment component |
@param sig - %vector containing stress increment components (output) |
@return The function returns %vector of stress increments in the parameter sig. |
Created by Tomas Koudelka, 11.2015 |
*/ |
void hypoplast_unsat_exp_therm::givestressincr (long /*lcid*/, long ipp, long /*im*/, long ido, long fi, vector &sig) |
{ |
nullv(sig); |
long i, j, ncomp = Mm->ip[ipp].ncompstr; |
for (i=fi, j=0; i<3 && j<sig.n; i++, j++) |
sig(j) = Mm->ip[ipp].eqother[ido+2*ncomp+i]; |
} |
/** |
The function computes correct stresses in the integration point and stores |
them into ip stress array. |
@param ipp - integration point pointer |
@param im - index of material type for given ip |
@param ido - index of internal variables for given material in the ipp other array |
@return The function does not return anything. |
Created by Tomas Koudelka, 1.10.2015 |
*/ |
void hypoplast_unsat_exp_therm::nlstresses (long ipp, long /*im*/, long ido) |
{ |
long i, j, rkf_stat; |
// long herr; |
// data handled by MEFEL |
long ncomp = Mm->ip[ipp].ncompstr; |
long neval = long(Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+5]); |
strastrestate ssst = Mm->ip[ipp].ssst; |
double aux, dtsub, sro; |
double pnewdt = 1.0; // reduction coefficient for new time step |
double dtime = Mp->timecon.actualforwtimeincr(); |
vector sig(ASTCKVEC(ngstress)), eps(ASTCKVEC(ngstrain)), deps(ASTCKVEC(ngstrain)); |
vector statev(ASTCKVEC(nstatev)); |
vector epseq(ASTCKVEC(ngstrain)); |
vector sigeq(ASTCKVEC(ngstress)); |
vector stateveq(ASTCKVEC(nstatev)); |
// rktype rkt = sra.give_rkt(); // type of Runge-Kutta method |
matrix dd_gen(ASTCKMAT(ngstress,ngstrain)); |
// counter of number of steps performed in RKF method within one time step |
long nstep = long(Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+6]); |
// the minimum step length attained in RKF method within one time step |
double mindt = Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+7]; |
// stress array have to contain values from the last attained equilibrium state |
for (i=0; i<ncomp; i++) |
Mm->ip[ipp].stress[i] = Mm->ip[ipp].eqother[ido+ncomp+i]; |
// calculate strain increments and store them in eps temporarily |
for (i=0; i<ncomp; i++) |
eps(i) = Mm->ip[ipp].strain[i]-Mm->ip[ipp].eqother[ido+i]; |
// convert stress, strain and strain increment vectors to full 6 componet vectors |
give_full_vector(sig.a, Mm->ip[ipp].stress, ssst); |
give_full_vector(deps.a, eps.a, ssst); |
nullv(eps); |
give_full_vector(eps.a, Mm->ip[ipp].eqother+ido, ssst); |
// stress vector must be reoredred |
// SIFEL ordering is sig11, sig22, sig33, sig23, sig13, sig12 |
// ABAQUS ordering is sig11, sig22, sig33, sig12, sig13, sig23 |
aux = sig(3); |
sig(3) = sig(5); |
sig(5) = aux; |
// strain vector must be reoredred |
// SIFEL ordering is eps11, eps22, eps33, gamma23, gamma13, gamma12 |
// ABAQUS ordering is eps11, eps22, eps33, gamma12, gamma13, gamma23 |
aux = eps(3); |
eps(3) = eps(5); |
eps(5) = aux; |
// strain increment vector must be reoredred |
// SIFEL ordering is deps11, deps22, deps33, dgamma23, dgamma13, dgamma12 |
// ABAQUS ordering is deps11, deps22, deps33, dgamma12, dgamma13, dgamma23 |
aux = deps(3); |
deps(3) = deps(5); |
deps(5) = aux; |
// assemble generalized strain |
eps(6) = Mm->ip[ipp].eqother[ido+2*ncomp+3+1]; // suction from the previous time step |
eps(7) = Mm->ip[ipp].eqother[ido+2*ncomp+3+3]; // temperature from the previous time step |
// assemble generalized stress vector |
sro = sig(6) = Mm->ip[ipp].eqother[ido+2*ncomp+3+2]; // degree of saturation Sr from the previous time step |
// assemble generalized strain increment vector |
if (pr_suc_fl == yes) //prescribed suction pressure s (positive) |
deps(6) = suc_fn.getval(Mp->time) - Mm->ip[ipp].eqother[ido+2*ncomp+3+1]; // suction increment ds |
else |
deps(6) = Mm->givenonmechq(suction, ipp) - Mm->ip[ipp].eqother[ido+2*ncomp+3+1]; // suction pressure increment ds |
if (pr_tempr_fl == yes) //prescribed temperature T |
deps(7) = tempr_fn.getval(Mp->time) - Mm->ip[ipp].eqother[ido+2*ncomp+3+3]; // temperature increment dT |
else |
deps(7) = Mm->givenonmechq(temperature, ipp) - Mm->ip[ipp].eqother[ido+2*ncomp+3+3]; // temperature increment dT |
// prepare working copy of internal variables from the last equilibrium state |
for (i=ido+2*ncomp+3, j=0; i<ido+2*ncomp+3+nstatev; i++, j++) |
statev(j) = Mm->ip[ipp].eqother[i]; |
dtsub = Mm->ip[ipp].eqother[ido+2*ncomp+3+nstatev]; |
// create copy of strain, stress and state variable vectors from the last equilibrium state |
copyv(eps, epseq); |
copyv(sig, sigeq); |
copyv(statev, stateveq); |
// compute new values of stress vector and state variable increments |
vector rkf_statev(ASTCKVEC(nrkfstatev)); |
rkf_statev[0] = Mm->ip[ipp].eqother[ido+2*ncomp+3+nstatev+5]; |
rkf_statev[1] = Mm->ip[ipp].eqother[ido+2*ncomp+3+nstatev+6]; |
rkf_statev[2] = Mm->ip[ipp].eqother[ido+2*ncomp+3+nstatev+7]; |
rkf_statev[3] = Mm->ip[ipp].eqother[ido+2*ncomp+3+nstatev]; |
rkf_stat = huet.soil_model(eps.a, sig.a, statev.a, deps.a, dtime, dd_gen.a, NULL, rkf_statev.a, rkfparams, 1, Mp->jstep, ipp); |
// actualize RKF state variables |
neval = long(rkf_statev[0]); |
nstep = long(rkf_statev[1]); |
mindt = rkf_statev[2]; |
dtsub = rkf_statev[3]; |
// store 'consistent' material stiffness matrix |
copym(dd_gen, Mm->ip[ipp].other+ido+2*ncomp+3+nstatev+12); |
/* |
switch (rkt) |
{ |
case fwdeulert: |
{ |
vector dsig(ASTCKVEC(ngstress)); |
vector dstatev(ASTCKVEC(nstatev)); |
rkf_stat = huet.soil_model(eps.a, sig.a, statev.a, deps.a, dsig.a, dstatev.a, NULL, NULL, 2, Mp->jstep); |
addv(sig, dsig, sig); |
addv(statev, dstatev, statev); |
neval += 1; |
nstep += 1; |
mindt = 1.0; |
break; |
} |
case heunt: |
rkf_stat = adfwdeuler(eps, sig, statev, deps, dtsub, neval, nstep, mindt); |
break; |
case rkf23t: |
rkf_stat = rkf23(ipp, eps, sig, statev, deps, dtsub, neval, nstep, mindt); |
break; |
case rkf23bst: |
rkf_stat = rkf23bs(eps, sig, statev, deps, dtsub, neval, nstep, mindt); |
break; |
case rkf34t: |
rkf_stat = rkf34(eps, sig, statev, deps, dtsub, neval, nstep, mindt); |
break; |
case rkf45t: |
rkf_stat = rkf45(eps, sig, statev, deps, dtsub, neval, nstep, mindt); |
break; |
default: |
print_err("unknown Runge-Kutta method is required", __FILE__, __LINE__, __func__); |
} |
*/ |
if (rkf_stat){ |
fprintf(Out, "\nRKF failed - rkf_stat=%ld, element=%ld, ip=%ld, loc_ip=%ld, istep=%ld, jstep=%ld, dt=%le", |
rkf_stat, Mm->elip[ipp], ipp, ipp-Mt->elements[Mm->elip[ipp]].ipp[0][0]+1, Mp->istep, Mp->jstep, Mp->timecon.actualforwtimeincr()); |
fprintf(Out, "\nsig\n"); |
printv(Out, sig); |
fprintf(Out, "\neps\n"); |
printv(Out, eps); |
fprintf(Out, "\ndeps\n"); |
printv(Out, deps); |
fprintf(Out, "\nstatev\n"); |
printv(Out, statev); |
fprintf(Out, "\n\n"); |
pnewdt = 0.5; // RKF was not able integrate quantities with required error => decrease time step in the solver |
} |
// stress vector must be reoredred to SIFEL notation |
// SIFEL ordering is sig11, sig22, sig33, sig23, sig13, sig12 |
// ABAQUS ordering is sig11, sig22, sig33, sig12, sig13, sig23 |
aux = sig(3); |
sig(3) = sig(5); |
sig(5) = aux; |
// store stress in reduced notation to the integration point |
give_red_vector(sig.a, Mm->ip[ipp].stress, ssst); |
// actual value of generalized strain vector |
// addv(eps,deps,eps); |
// store actual value of strain vector |
Mm->storeother(ipp, ido, ncomp, Mm->ip[ipp].strain); |
// store actual value of stress vector |
Mm->storeother(ipp, ido+ncomp, ncomp, Mm->ip[ipp].stress); |
// store actual value of state variables |
Mm->storeother(ipp, ido+2*ncomp+3, nstatev, statev.a); |
// store actual value of suction |
Mm->ip[ipp].other[ido+2*ncomp+3+1] = eps(6); |
// store actual value of temperature |
Mm->ip[ipp].other[ido+2*ncomp+3+3] = eps(7); |
// store actual value of RK substep coefficient |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev]= dtsub; |
// store actual value of time step coefficient |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+1]= pnewdt; |
// store actual number of model evaluation - only for testing purposes |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+5]= neval; |
// store actual number of performed RKF steps - only for testing purposes |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+6]= nstep; |
// store the minimum RKF step length - only for testing purposes |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+7]= mindt; |
// volumetric strain rate is computed via generalized trapesoidal rule |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+10]= 0.5*((deps(0)+deps(1)+deps(2))/dtime + Mm->ip[ipp].eqother[ido+2*ncomp+3+nstatev+10]); |
// volumetric strain rate |
//Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+10]= (deps(0)+deps(1)+deps(2))/dtime; |
/* |
// assemble non-mechanical blocks (all except of sig-eps block) of generalized stiffness matrix |
herr = huet.soil_model(epseq.a, sigeq.a, stateveq.a, NULL, NULL, NULL, dd_gen.a, NULL, 3, Mp->jstep); |
if (herr) |
{ |
print_err("generalized stiffness matrix cannot be assembled on element %ld (ip=%ld)", __FILE__, __LINE__, __func__, Mm->elip[ipp]+1, ipp+1); |
abort(); |
} |
// store derivatives of degree of saturation Sr |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+8] = dd_gen(ngstress-1, ngstrain-2); // store dSr/ds matrix component |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+9] = dd_gen(ngstress-1, ngstrain-1); // store dSr/dT matrix component |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+11] = dd_gen(ngstress-1, 0)+dd_gen(ngstress-1, 1)+dd_gen(ngstress-1, 2); // compute and store dSr/depsv from matrix components |
*/ |
// calculate additional quantities used for output of results |
double epsv; |
// calculate volumetric strain |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+2]= epsv = eps(0)+eps(1)+eps(2); |
// suction increment |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+3]= eps(6)-Mm->ip[ipp].eqother[ido+2*ncomp+3+1]; |
// depsV |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+4]= deps(0)+deps(1)+deps(2); |
/* |
// calculate strain deviator |
epsv *= 1.0/3.0; |
eps(0) -= epsv; |
eps(1) -= epsv; |
eps(2) -= epsv; |
deviator(eps, eps); |
// vertical strain deviator component |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+3]= eps(1); |
// calculate stress deviator |
deviator(sig, sig); |
// vertical stress deviator component |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+4]= sig(1); |
*/ |
} |
/** |
The function reduces step length in Runge-Kutta-Fehlberg methods according to given |
coefficient and minimum step length. |
@param rc - reduction coefficient of step length (input) |
@param h - actual/modified step length (input/output) |
@param hmin - minimum step length (input) |
@retval 0 - On sucessfull step reduction. |
@retval 1 - The minimum step length has been attained and the step cannot be reduced further. |
Created by Tomas Koudelka, 24.5.2016 |
*/ |
long hypoplast_unsat_exp_therm::rkf_redstep(double rc, double &h, double hmin) |
{ |
if (h > hmin) |
{ |
h *= rc; |
if (h < hmin) |
h = hmin; |
return 0; |
} |
else |
return 1; |
} |
/** |
The function returns time step size required by the hypoplsaticity model. It is represented by ratio |
of required time step size to the actual one or 1.0 for no change in time step size. |
@param ipp - integration point number in the mechmat ip array. |
@param im - index of material type for given ip |
@param ido - index of internal variables for given material in the ipp other array |
@return The function returns required time step size provided by the hypoplasticity model |
Created by Tomas Koudelka, 1.10.2015 |
*/ |
double hypoplast_unsat_exp_therm::dstep_red(long ipp, long /*im*/, long ido) |
{ |
long ncomp = Mm->ip[ipp].ncompstr; |
return (Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+1]); |
} |
/** |
Function updates values in the other array reached in the previous equlibrium state to |
values reached in the new actual equilibrium state. |
@param ipp - integration point number in the mechmat ip array. |
@param im - index of material type for given ip |
@param ido - index of internal variables for given material in the ipp other array |
@return The function does not return anything. |
Created by Tomas Koudelka, 1.10.2015 |
*/ |
void hypoplast_unsat_exp_therm::updateval (long ipp,long im,long ido) |
{ |
long i, j; |
// long herr; |
long n = Mm->givencompeqother(ipp,im); |
long ncomp = Mm->ip[ipp].ncompstr; |
strastrestate ssst = Mm->ip[ipp].ssst; |
double aux; |
vector sigeq(ASTCKVEC(ngstress)); |
vector epseq(ASTCKVEC(ngstrain)); |
vector stateveq(ASTCKVEC(nstatev)); |
// matrix dd_gen(ASTCKMAT(ngstress,ngstrain)); |
// convert stress, strain and strain increment vectors to full 6 componet vectors |
give_full_vector(epseq.a, Mm->ip[ipp].strain, ssst); |
give_full_vector(sigeq.a, Mm->ip[ipp].stress, ssst); |
// stress vector must be reoredred |
// SIFEL ordering is sig11, sig22, sig33, sig23, sig13, sig12 |
// ABAQUS ordering is sig11, sig22, sig33, sig12, sig13, sig23 |
aux = sigeq(3); |
sigeq(3) = sigeq(5); |
sigeq(5) = aux; |
// strain vector must be reoredred |
// SIFEL ordering is eps11, eps22, eps33, gamma23, gamma13, gamma12 |
// ABAQUS ordering is eps11, eps22, eps33, gamma12, gamma13, gamma23 |
aux = epseq(3); |
epseq(3) = epseq(5); |
epseq(5) = aux; |
// assemble generalized strain increment vector |
if (pr_suc_fl == yes) //prescribed suction pressure s (positive) |
epseq(6) = suc_fn.getval(Mp->time); // suction s defined by user function |
else |
epseq(6) = Mm->givenonmechq(suction, ipp); // suction s from TRFEL |
if (pr_tempr_fl == yes) //prescribed temperature T |
epseq(7) = tempr_fn.getval(Mp->time); // temperature T defined by user function |
else |
epseq(7) = Mm->givenonmechq(temperature, ipp); // temperature T from TRFEL |
// assemble generalized stress vector |
sigeq(6) = Mm->ip[ipp].other[ido+2*ncomp+3+2]; // actual degree of saturation Sr |
// prepare working copy of internal variables from the last equilibrium state |
for (i=ido+2*ncomp+3, j=0; i<ido+2*ncomp+3+nstatev; i++, j++) |
stateveq(j) = Mm->ip[ipp].other[i]; |
/* |
// assemble non-mechanical blocks (all except of sig-eps block) of generalized stiffness matrix |
herr = huet.soil_model(epseq.a, sigeq.a, stateveq.a, NULL, NULL, NULL, dd_gen.a, NULL, 3, Mp->jstep); |
if (herr) |
{ |
print_err("generalized stiffness matrix cannot be assembled on element %ld (ip=%ld)", __FILE__, __LINE__, __func__, Mm->elip[ipp]+1, ipp+1); |
abort(); |
} |
// store derivatives of degree of saturation Sr |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+8] = dd_gen(ngstress-1, ngstrain-2); // store dSr/ds matrix component |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+9] = dd_gen(ngstress-1, ngstrain-1); // store dSr/dT matrix component |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+11] = dd_gen(ngstress-1, 0)+dd_gen(ngstress-1, 1)+dd_gen(ngstress-1, 2); // compute dSr/depsv from matrix components |
*/ |
matrix dd_gen; |
makerefm(dd_gen, Mm->ip[ipp].other+ido+2*ncomp+3+nstatev+12, ngstress, ngstrain); |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+8] = dd_gen(ngstress-1, ngstrain-2); // store dSr/ds matrix component |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+9] = dd_gen(ngstress-1, ngstrain-1); // store dSr/dT matrix component |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+11] = dd_gen(ngstress-1, 0);//+dd_gen(ngstress-1, 1)+dd_gen(ngstress-1, 2); // compute dSr/depsv from matrix components |
// copy internal variables from working array to the equilibrium array |
for (i=0;i<n;i++) |
Mm->ip[ipp].eqother[ido+i]=Mm->ip[ipp].other[ido+i]; |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+5] = 0; // zero neval at the end of actual time step |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+6] = 0; // zero nstep at the end of actual time step |
Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+7] = 1.0; // set mindt to 1 at the end of actual time step |
} |
/** |
The funtion marks required non-mechanical quantities in the array anmq. |
@param anmq - array with flags for used material types |
anmq[i] = 1 => qunatity type nonmechquant(i+1) is required |
anmq[i] = 0 => qunatity type nonmechquant(i+1) is not required |
@return The function does not return anything, but it may change content of anmq array. |
Created by Tomas Koudelka, 1.10.2015 |
*/ |
void hypoplast_unsat_exp_therm::give_reqnmq(long *anmq) |
{ |
// anmq[saturation_degree-1] = 1; |
if (pr_suc_fl == no) |
anmq[suction-1] = 1; |
if (pr_tempr_fl == no) |
anmq[temperature-1] = 1; |
} |
/** |
The function returns the number of eqother array componets of the material model. |
@param ipp - integration point number in the mechmat ip array. |
@retval The function returns value of |
Created by Tomas Koudelka, 4.3.2019 |
*/ |
long hypoplast_unsat_exp_therm::givencompeqother(long ipp) |
{ |
long ncompstr = Mm->ip[ipp].ncompstr; |
return 2*ncompstr+3+nstatev+12+ngstress*ngstrain; |
} |
/** |
The function extracts actual degree of saturation for the actual attained state. |
@param ipp - integration point number in the mechmat ip array. |
@param ido - index of internal variables for given material in the ipp other array |
@retval The function returns value of actual degree of saturation Sr. |
Created by Tomas Koudelka, 25.5.2016 |
*/ |
double hypoplast_unsat_exp_therm::give_sr(long ipp, long ido) |
{ |
long ncompstr = Mm->ip[ipp].ncompstr; |
return Mm->ip[ipp].other[ido+2*ncompstr+3+2]; |
} |
/** |
The function computes actual derivative of degree of saturation with respect to suction |
for the actual attained state. |
@param ipp - integration point number in the mechmat ip array. |
@param ido - index of internal variables for given material in the ipp other array |
@retval The function returns value of derivative of actual degree of saturation with respect to suction dSr/ds. |
Created by Tomas Koudelka, 25.5.2016 |
*/ |
double hypoplast_unsat_exp_therm::give_dsr_ds(long ipp, long ido) |
{ |
long ncomp = Mm->ip[ipp].ncompstr; |
double dsr = Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+8]; |
return dsr; |
} |
/** |
The function computes actual derivative of degree of saturation with respect to temperature |
for the actual attained state. |
@param ipp - integration point number in the mechmat ip array. |
@param ido - index of internal variables for given material in the ipp other array |
@retval The function returns value of derivative of actual degree of saturation with respect to suction dSr/ds. |
Created by Tomas Koudelka, 29.6.2017 |
*/ |
double hypoplast_unsat_exp_therm::give_dsr_dtemp(long ipp, long ido) |
{ |
long ncomp = Mm->ip[ipp].ncompstr; |
double dsr = Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+9]; |
return dsr; |
} |
/** |
The function computes actual derivative of degree of saturation with respect to volumetric strain |
for the attained equilibrium state. |
@param ipp - integration point number in the mechmat ip array. |
@param ido - index of internal variables for given material in the ipp other array |
@retval The function returns value of derivative of actual degree of saturation with respect to suction dSr/ds. |
Created by Tomas Koudelka, 29.6.2018 |
*/ |
double hypoplast_unsat_exp_therm::give_dsr_depsv(long ipp, long ido) |
{ |
long ncomp = Mm->ip[ipp].ncompstr; |
double dsr = Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+11]; |
return dsr; |
} |
/** |
The function extracts actual porosity for the actual attained state. |
@param ipp - integration point number in the mechmat ip array. |
@param ido - index of internal variables for given material in the ipp other array |
@retval The function returns value of actual porosity. |
Created by Tomas Koudelka, 25.5.2016 |
*/ |
double hypoplast_unsat_exp_therm::give_porosity(long ipp, long ido) |
{ |
long ncompstr = Mm->ip[ipp].ncompstr; |
double e = Mm->ip[ipp].other[ido+2*ncompstr+3]; // actual void ratio |
return (e/(1.0+e)); |
} |
/** |
The function extracts actual void ratio for the actual attained state. |
@param ipp - integration point number in the mechmat ip array. |
@param ido - index of internal variables for given material in the ipp other array |
@retval The function returns value of actual porosity e. |
Created by Tomas Koudelka, 25.5.2016 |
*/ |
double hypoplast_unsat_exp_therm::give_void_ratio(long ipp, long ido) |
{ |
long ncompstr = Mm->ip[ipp].ncompstr; |
return Mm->ip[ipp].other[ido+2*ncompstr+3]; |
} |
/** |
The function returns rate of the volumetric strain at the given integration point. |
@param ipp - integration point number in the mechmat ip array. |
@param ido - index of internal variables for given material in the ipp other array |
@return The function returns rate of the volumetric strain. |
Created by Tomas Koudelka 05.2018 |
*/ |
double hypoplast_unsat_exp_therm::give_strain_vol_rate(long ipp, long ido) |
{ |
long ncomp = Mm->ip[ipp].ncompstr; |
return Mm->ip[ipp].other[ido+2*ncomp+3+nstatev+10]; |
} |
/** |
The function returns approximation of the bulk modulus from the stored |
tangent stiffness %matrix. |
@param ipp - integration point number in the mechmat ip array. |
@param ido - index of internal variables for given material in the ipp other array |
@return The function returns approximated value of the bulk modulus. |
Created by Tomas Koudelka 09.2023 |
*/ |
double hypoplast_unsat_exp_therm::give_bulk_modulus(long ipp, long ido) |
{ |
long i, ncomp = Mm->ip[ipp].ncompstr; |
matrix d; |
makerefm(d, Mm->ip[ipp].other+ido+2*ncomp+3+nstatev+12, ngstress, ngstrain); |
double k = 0.0; |
for (i=0; i<3; i++) |
k = d(i,0) + d(i,1) + d(i,2); |
k = 1.0/9.0; |
return k; |
} |
/** |
The function changes material parameters for stochastic analysis. |
@param atm - selected material parameters (parameters which are changed) |
@param val - array containing new values of parameters |
@return The function does not return anything. |
Created by Tomas Koudelka, 30.1.2014 |
*/ |
void hypoplast_unsat_exp_therm::changeparam (atsel &atm,vector &val) |
{ |
long i; |
for (i=0;i<atm.num;i++){ |
switch (atm.atrib[i]){ |
case 0:{ |
phideg=val[i]; |
break; |
} |
case 1:{ |
lam_star=val[i]; |
break; |
} |
case 2:{ |
kap_star=val[i]; |
break; |
} |
case 3:{ |
n_star=val[i]; |
break; |
} |
case 4:{ |
nu=val[i]; |
break; |
} |
case 5:{ |
n=val[i]; |
break; |
} |
case 6:{ |
l=val[i]; |
break; |
} |
case 7:{ |
nt=val[i]; |
break; |
} |
case 8:{ |
lt=val[i]; |
break; |
} |
case 9:{ |
m=val[i]; |
break; |
} |
case 10:{ |
alpha_s=val[i]; |
break; |
} |
case 11:{ |
kap_m=val[i]; |
break; |
} |
case 12:{ |
sm_star=val[i]; |
break; |
} |
case 13:{ |
em_star=val[i]; |
break; |
} |
case 14:{ |
s_airentry0=val[i]; |
break; |
} |
case 15:{ |
em0=val[i]; |
break; |
} |
case 16:{ |
tr=val[i]; |
break; |
} |
case 17:{ |
at=val[i]; |
break; |
} |
case 18:{ |
bt=val[i]; |
break; |
} |
case 19:{ |
aer=val[i]; |
break; |
} |
case 20:{ |
p_t=val[i]; |
break; |
} |
default:{ |
fprintf (stderr,"\n\n wrong number of atribute in function changeparam (file %s, line %d).\n",__FILE__,__LINE__); |
} |
} |
} |
} |
/trunk/SIFEL/MEFEL/SRC/linhex.cpp |
---|
1452,7 → 1452,7 |
for (j=0;j<intordsm[0][0];j++){ |
for (k=0;k<intordsm[0][0];k++){ |
// computation of correct stresses |
// computation of actual stresses |
if (Mp->strcomp==1) |
Mm->computenlstresses (ipp,Mm->ip[ipp]); |
/trunk/SIFEL/MEFEL/SRC/lssolver.cpp |
---|
115,7 → 115,7 |
aux = Mp->homog; |
Mp->homog = 0; |
mefel_right_hand_side(i,rhs,fl); |
Mp->homog = aux; |
Mp->homog = aux; |
// computes required quantities |
compute_req_val (i); |
// in artificial time 0.0 the nodal forces contains only the load vector fl |
/trunk/SIFEL/MEFEL/SRC/mechmat.cpp |
---|
90,6 → 90,9 |
#include "homogmatm.h" |
#include "stacktrace.h" |
#include "ipmap.h" |
#include "lhsrhs.h" |
#include "selection.h" |
#include "mathem.h" |
#include <math.h> |
#include <string.h> |
3561,6 → 3564,39 |
/** |
Function restores part of array other to %vector comp. |
@param[in] ipp - integration point pointer |
@param[in] selcomp - selection of components |
@param[out] comp - %vector for the component storage |
@return The function returns part of other array in the argument comp. |
Created by TKo, 09.2020 |
*/ |
void mechmat::giveother (long ipp, sel &selcomp, vector &comp) |
{ |
long i,j; |
j = 0; |
if ((selcomp.st == sel_list) || (selcomp.st == sel_single)){ |
for (i=0; i<selcomp.n; i++){ |
comp(j) = ip[ipp].other[selcomp.id1[i]]; |
j++; |
} |
} |
else{ |
for (i=0; i<ip[ipp].ncompother; i++){ |
if (selcomp.presence_id(i)){ |
comp(j) = ip[ipp].other[i]; |
j++; |
} |
} |
} |
} |
/** |
Function stores components of array other. |
@param[in] ipp - integration point pointer |
3896,10 → 3932,10 |
break; |
case cebfipcontmat: |
case contmat: |
ncompo = 2; |
ncompo = ncompstr; |
break; |
case damplifmat: |
ncompo = 5; |
ncompo = 4+ncompstr-1; |
break; |
case creeprs: |
case creepb3: |
4734,6 → 4770,605 |
/** |
The function returns a characteristics of the required quantity. |
The return value is the natural mathematic representation of the quantity - |
scalar, vector or the second order tensor. Additionally, it returns the maximum |
number of components used for the qunatity storage in the argument ncomp. |
If the given quantity is the second order tensor, the function returns quantity storage |
notation in the argument tn and tensor type identifier in the argument tti. |
@param[in] mq - required quantity type. |
@param[in] refmq - referenced mechanical quantity, used only for mq == tensdeviator |
@param[out] ncomp - the maximum number of quantity components. |
@param[out] tn - tensor storarge notation for quantities representded as tensors otherwise 0 |
@param[out] tti - tensor type identifier (stress/strain/other) for quantities representded as tensors otherwise -1 |
@retval scalq if the given quantity is represented as a scalar. |
@retval vectq if the given quantity is represented as a vector. |
@retval tensq if the given quantity is represented as the second order tensor. |
Created by TKo, 09.2023 |
*/ |
quantrep mechmat::give_quant_rep(mechquant mq, mechquant refmq, long &ncomp, tensqnot &tn, strastre &tti) |
{ |
quantrep ret = undefq; |
tn = undeftn; |
tti = undef_strastre; |
ncomp = 1; |
switch (mq){ |
case time_q: // time (constant scalar quantity at whole domain) |
case step_id_q: // step id (constant scalar quantity at whole domain) |
case load_fact_q: // load factor in nonlinear statics problem type (constant scalar quantity at whole domain) |
case eigval_q: // eigen values in eigenvalue problem type (constant scalar quantity at whole domain) |
case eps_x: // strain components as scalars |
case eps_y: |
case eps_z: |
case eps_yz: |
case eps_xz: |
case eps_xy: |
case epsp_x: // components of plastic strains considered as scalars |
case epsp_y: |
case epsp_z: |
case gammap_yz: |
case gammap_xz: |
case gammap_xy: |
case sig_x: // stress components as scalars |
case sig_y: |
case sig_z: |
case tau_yz: |
case tau_xz: |
case tau_xy: |
case first_inv: // A11 + A22 + A33 |
case second_inv: // A11*A22 + A11*A33 + A22*A33 - A12^2 - A13^2 - A23^2 |
case third_inv: // det|A| |
case tensor_norm: // ||A|| = sqrt(a_ij*a_ij) |
case strain_vol: // eps_v = eps_x + eps_y + eps_z |
case mean_stress: // sig_m = (sig_x + sig_y + sig_z)/3 |
case j2inv: // negative value of the second invariant of stress deviator, i.e. J2 = 1/2 s_ij s_ij |
case von_mises_stress:// sig_eff = sqrt(3*J2) |
case cons_param: // consistency parameter gamma |
case damage_scal: // scalar damage (omega) |
case damaget_scal: // scalar damage (omega_t) in tension |
case damagec_scal: // scalar damage (omega_c) in compression |
ret = scalq; |
break; |
case displ_q: // displacement vector |
case react_q: // reactions vector at nodes |
case load_vect_q: // load vector at nodes |
case int_force_q: // internal force vector |
case resid_vect_q: // residual vector |
ret = vectq; |
ncomp = Mt->give_maxndofn(); |
break; |
case nonmech_q: // nonmechanical quantities at ip |
ret = vectq; |
ncomp = Mm->nnmq; |
break; |
case other_q: // other array values as a vector |
ret = vectq; |
ncomp = std::max(max_ncompothern, max_ncompothere); |
break; |
case strain_q: // strain tensor |
case tempr_strain_q: // temperature strain tensor |
case eig_strain_q: // eigenstrain tensor |
case macrostrain_q: // macrostrain (constant tensor quantity at whole domain) |
case strain_deviator: // s_ij = sig_ij - delta_ij*sig_m |
case strain_pl: // plastic strain tensor |
ret = tensq; |
tn = voigtred; |
tti = strain; |
ncomp = std::max(max_ncompstrn, max_ncompstre); |
break; |
case stress_q: // stress tensor |
case eig_stress_q: // eigenstress tensor |
case macrostress_q: // macrostress (constant tensor quantity at whole domain) |
case stress_deviator: // e_ij = eps_ij - delta_ij*eps_v/3 |
ret = tensq; |
tn = voigtred; |
tti = stress; |
ncomp = std::max(max_ncompstrn, max_ncompstre); |
break; |
case tensdeviator: // D_ij = A_ij - delta_ij*A_kk/3 |
ret = give_quant_rep(mq, refmq, ncomp, tn, tti); |
break; |
case damage_tens: // damage tensor (Omega) |
case damaget_tens: // damage tensor (Omega_t) in tension |
case damagec_tens: // damage tensor (Omega_c) in compression |
ret = tensq; |
tn = fullmtx; |
tti = other; |
ncomp = 3*3; |
break; |
default: |
print_err("unknown type of quantitity (%d) is required\n", __FILE__, __LINE__, __func__, int(mq)); |
abort(); |
} |
return ret; |
} |
/** |
The function returns a required scalar qunatity in the given integration point. |
The value is returned in the argument qv. |
@param[in] ipp - integration point pointer |
@param[in] mqn - quantity name |
@param[in] reftensq - referenced tensor quantity, it is used only if the mqn |
is an tensor derived value (invariant, norm,...), otherwise it is ignored |
@param[in] lcid - load case id or eigenvalue id. |
@param[in] selrefcomp - selection of referenced tensor components, it is used only if the mqn |
is an tensor derived value (invariant, norm,...), otherwise it is ignored |
@param[in] ref_strastre - identfier of of stress/strain/other type of tensors given by array, i.e. |
reftensq == (other_q || nonmech_q), otherwise it is ignored |
@param[out] qv - required quantity value. |
@return The function returns the quantity value in the argument qv. |
Created by Tomas Koudelka 09.2023 |
*/ |
void mechmat::give_quant(long ipp, mechquant mqn, mechquant reftensq, long lcid, sel &selrefcomp, |
strastre ref_strastre, double &qv) |
{ |
matrix auxm; |
vector eps, epst, sig; |
qv = 0.0; |
switch (mqn){ |
case time_q: // time (constant scalar quantity at whole domain) |
qv = Mp->time; |
break; |
case step_id_q: // step id (constant scalar quantity at whole domain) |
qv = Mp->istep; |
break; |
case load_fact_q: // load factor in nonlinear statics problem type (constant scalar quantity at whole domain) |
qv = Mp->lambda; |
break; |
case eigval_q: // eigen values in eigenvalue problem type (constant scalar quantity at whole domain) |
//qv = Lsrs->eigv[lcid]; |
break; |
case first_inv: // A11 + A22 + A33 |
reallocm(RSTCKMAT(3, 3, auxm)); |
give_quant(ipp, reftensq, nomech_q, lcid, selrefcomp, ref_strastre, auxm); |
qv = first_invar(auxm);; |
break; |
case second_inv: // A11*A22 + A11*A33 + A22*A33 - A12^2 - A13^2 - A23^2 |
reallocm(RSTCKMAT(3, 3, auxm)); |
give_quant(ipp, reftensq, nomech_q, lcid, selrefcomp, ref_strastre, auxm); |
qv = second_invar(auxm);; |
break; |
case third_inv: // det|A| |
reallocm(RSTCKMAT(3, 3, auxm)); |
give_quant(ipp, reftensq, nomech_q, lcid, selrefcomp, ref_strastre, auxm); |
qv = third_invar(auxm);; |
break; |
case tensor_norm: // ||A|| : sqrt(a_ij*a_ij) |
reallocm(RSTCKMAT(3, 3, auxm)); |
give_quant(ipp, reftensq, nomech_q, lcid, selrefcomp, ref_strastre, auxm); |
qv = norm(auxm);; |
break; |
case strain_vol: // eps_v : eps_x + eps_y + eps_z |
reallocv(RSTCKVEC(6, eps)); |
give_full_vector(eps, ip[ipp].strain, ip[ipp].ssst); |
qv = first_invar(eps); |
break; |
case mean_stress: // sig_m : (sig_x + sig_y + sig_z)/3 |
reallocv(RSTCKVEC(6, sig)); |
give_full_vector(sig, ip[ipp].stress, ip[ipp].ssst); |
qv = (1.0/3.0)*first_invar(sig); |
break; |
case j2inv: // negative value of the second invariant of stress deviator, i.e. J2 : 1/2 s_ij s_ij |
reallocv(RSTCKVEC(6, sig)); |
give_full_vector(sig, ip[ipp].stress, ip[ipp].ssst); |
qv = j2_stress_invar(sig); |
break; |
case von_mises_stress:// sig_eff : sqrt(3*J2) |
reallocv(RSTCKVEC(6, sig)); |
give_full_vector(sig, ip[ipp].stress, ip[ipp].ssst); |
qv = 3.0*j2_stress_invar(sig); |
qv = sqrt(qv); |
break; |
case cons_param: // consistency parameter gamma |
qv = give_consparam(ipp); |
break; |
case damage_scal: // scalar damage (omega) |
qv = give_dampar(ipp); |
break; |
//case damaget_scal: // scalar damage (omega_t) in tension |
//case damagec_scal: // scalar damage (omega_c) in compression |
case eps_x: // strain components as scalars |
reallocv(RSTCKVEC(6, eps)); |
give_full_vector(eps, ip[ipp].strain, ip[ipp].ssst); |
qv = eps(0); |
break; |
case eps_y: |
reallocv(RSTCKVEC(6, eps)); |
give_full_vector(eps, ip[ipp].strain, ip[ipp].ssst); |
qv = eps(1); |
break; |
case eps_z: |
reallocv(RSTCKVEC(6, eps)); |
give_full_vector(eps, ip[ipp].strain, ip[ipp].ssst); |
qv = eps(2); |
break; |
case gamma_yz: |
reallocv(RSTCKVEC(6, eps)); |
give_full_vector(eps, ip[ipp].strain, ip[ipp].ssst); |
qv = eps(3); |
break; |
case gamma_xz: |
reallocv(RSTCKVEC(6, eps)); |
give_full_vector(eps, ip[ipp].strain, ip[ipp].ssst); |
qv = eps(4); |
break; |
case gamma_xy: |
reallocv(RSTCKVEC(6, eps)); |
give_full_vector(eps, ip[ipp].strain, ip[ipp].ssst); |
qv = eps(5); |
break; |
case eps_yz: |
reallocv(RSTCKVEC(6, eps)); |
give_full_vector(eps, ip[ipp].strain, ip[ipp].ssst); |
qv = 0.5*eps(3); |
break; |
case eps_xz: |
reallocv(RSTCKVEC(6, eps)); |
give_full_vector(eps, ip[ipp].strain, ip[ipp].ssst); |
qv = 0.5*eps(4); |
break; |
case eps_xy: |
reallocv(RSTCKVEC(6, eps)); |
give_full_vector(eps, ip[ipp].strain, ip[ipp].ssst); |
qv = 0.5*eps(5); |
break; |
case sig_x: // stress components as scalars |
reallocv(RSTCKVEC(6, eps)); |
give_full_vector(sig, ip[ipp].stress, ip[ipp].ssst); |
qv = sig(0); |
break; |
case sig_y: |
reallocv(RSTCKVEC(6, eps)); |
give_full_vector(sig, ip[ipp].stress, ip[ipp].ssst); |
qv = sig(1); |
break; |
case sig_z: |
reallocv(RSTCKVEC(6, eps)); |
give_full_vector(sig, ip[ipp].stress, ip[ipp].ssst); |
qv = sig(2); |
break; |
case tau_yz: |
reallocv(RSTCKVEC(6, eps)); |
give_full_vector(sig, ip[ipp].stress, ip[ipp].ssst); |
qv = sig(3); |
break; |
case tau_xz: |
reallocv(RSTCKVEC(6, eps)); |
give_full_vector(sig, ip[ipp].stress, ip[ipp].ssst); |
qv = sig(4); |
break; |
case tau_xy: |
reallocv(RSTCKVEC(6, eps)); |
give_full_vector(sig, ip[ipp].stress, ip[ipp].ssst); |
qv = sig(5); |
break; |
case epsp_x: // components of plastic strains considered as scalars |
reallocv(RSTCKVEC(ip[ipp].ncompstr, eps)); |
reallocv(RSTCKVEC(6, epst)); |
giveirrstrains(ipp, 0, 0, eps); |
give_full_vector(epst, eps, ip[ipp].ssst); |
qv = epst(0); |
break; |
case epsp_y: |
reallocv(RSTCKVEC(ip[ipp].ncompstr, eps)); |
reallocv(RSTCKVEC(6, epst)); |
giveirrstrains(ipp, 0, 0, eps); |
give_full_vector(epst, eps, ip[ipp].ssst); |
qv = epst(1); |
break; |
case epsp_z: |
reallocv(RSTCKVEC(ip[ipp].ncompstr, eps)); |
reallocv(RSTCKVEC(6, epst)); |
giveirrstrains(ipp, 0, 0, eps); |
give_full_vector(epst, eps, ip[ipp].ssst); |
qv = epst(2); |
break; |
case gammap_yz: |
reallocv(RSTCKVEC(ip[ipp].ncompstr, eps)); |
reallocv(RSTCKVEC(6, epst)); |
giveirrstrains(ipp, 0, 0, eps); |
give_full_vector(epst, eps, ip[ipp].ssst); |
qv = epst(3); |
break; |
case gammap_xz: |
reallocv(RSTCKVEC(ip[ipp].ncompstr, eps)); |
reallocv(RSTCKVEC(6, epst)); |
giveirrstrains(ipp, 0, 0, eps); |
give_full_vector(epst, eps, ip[ipp].ssst); |
qv = epst(4); |
break; |
case gammap_xy: |
reallocv(RSTCKVEC(ip[ipp].ncompstr, eps)); |
reallocv(RSTCKVEC(6, epst)); |
giveirrstrains(ipp, 0, 0, eps); |
give_full_vector(epst, eps, ip[ipp].ssst); |
qv = epst(5); |
break; |
case epsp_yz: |
reallocv(RSTCKVEC(ip[ipp].ncompstr, eps)); |
reallocv(RSTCKVEC(6, epst)); |
giveirrstrains(ipp, 0, 0, eps); |
give_full_vector(epst, eps, ip[ipp].ssst); |
qv = 0.5*epst(3); |
break; |
case epsp_xz: |
reallocv(RSTCKVEC(ip[ipp].ncompstr, eps)); |
reallocv(RSTCKVEC(6, epst)); |
giveirrstrains(ipp, 0, 0, eps); |
give_full_vector(epst, eps, ip[ipp].ssst); |
qv = 0.5*epst(4); |
break; |
case epsp_xy: |
reallocv(RSTCKVEC(ip[ipp].ncompstr, eps)); |
reallocv(RSTCKVEC(6, epst)); |
giveirrstrains(ipp, 0, 0, eps); |
give_full_vector(epst, eps, ip[ipp].ssst); |
qv = 0.5*epst(5); |
break; |
default: |
print_err("unknown scalar quantity type (%d) is required on element %ld, ipp=%ld.\n", |
__FILE__, __LINE__, __func__, int(mqn), elip[ipp]+1, ipp); |
abort(); |
} |
} |
/** |
The function returns required components of a %vector qunatity in the given integration point. |
The quantity components are returned in the argument qv. |
@param[in] ipp - integration point pointer |
@param[in] mqn - quantity name |
@param[in] lcid - load case id or eigenvalue id. |
@param[in] selcomp - selection of the %vector components |
@param[out] qv - required quantity value. |
@return The function returns the quantity components in the argument qv. |
Created by Tomas Koudelka 09.2023 |
*/ |
void mechmat::give_quant(long ipp, mechquant mqn, long lcid, sel &selcomp, vector &qv) |
{ |
long i, id; |
switch (mqn){ |
//case displ_q: // displacement vector, it will be handled in new materialpoints concept, now displacements are not defined on integration points |
// following options have no meaning for the integration points |
//case react_q: // reactions vector at nodes |
//case load_vect_q: // load vector at nodes |
//case int_force_q: // internal force vector |
//case resid_vect_q: // residual vector |
case nonmech_q: // nonmechanical quantities at ip |
id = 0; |
for(i=0; i < nnmq; i++){ |
if (selcomp.presence_id(i)){ |
qv(id) = nonmechq[i][ipp]; |
id++; |
} |
} |
break; |
case other_q: // other array values as a vector |
id = 0; |
for(i=0; i < ip[ipp].ncompother; i++){ |
if (selcomp.presence_id(i)){ |
qv(id) = ip[ipp].other[i]; |
id++; |
} |
} |
break; |
default: |
print_err("unknown vector quantity type (%d) is required on element %ld, ipp=%ld.\n", |
__FILE__, __LINE__, __func__, int(mqn), elip[ipp]+1, ipp); |
abort(); |
} |
} |
/** |
The function returns a required tensor qunatity in the given integration point. |
The quantity components are returned in the argument qv. |
@param[in] ipp - integration point pointer |
@param[in] mqn - required quantity name |
@param[in] reftensq - referenced quantity handled as an ordinary tensor |
@param[in] lcid - load case id or eigenvalue id. |
@param[in] selcomp - selection of array components for mqn == (other_q || nonmech_q) |
or mqn == tensdeviator reftensq == (other_q || nonmech_q), |
otherwise it is ignored |
@param[in] array_strastre - identfier of of stress/strain/other type of tensors given by array, i.e. |
mqn == (other_q || nonmech_q) or for referenced tensor reftensq == (other_q || nonmech_q), |
otherwise it is ignored |
@param[out] qv - required quantity value. |
@return The function returns the quantity components in the argument qv. |
Created by Tomas Koudelka 09.2023 |
*/ |
void mechmat::give_quant(long ipp, mechquant mqn, mechquant reftensq, long lcid, sel &selcomp, |
strastre array_strastre, matrix &qv) |
{ |
vector eps, epst, eps0, epsp, meps, sig, sig0, msig, other_arr; |
double *epsptr, *sigptr; |
long ncompstr, ncsel, nc; |
double inv; |
switch (mqn){ |
case strain_q: // strain tensor |
ncompstr = ip[ipp].ncompstr; |
epsptr = ip[ipp].strain+lcid*ncompstr; |
makerefv(eps, epsptr, ncompstr); |
vector_tensor(eps, qv, ip[ipp].ssst, strain); |
break; |
case stress_q: // stress tensor |
ncompstr = ip[ipp].ncompstr; |
sigptr = ip[ipp].stress+lcid*ncompstr; |
makerefv(sig, sigptr, ncompstr); |
vector_tensor(sig, qv, ip[ipp].ssst, stress); |
break; |
case tempr_strain_q: // temperature strain tensor |
makerefv(epst, tempstrains[ipp], ip[ipp].ncompstr); |
vector_tensor(epst, qv, ip[ipp].ssst, strain); |
break; |
case eig_strain_q: // eigenstrain tensor |
makerefv(eps0, eigstrains[ipp], ip[ipp].ncompstr); |
vector_tensor(eps0, qv, ip[ipp].ssst, strain); |
break; |
case eig_stress_q: // eigenstress tensor |
makerefv(sig0, eigstresses[ipp], ip[ipp].ncompstr); |
vector_tensor(sig, qv, ip[ipp].ssst, stress); |
break; |
case macrostrain_q: // macrostrain (constant tensor quantity at whole domain) |
reallocv(RSTCKVEC(Mt->max_ncompstr, meps)); |
macrostrains(lcid, meps); |
vector_tensor(meps, qv, ip[ipp].ssst, strain); |
break; |
case macrostress_q: // macrostress (constant tensor quantity at whole domain) |
reallocv(RSTCKVEC(Mt->max_ncompstr, msig)); |
macrostresses(lcid, msig); |
vector_tensor(msig, qv, ip[ipp].ssst, stress); |
break; |
case tensdeviator: // D_ij : A_ij - delta_ij*A_kk/3 |
give_quant(ipp, reftensq, nomech_q, lcid, selcomp, array_strastre, qv); |
inv = (qv(0,0)+qv(1,1)+qv(2,2))/3.0; |
qv(0,0) -= inv; |
qv(1,1) -= inv; |
qv(2,2) -= inv; |
break; |
case strain_deviator: // e_ij : eps_ij - delta_ij*eps_v/3 |
makerefv(eps, ip[ipp].strain, ip[ipp].ncompstr); |
vector_tensor(eps, qv, ip[ipp].ssst, strain); |
inv = (qv(0,0)+qv(1,1)+qv(2,2))/3.0; |
qv(0,0) -= inv; |
qv(1,1) -= inv; |
qv(2,2) -= inv; |
break; |
case stress_deviator: // s_ij : sig_ij - delta_ij*sig_m |
makerefv(sig, ip[ipp].stress, ip[ipp].ncompstr); |
vector_tensor(sig, qv, ip[ipp].ssst, stress); |
inv = (qv(0,0)+qv(1,1)+qv(2,2))/3.0; |
qv(0,0) -= inv; |
qv(1,1) -= inv; |
qv(2,2) -= inv; |
break; |
case strain_pl: // plastic strain tensor |
reallocv(RSTCKVEC(ip[ipp].ncompstr, epsp)); |
giveirrstrains(ipp, 0, 0, epsp); |
vector_tensor(epsp, qv, ip[ipp].ssst, strain); |
break; |
case other_q: |
ncsel = selcomp.give_nselcomp(ip[ipp].ncompother); |
if (ncsel == 9){ |
makerefv(other_arr, qv.a, ncsel); |
giveother(ipp, selcomp, other_arr); |
} |
else{ |
nc = give_ncompstr(ip[ipp].ssst); |
if (nc == ncsel){ |
reallocv(RSTCKVEC(ncsel, other_arr)); |
giveother(ipp, selcomp, other_arr); |
vector_tensor(other_arr, qv, ip[ipp].ssst, array_strastre); |
} |
else{ |
print_err("number of selected other array components %ld does not correspond\n" |
"to the number of tensor components in Voigt's notation %ld for the %s\n" |
"stress/strain state at ipp=%ld, eid=%ld\n", __FILE__, __LINE__, __func__, |
ncsel, nc, strastrestate_kwdset.get_str(ip[ipp].ssst), ipp, elip[ipp]+1); |
abort(); |
} |
} |
break; |
case nonmech_q: |
ncsel = selcomp.give_nselcomp(nnmq); |
if (ncsel == 9){ |
makerefv(other_arr, qv.a, ncsel); |
give_nonmechqcomp(ipp, selcomp, other_arr); |
} |
else{ |
nc = give_ncompstr(ip[ipp].ssst); |
if (nc == ncsel){ |
reallocv(RSTCKVEC(ncsel, other_arr)); |
give_nonmechqcomp(ipp, selcomp, other_arr); |
vector_tensor(other_arr, qv, ip[ipp].ssst, array_strastre); |
} |
else{ |
print_err("number of selected nonmechq array components %ld does not correspond\n" |
"to the number of tensor components in Voigt's notation %ld for the %s\n" |
"stress/strain state at ipp=%ld, eid=%ld\n", __FILE__, __LINE__, __func__, |
ncsel, nc, strastrestate_kwdset.get_str(ip[ipp].ssst), ipp, elip[ipp]+1); |
abort(); |
} |
} |
break; |
//case damage_tens: // damage tensor (Omega) |
//case damaget_tens: // damage tensor (Omega_t) in tension |
//case damagec_tens: // damage tensor (Omega_c) in compression |
default: |
print_err("unknown tensor quantity type (%d) is required on element %ld, ipp=%ld.\n", |
__FILE__, __LINE__, __func__, int(mqn), elip[ipp]+1, ipp); |
abort(); |
} |
} |
/** |
The function returns required quantity on the given integration point. |
@param[in] ipp - integration point pointer |
@param[in] mq - required quantity type |
@param[in] reftensq - referenced tensor quantity, it is used only if the mqn |
is an tensor derived value (invariant, norm,...) |
@param[in] lcid - load case id |
@param[in] qr - original character of the required quantity (scalar/vector/tensor) |
@param[in] selcomp - component selection for a vector quantity |
@param[in] array_strastre - identfier of of stress/strain/other type of tensors given by array, i.e. |
mqn == (other_q || nonmech_q) or for referenced tensor reftensq == (other_q || nonmech_q), |
otherwise it is ignored |
@param[out] sv - output argument for a scalar quantity |
@param[out] vv - output argument for a vector quantity |
@param[out] tv - output argument for a tensor quantity |
@return The function returns required quantity value(s) in one of the arguments |
sv, vv, tv according to qt argument value. |
Created by Tomas Koudelka, 09.2023 |
*/ |
void mechmat::give_quant(long ipp, mechquant mq, mechquant reftensq, long lcid, quantrep qr, sel &selcomp, |
strastre array_strastre, double &sv, vector &vv, matrix &tv) |
{ |
switch(qr){ |
case scalq: |
give_quant(ipp, mq, reftensq, lcid, selcomp, array_strastre, sv); |
break; |
case vectq: |
give_quant(ipp, mq, lcid, selcomp, vv); |
break; |
case tensq: |
give_quant(ipp, mq, reftensq, lcid, selcomp, array_strastre, tv); |
break; |
default: |
print_err("unknown qunatity character type (%d)\n", __FILE__, __LINE__, __func__, int(qr)); |
abort(); |
} |
} |
/** |
Function returns required mechanical quantity stored at integration point |
for TRFEL . |
6159,6 → 6794,31 |
/** |
The function returns selected components of array of non-mechanical quantities (nonmechq) |
on given integration point. |
@param[in] ipp - integration point pointer |
@param[in] selcomp - definition of selected components |
@param[out] nmqcomp - output array of required nonmechanical quantities. |
@return The function returns required components of nonmechnical quantities in the argument nmqcomp. |
Created by Tomas Koudelka, 10.2023 |
*/ |
void mechmat::give_nonmechqcomp (long ipp, sel selcomp, vector &nmqcomp) |
{ |
long i, k; |
k=0; |
for (i=0; i<tnknmq; i++){ |
if (selcomp.presence_id(i)) |
nmqcomp[k] = nonmechq[i][ipp]; |
} |
} |
/** |
The function stores required non-mechanical quantity into the nonmechq array. |
It is used either in case of prescribed temperature changes in the input file or |
/trunk/SIFEL/MEFEL/SRC/mechmat.h |
---|
84,6 → 84,7 |
class cusatismaterial; |
struct matrix; |
struct vector; |
class sel; |
class ipmap; |
299,9 → 300,12 |
/// returns given actual internal variable components on given int. point |
void giveother (long ipp,long fi,long ncomp,double *comp); |
/// returns given internal variable components from the last equilibrium step on given int. point |
/// returns given actual internal variable components on given int. point |
void giveother (long ipp,long fi,long ncomp, vector &comp); |
/// returns given actual internal variable components on given int. point |
void giveother (long ipp, sel &selcomp, vector &comp); |
/// storage of given internal variable components on given int. point |
void storeother (long ipp,long fi,long ncomp,double *comp); |
344,6 → 348,23 |
/// returns actual compression strength (for damage models) |
double give_actual_fc (long ipp, long im=0, long ido=0); |
/// returns quantity representation (scalar/vector/tensor) and for the tensor quantities, it returns quantity storage notation |
/// (Voigt reduced notation/Voigt full notation/Full matrix 3x3) and tensor type identfier (stress/strain/other) |
quantrep give_quant_rep(mechquant mq, mechquant refmq, long &ncomp, tensqnot &tn, strastre &tti); |
/// returns value of the required scalar quantity in the given integration point |
void give_quant(long ipp, mechquant mqn, mechquant reftensq, long lcid, sel &selrefcomp, strastre ref_strastre, double &qv); |
/// returns value of the required %vector quantity in the given integration point |
void give_quant(long ipp, mechquant mqn, long lcid, sel &selcomp, vector &qv); |
/// returns value of the required %tensor quantity in the given integration point |
void give_quant(long ipp, mechquant mqn, mechquant reftensq, long lcid, sel &selcomp, strastre array_strastre, matrix &qv); |
/// returns value of the required quantity defined in the given integration point |
void give_quant(long ipp, mechquant mq, mechquant reftensq, long lcid, quantrep qr, sel &selcomp, strastre array_strastre, |
double &sv, vector &vv, matrix &tv); |
/// returns required mechanical quantity for passed to TRFEL |
double givemechq(nontransquant qt, long ipp); |
414,6 → 435,9 |
/// returns given non-mechanical quantity from nonmechq array on given integration point |
double givenonmechq (nonmechquant qt, long ipp); |
/// returns components of non-mechanical quantity array nonmechq on given integration point |
void give_nonmechqcomp (long ipp, sel selcomp, vector &nmqcomp); |
/// stores given non-mechanical quantity from nonmechq array on given integration point |
void storenonmechq (nonmechquant qt, long ipp, double val); |
/trunk/SIFEL/MEFEL/SRC/mechprint.cpp |
---|
30,6 → 30,7 |
#include <stdlib.h> |
#include <math.h> |
#include <string.h> |
#include <set> |
47,7 → 48,7 |
@return The function does not return anything. |
Created 2004 by Tomas Koudelka, koudelka@cml.fsv.cvut.cz |
Created 2004 by Tomas Koudelka, tomas.koudelka@fsv.cvut.cz |
*/ |
void print_init(long istep, const char *mode, long idn1, long ide1) |
244,7 → 245,7 |
@return The function does not return anything. |
Created 2004 by Tomas Koudelka, koudelka@cml.fsv.cvut.cz |
Created 2004 by Tomas Koudelka, tomas.koudelka@fsv.cvut.cz |
*/ |
void print_step(long lcid, long istep, double lambda, double *fi) |
298,7 → 299,7 |
@return The function does not return anything. |
Created 2004 by Tomas Koudelka, koudelka@cml.fsv.cvut.cz |
Created 2004 by Tomas Koudelka, tomas.koudelka@fsv.cvut.cz |
*/ |
void print_step_forced(long lcid, long istep, double lambda, double *fi) |
346,7 → 347,7 |
@return The function does not return anything. |
Created 2004 by Tomas Koudelka, koudelka@cml.fsv.cvut.cz |
Created 2004 by Tomas Koudelka, tomas.koudelka@fsv.cvut.cz |
*/ |
void print_flush() |
370,7 → 371,7 |
@return The function does not return anything. |
Created 2004 by Tomas Koudelka, koudelka@cml.fsv.cvut.cz |
Created 2004 by Tomas Koudelka, tomas.koudelka@fsv.cvut.cz |
*/ |
void print_close() |
{ |
400,7 → 401,7 |
@return The function does not return anything. |
Created 2004 by Tomas Koudelka, koudelka@cml.fsv.cvut.cz |
Created 2004 by Tomas Koudelka, tomas.koudelka@fsv.cvut.cz |
*/ |
void export_gid_mesh(FILE *out, long idn1, long ide1) |
{ |
734,6 → 735,34 |
} |
if (print_header == 0) |
fprintf(out, "end Elements\n"); |
print_header = 1; |
for (i=0; i < Mt->ne; i++) |
{ |
if (Gtm->leso[i]==0) |
continue; |
switch(Mt->elements[i].te) |
{ |
case hexintface: |
if (print_header) |
{ |
fprintf(out, "MESH \"%ld-hexintface\" dimension 3 Elemtype Quadrilateral Nnode 4\n", ide1); |
print_header = 0; |
if (print_coord) |
{ |
write_gid_nodes(out, idn1); |
print_coord = 0; |
} |
fprintf(out, "Elements\n"); |
} |
write_gid_contact_element(out, i, idn1, ide1); |
break; |
default: |
break; |
} |
} |
if (print_header == 0) |
fprintf(out, "end Elements\n"); |
} |
747,7 → 776,7 |
@return The function does not return anything. |
Created 2004 by Tomas Koudelka, koudelka@cml.fsv.cvut.cz |
Created 2004 by Tomas Koudelka, tomas.koudelka@fsv.cvut.cz |
*/ |
void export_gid_gauss_pt(FILE *out, long ide1) |
{ |
1384,6 → 1413,22 |
break; |
} |
} |
for (i=0; i < Mt->ne; i++) |
{ |
if (Gtm->leso[i]==0) |
continue; |
if (Mt->elements[i].te == hexintface) |
{ |
fprintf(out, "GaussPoints \"%d\" Elemtype Quadrilateral \"%ld-hexintface\"\n", Mt->elements[i].te, ide1); |
fprintf(out, "Number Of Gauss Points: %ld\n", Hexifc->tnip); |
fprintf(out, "Nodes not included\n"); |
fprintf(out, "Natural coordinates: internal\n"); |
fprintf(out, "end GaussPoints\n\n"); |
break; |
} |
} |
} |
1398,7 → 1443,7 |
@return The function does not return anything. |
Created 2004 by Tomas Koudelka, koudelka@cml.fsv.cvut.cz |
Created 2004 by Tomas Koudelka, tomas.koudelka@fsv.cvut.cz |
*/ |
void export_gid_2dmesh(FILE *out, long icut, long idn1, long ide1) |
{ |
1449,7 → 1494,7 |
@return The function does not return anything. |
Created 2004 by Tomas Koudelka, koudelka@cml.fsv.cvut.cz |
Created 2004 by Tomas Koudelka, tomas.koudelka@fsv.cvut.cz |
*/ |
void write_gid_nodes(FILE *out, long idn1) |
{ |
1472,7 → 1517,7 |
@return The function does not return anything. |
Created 2004 by Tomas Koudelka, koudelka@cml.fsv.cvut.cz |
Created 2004 by Tomas Koudelka, tomas.koudelka@fsv.cvut.cz |
*/ |
void write_gid_element(FILE *out, long i, long idn1, long ide1) |
{ |
1501,7 → 1546,7 |
@return The function does not return anything. |
Created 2013 by Tomas Koudelka, koudelka@cml.fsv.cvut.cz |
Created 2013 by Tomas Koudelka, tomas.koudelka@fsv.cvut.cz |
*/ |
void write_gid_contact_element(FILE *out, long i, long idn1, long ide1) |
{ |
1530,7 → 1575,7 |
@return The function does not return anything. |
Created 2004 by Tomas Koudelka, koudelka@cml.fsv.cvut.cz |
Created 2004 by Tomas Koudelka, tomas.koudelka@fsv.cvut.cz |
*/ |
void write_gid_2delement(FILE *out, long i, long id1, long nne, long icut, long di, long idn1, long ide1) |
{ |
1547,6 → 1592,101 |
/** |
The function prints set of elements of required types to the GiD mesh file. |
@param[in,out] out - pointer to the opened GiD mesh file |
@param[in] reqet - set of required element types that will be printed |
@param[in] header - string with element set header quoting section of elements of one common type |
@param[in] idn1 - shift index of the nodal numbers |
@param[in] ide1 - shift index of the element numbers |
@return The function does not return anything, but it may change the content of the file referred by the argumnet out. |
Created by Tomas Koudelka, 10.2023 |
*/ |
void write_gid_elem_set(FILE *out, const std::set<elemtype> &reqet, const char *header, long idn1, long ide1) |
{ |
long i; |
bool pheader = true; |
for (i=0; i < Mt->ne; i++) |
{ |
if (Gtm->leso[i]==0) |
continue; |
if (reqet.find(Mt->elements[i].te) != reqet.end()){ |
if (pheader){ |
fprintf(out, "%s\n", header); |
fprintf(out, "Elements\n"); |
pheader = false; |
} |
write_gid_element(out, i, idn1, ide1); |
} |
} |
if (pheader == false) |
fprintf(out, "End Elements\n"); |
} |
/** |
The function exports nodes and sets of used elements to the file given by parameter out in the GiD mesh format. |
@param out - pointer to the opened text file where the output will be produced |
@param idn1 - id of the first node for GiD mesh (default should be idn1 = 1 -> nodes are numbered from 1) |
@param ide1 - id of the first element for GiD mesh (default should be ide1 = 1 -> elements are numbered from 1) |
@return The function does not return anything, but it changes the content of file referred by the argumnet out. |
Created by Tomas Koudelka, 10.2023, tomas.koudelka@fsv.cvut.cz |
*/ |
void write_gid_mesh(FILE *out, long idn1, long ide1) |
{ |
const long hs = 1025; |
char header[hs]; |
write_gid_nodes(out, idn1); |
snprintf(header, hs, "MESH \"%ld-beams2\" dimension 3 Elemtype Linear Nnode 2\n", ide1); |
write_gid_elem_set(out, {bar2d, bar3d, beam2d, beam3d, subsoilbeam}, header, idn1, ide1); |
snprintf(header, hs, "MESH \"%ld-plcontact2l\" dimension 3 Elemtype Linear Nnode 2\n", ide1); |
write_gid_elem_set(out, {planequadinterface}, header, idn1, ide1); |
snprintf(header, hs, "MESH \"%ld-beams3\" dimension 3 Elemtype Linear Nnode 3\n", ide1); |
write_gid_elem_set(out, {barq2d, barq3d}, header, idn1, ide1); |
snprintf(header, hs, "MESH \"%ld-trias3\" dimension 3 Elemtype Triangle Nnode 3\n", ide1); |
write_gid_elem_set(out, {cctel, dktel, dstel, subsoilplatetr, axisymmlt, planeelementlt, |
planeelementrotlt, shelltrelem, shelltrmelem}, header, idn1, ide1); |
snprintf(header, hs, "MESH \"%ld-trias6\" dimension 3 Elemtype Triangle Nnode 6\n", ide1); |
write_gid_elem_set(out, {axisymmqt, planeelementqt}, header, idn1, ide1); |
snprintf(header, hs, "MESH \"%ld-Quads4\" dimension 3 Elemtype Quadrilateral Nnode 4\n", ide1); |
write_gid_elem_set(out, {axisymmlq, planeelementlq, planeelementrotlq, q4plateel, subsoilplateq}, header, idn1, ide1); |
snprintf(header, hs, "MESH \"%ld-Quads8\" dimension 3 Elemtype Quadrilateral Nnode 8\n", ide1); |
write_gid_elem_set(out, {planeelementqq, axisymmqq, axisymmcq}, header, idn1, ide1); |
snprintf(header, hs, "MESH \"%ld-Tetras4\" dimension 3 Elemtype Tetrahedra Nnode 4\n", ide1); |
write_gid_elem_set(out, {lineartet}, header, idn1, ide1); |
snprintf(header, hs, "MESH \"%ld-Tetras10\" dimension 3 Elemtype Tetrahedra Nnode 10\n", ide1); |
write_gid_elem_set(out, {quadrtet}, header, idn1, ide1); |
snprintf(header, hs, "MESH \"%ld-Brick8\" dimension 3 Elemtype Hexahedra Nnode 8\n", ide1); |
write_gid_elem_set(out, {linearhex}, header, idn1, ide1); |
snprintf(header, hs, "MESH \"%ld-Brick20\" dimension 3 Elemtype Hexahedra Nnode 20\n", ide1); |
write_gid_elem_set(out, {quadrhex}, header, idn1, ide1); |
snprintf(header, hs, "MESH \"%ld-hexintface\" dimension 3 Elemtype Quadrilateral Nnode 4\n", ide1); |
write_gid_elem_set(out, {hexintface}, header, idn1, ide1); |
} |
/** |
The function writes displacement vector for all nodes to the file given by parameter out in GiD format. |
The results are printed for all nodes with no dependency on the outdriver selection. |
1556,7 → 1696,7 |
@return The function does not return anything. |
Created 2004 by Tomas Koudelka, koudelka@cml.fsv.cvut.cz |
Created 2004 by Tomas Koudelka, tomas.koudelka@fsv.cvut.cz |
*/ |
void write_gid_displ(FILE *out, long lcid, const char *desclcid) |
{ |
1672,8 → 1812,8 |
@return The function does not return anything. |
created 06.2007 by Tomas Koudelka, koudelka@cml.fsv.cvut.cz |
modified 04.2016 by Tomas Koudelka, koudelka@cml.fsv.cvut.cz |
created 06.2007 by Tomas Koudelka, tomas.koudelka@fsv.cvut.cz |
modified 04.2016 by Tomas Koudelka, tomas.koudelka@fsv.cvut.cz |
*/ |
void write_gid_nforces(FILE *out, long lcid, const char *desclcid, double *ifor) |
{ |
1839,7 → 1979,7 |
@return The function does not return anything. |
Created 2004 by Tomas Koudelka, koudelka@cml.fsv.cvut.cz |
Created 2004 by Tomas Koudelka, tomas.koudelka@fsv.cvut.cz |
*/ |
void write_gid_nodscalar(FILE *out, strastre scal, long lcid, long dir, const char *desclcid) |
{ |
1847,7 → 1987,6 |
long i, ncompstr, ncompother; |
double aux; |
long ir; |
const char *namevar[] = {"x", "y", "z"}; |
matrix t; |
vector str, p; |
2017,7 → 2156,7 |
if (Outdm->nog.transtre[ir] > 0) |
{ |
Mt->give_nodal_coord(i, p); |
Outdm->lcs[Outdm->nog.transtre[ir]-1].evaluate_t(p, namevar, t); |
Outdm->lcs[Outdm->nog.transtre[ir]-1].give_transfmat(t, p, Mp->time); |
str.n = ncompstr; |
str.a = Mt->nodes[i].stress+ncompstr*lcid; |
if (ncompstr == 4) |
2043,7 → 2182,7 |
if (Outdm->nog.transtra[ir] > 0) |
{ |
Mt->give_nodal_coord(i, p); |
Outdm->lcs[Outdm->nog.transtra[ir]-1].evaluate_t(p, namevar, t); |
Outdm->lcs[Outdm->nog.transtra[ir]-1].give_transfmat(t, p, Mp->time); |
str.n = ncompstr; |
str.a = Mt->nodes[i].strain+ncompstr*lcid; |
if (ncompstr == 4) |
2118,7 → 2257,7 |
@return The function does not return anything. |
created 3.10.2007 by Tomas Koudelka, koudelka@cml.fsv.cvut.cz |
created 3.10.2007 by Tomas Koudelka, tomas.koudelka@fsv.cvut.cz |
*/ |
void write_gid_nodvector(FILE *out, strastre q, long lcid, long sid, const char *desclcid) |
{ |
2243,7 → 2382,7 |
@return The function does not return anything. |
created 4.10.2007 by Tomas Koudelka, koudelka@cml.fsv.cvut.cz |
created 4.10.2007 by Tomas Koudelka, tomas.koudelka@fsv.cvut.cz |
*/ |
void write_gid_nodtensor(FILE *out, strastre q, long lcid, long sid, const char *desclcid) |
{ |
2250,7 → 2389,6 |
char sig[70]; |
long i, ncompstr, ncompother; |
long asid, q_id1, q_n; |
const char *namevar[] = {"x", "y", "z"}; |
matrix t(ASTCKMAT(3,3)); // tensor represenation of the given quantity |
matrix tmat; // transformation matrix to the local coordinate system |
vector str, p; |
2345,7 → 2483,7 |
if (Outdm->nog.transtra[sid] > 0) |
{ |
Mt->give_nodal_coord(i, p); |
Outdm->lcs[Outdm->nog.transtra[sid]-1].evaluate_t(p, namevar, tmat); |
Outdm->lcs[Outdm->nog.transtra[sid]-1].give_transfmat(tmat, p, Mp->time); |
glmatrixtransf(t, tmat); |
} |
if (q_n == 6) |
2371,7 → 2509,7 |
if (Outdm->nog.transtre[sid] > 0) |
{ |
Mt->give_nodal_coord(i, p); |
Outdm->lcs[Outdm->nog.transtre[sid]-1].evaluate_t(p, namevar, tmat); |
Outdm->lcs[Outdm->nog.transtre[sid]-1].give_transfmat(tmat, p, Mp->time); |
glmatrixtransf(t, tmat); |
} |
if (q_n == 6) |
2421,7 → 2559,7 |
@return The function does not return anything. |
Created 2004 by Tomas Koudelka, koudelka@cml.fsv.cvut.cz |
Created 2004 by Tomas Koudelka, tomas.koudelka@fsv.cvut.cz |
*/ |
void write_gid_elemscalar(FILE *out, strastre scal, long lcid, long dir, const char *desclcid) |
{ |
2549,6 → 2687,9 |
if (Qwed) |
write_gid_elem_type_scalar(out, scal, lcid, dir, desclcid, quadrwed); |
if (Hexifc) |
write_gid_elem_type_scalar(out, scal, lcid, dir, desclcid, hexintface); |
} |
2567,8 → 2708,8 |
@return The function does not return anything. |
Created 2004 by Tomas Koudelka, koudelka@cml.fsv.cvut.cz |
modified 04.2016 by Tomas Koudelka, koudelka@cml.fsv.cvut.cz |
Created 2004 by Tomas Koudelka, tomas.koudelka@fsv.cvut.cz |
modified 04.2016 by Tomas Koudelka, tomas.koudelka@fsv.cvut.cz |
*/ |
void write_gid_elem_type_scalar(FILE *out, strastre scal, long lcid, long dir, const char *desclcid, elemtype te) |
{ |
2577,7 → 2718,6 |
long i, j, ipp,ncompstr,ncompother,tnip, ir; |
long print_header = 1; |
long num_copy_ip; |
const char *namevar[] = {"x", "y", "z"}; |
matrix t; |
vector str, p; |
double aux; |
2726,7 → 2866,24 |
print_err("unknown direction of stresses is required", __FILE__, __LINE__, __func__); |
} |
break; |
case planecontact: |
switch(dir){ |
case 0: |
sig = "tau_1"; |
break; |
case 1: |
if (te == hexintface) |
sig = "tau_2"; |
else |
sig = "sig_n"; |
break; |
case 2: |
sig = "sig_n"; |
break; |
default: |
print_err("unknown direction of stresses is required", __FILE__, __LINE__, __func__); |
} |
break; |
case platek:{ |
switch (dir){ |
case 0: |
2908,6 → 3065,24 |
} |
break; |
case planecontact: |
switch(dir){ |
case 0: |
sig = "slip_1"; |
break; |
case 1: |
if (te == hexintface) |
sig = "slip_2"; |
else |
sig = "norm_d"; |
break; |
case 2: |
sig = "norm_d"; |
break; |
default: |
print_err("unknown direction of strains is required", __FILE__, __LINE__, __func__); |
} |
break; |
case plates:{ |
switch (dir){ |
case 0:{ |
3092,7 → 3267,7 |
if (Outdm->eog.transtra[ir] > 0) |
{ |
ipcoord(Mm->elip[ipp], ipp, 0, 0, p); |
Outdm->lcs[Outdm->eog.transtra[ir]-1].evaluate_t(p, namevar, t); |
Outdm->lcs[Outdm->eog.transtra[ir]-1].give_transfmat(t, p, Mp->time); |
gl_comp_engvectortransf(str, aux, dir, t, Mm->ip[ipp].ssst, strain); |
fprintf(out, " % e\n", aux); |
} |
3104,7 → 3279,7 |
if (Outdm->eog.transtra[ir] > 0) |
{ |
ipcoord(Mm->elip[ipp], ipp, 0, 0, p); |
Outdm->lcs[Outdm->eog.transtra[ir]-1].evaluate_t(p, namevar, t); |
Outdm->lcs[Outdm->eog.transtra[ir]-1].give_transfmat(t, p, Mp->time); |
gl_comp_engvectortransf(str, aux, dir, t, Mm->ip[ipp].ssst, strain); |
fprintf(out, "%7c % e\n", ' ', aux); |
} |
3117,7 → 3292,7 |
if (Outdm->eog.transtra[ir] > 0) |
{ |
ipcoord(Mm->elip[ipp], ipp, 0, 0, p); |
Outdm->lcs[Outdm->eog.transtra[ir]-1].evaluate_t(p, namevar, t); |
Outdm->lcs[Outdm->eog.transtra[ir]-1].give_transfmat(t, p, Mp->time); |
gl_comp_engvectortransf(str, aux, dir, t, Mm->ip[ipp].ssst, strain); |
} |
for (j = 0; j < num_copy_ip; j++) |
3159,7 → 3334,7 |
if (Outdm->eog.transtre[ir] > 0) |
{ |
ipcoord(Mm->elip[ipp], ipp, 0, 0, p); |
Outdm->lcs[Outdm->eog.transtre[ir]-1].evaluate_t(p, namevar, t); |
Outdm->lcs[Outdm->eog.transtre[ir]-1].give_transfmat(t, p, Mp->time); |
gl_comp_engvectortransf(str, aux, dir, t, Mm->ip[ipp].ssst, stress); |
fprintf(out, " % e\n", aux); |
} |
3174,7 → 3349,7 |
if (Outdm->eog.transtre[ir] > 0) |
{ |
ipcoord(Mm->elip[ipp], ipp, 0, 0, p); |
Outdm->lcs[Outdm->eog.transtre[ir]-1].evaluate_t(p, namevar, t); |
Outdm->lcs[Outdm->eog.transtre[ir]-1].give_transfmat(t, p, Mp->time); |
gl_comp_engvectortransf(str, aux, dir, t, Mm->ip[ipp].ssst, stress); |
fprintf(out, "%7c % e\n", ' ', aux); |
} |
3188,7 → 3363,7 |
if (Outdm->eog.transtre[ir] > 0) |
{ |
ipcoord(Mm->elip[ipp], ipp, 0, 0, p); |
Outdm->lcs[Outdm->eog.transtre[ir]-1].evaluate_t(p, namevar, t); |
Outdm->lcs[Outdm->eog.transtre[ir]-1].give_transfmat(t, p, Mp->time); |
gl_comp_engvectortransf(str, aux, dir, t, Mm->ip[ipp].ssst, stress); |
} |
for (j = 0; j < num_copy_ip; j++) |
3274,7 → 3449,7 |
@return The function does not return anything. |
created 4.10.2007 by Tomas Koudelka, koudelka@cml.fsv.cvut.cz |
created 4.10.2007 by Tomas Koudelka, tomas.koudelka@fsv.cvut.cz |
*/ |
void write_gid_elemvector(FILE *out, strastre q, long lcid, long sid, const char *desclcid) |
{ |
3389,6 → 3564,10 |
if (Qwed) |
write_gid_elem_type_vector(out, q, lcid, sid, desclcid, quadrwed); |
if (Hexifc) |
write_gid_elem_type_vector(out, q, lcid, sid, desclcid, hexintface); |
} |
3407,7 → 3586,7 |
@return The function does not return anything. |
created 4.10.2007 by Tomas Koudelka, koudelka@cml.fsv.cvut.cz |
created 4.10.2007 by Tomas Koudelka, tomas.koudelka@fsv.cvut.cz |
*/ |
void write_gid_elem_type_vector(FILE *out, strastre q, long lcid, long sid, const char *desclcid, elemtype te) |
{ |
3645,7 → 3824,7 |
@return The function does not return anything. |
created 4.10.2007 by Tomas Koudelka, koudelka@cml.fsv.cvut.cz |
created 4.10.2007 by Tomas Koudelka, tomas.koudelka@fsv.cvut.cz |
*/ |
void write_gid_elemtensor(FILE *out, strastre q, long lcid, long sid, const char *desclcid) |
{ |
3760,6 → 3939,9 |
if (Qwed) |
write_gid_elem_type_tensor(out, q, lcid, sid, desclcid, quadrwed); |
if (Hexifc) |
write_gid_elem_type_tensor(out, q, lcid, sid, desclcid, hexintface); |
} |
3778,7 → 3960,7 |
@return The function does not return anything. |
created 4.10.2007 by Tomas Koudelka, koudelka@cml.fsv.cvut.cz |
created 4.10.2007 by Tomas Koudelka, tomas.koudelka@fsv.cvut.cz |
*/ |
void write_gid_elem_type_tensor(FILE *out, strastre q, long lcid, long sid, const char *desclcid, elemtype te) |
{ |
3792,7 → 3974,6 |
matrix t(ASTCKMAT(3,3)); // tensor represenation of the given quantity |
matrix tmat; // transformation matrix to the local coordinate system |
vector str, p; |
const char *namevar[] = {"x", "y", "z"}; |
if(Outdm->nlcs > 0) |
{ |
3953,7 → 4134,7 |
if (Outdm->eog.transtra[sid] > 0) |
{ |
ipcoord(Mm->elip[ipp], ipp, 0, 0, p); |
Outdm->lcs[Outdm->eog.transtra[sid]-1].evaluate_t(p, namevar, tmat); |
Outdm->lcs[Outdm->eog.transtra[sid]-1].give_transfmat(tmat, p, Mp->time); |
glmatrixtransf(t, tmat); |
} |
if (q_n == 6) |
3972,7 → 4153,7 |
if (Outdm->eog.transtra[sid] > 0) |
{ |
ipcoord(Mm->elip[ipp], ipp, 0, 0, p); |
Outdm->lcs[Outdm->eog.transtra[sid]-1].evaluate_t(p, namevar, tmat); |
Outdm->lcs[Outdm->eog.transtra[sid]-1].give_transfmat(tmat, p, Mp->time); |
glmatrixtransf(t, tmat); |
} |
if (q_n == 6) |
4003,7 → 4184,7 |
if (Outdm->eog.transtre[sid] > 0) |
{ |
ipcoord(Mm->elip[ipp], ipp, 0, 0, p); |
Outdm->lcs[Outdm->eog.transtre[sid]-1].evaluate_t(p, namevar, tmat); |
Outdm->lcs[Outdm->eog.transtre[sid]-1].give_transfmat(tmat, p, Mp->time); |
glmatrixtransf(t, tmat); |
} |
if (q_n == 6) |
4022,7 → 4203,7 |
if (Outdm->eog.transtre[sid] > 0) |
{ |
ipcoord(Mm->elip[ipp], ipp, 0, 0, p); |
Outdm->lcs[Outdm->eog.transtre[sid]-1].evaluate_t(p, namevar, tmat); |
Outdm->lcs[Outdm->eog.transtre[sid]-1].give_transfmat(tmat, p, Mp->time); |
glmatrixtransf(t, tmat); |
} |
if (q_n == 6) |
6284,3 → 6465,241 |
fprintf (aux,"\n"); |
fflush (aux);*/ |
} |
/** |
The function prints header, points and used elements to the VTK file |
@param[in,out] out - pointer to the opened VTK file |
@param[in] istep - integration step |
@param[in] time - actual time or load coefficient |
@return The function does not return anything, but changes content of file given by the argument out. |
Created by Vit Smilauer, modified by Tomas Koudelka, 10.2023 |
*/ |
void print_vtk_header(FILE *out, long istep, double time) |
{ |
long i, j, nn; |
// array of nodal correspondence on linear hexahedron element |
long trlh[8] = {6, 7, 4, 5, //xy, z=0, xi=x,nu=y, theta=z |
2, 3, 0, 1}; //xy, z<>0 |
// array of nodal correspondence on quadratic hexahedron element |
long trqh[20] = { 6, 7, 4, 5,//xy, z=0, xi=x,nu=y, theta=z |
2, 3, 0, 1, |
18, 19, 16, 17, |
10, 11, 8, 9, |
14, 15, 12, 13}; |
fprintf(out, "# vtk DataFile Version 1.0\n"); |
fprintf(out, "Time step %ld time %lf\n", istep, time); |
fprintf(out, "ASCII\n\n"); |
fprintf(out, "DATASET UNSTRUCTURED_GRID\n"); |
fprintf(out, "POINTS %ld float\n", Mt->nn); |
for (i=0; i<Mt->nn; i++){ |
fprintf(out, "%e %e %e\n", Gtm->gnodes[i].x, Gtm->gnodes[i].y, Gtm->gnodes[i].z); |
} |
long int ncells = 0; |
for (i=0; i < Mt->ne; i++){ |
ncells += Mt->give_nne (i); |
} |
fprintf(out, "\nCELLS %ld %ld\n", Mt->ne, ncells+Mt->ne); |
for (i=0; i < Mt->ne; i++){ |
fprintf(out, "%ld ", Mt->give_nne(i));//number of nodes on element |
for(j=0;j<Mt->give_nne(i);j++){ |
switch(Mt->elements[i].te){ //due to node renumbering |
case linearhex: |
nn=trlh[j]; |
break; |
case quadrhex: |
nn=trqh[j]; |
break; |
default: |
nn=j; |
break; |
} |
fprintf(out, "%ld ", Gtm->gelements[i].nodes[nn]); |
} |
fprintf(out, "\n"); |
} |
//output cell types |
fprintf(out, "\nCELL_TYPES %ld\n", Mt->ne); |
for (i=0; i < Mt->ne; i++){ |
switch(Mt->elements[i].te){ |
case bar2d: |
case beam2d: |
case bar3d: |
case beam3d: |
fprintf(out, "3\n");//VTK_LINE |
break; |
case barq2d: |
case barq3d: |
fprintf(out, "21\n");//VTK_QUADRATIC_EDGE |
break; |
case planeelementlt: |
case axisymmlt: |
fprintf(out, "5\n");//VTK_TRIANGLE |
break; |
case planeelementlq: |
case axisymmlq: |
fprintf(out, "9\n");//VTK_QUAD |
break; |
case planeelementqq: |
case axisymmqq: |
fprintf(out, "23\n");//VTK_QUADRATIC_QUAD |
break; |
case lineartet: |
fprintf(out, "10\n");//VTK_TETRA |
break; |
case linearhex: |
fprintf(out, "12\n");//VTK_HEXAHEDRON - Renumbered nodes |
break; |
case quadrhex: |
fprintf(out, "25\n");//VTK_QUADRATIC_HEXAHEDRON - Renumbered nodes |
break; |
default: |
print_err("unknown element type in VTK export", __FILE__, __LINE__, __func__); |
abort(); |
break; |
} |
} |
} |
/** |
The function prints data to the VTK file. |
VTK can not handle integration points directly, results in nodes only |
@param[in,out] out - pointer to the opened VTK file |
@param[in] lcid - load case id |
@return The function does not return anything, but changes content of file given by the argument out. |
Created by Vit Smilauer, modified by Tomas Koudelka, 10.2023 |
*/ |
void write_vtk_unkn(FILE *out, long lcid) |
{ |
vector r; |
long i, j, k, ncomp, max_ncomp; |
fprintf(out, "\nPOINT_DATA %ld\n", Mt->nn); |
//displacements at nodes |
if (Outdm->nog.selndisp.st != sel_no){ |
fprintf(out, "VECTORS Nodal_displacements float\n"); |
reallocv(RSTCKVEC(3, r)); |
for (i=0; i<Mt->nn; i++){ |
r[0]=r[1]=r[2]=0; |
noddispl (lcid, r.a, i); |
fprintf(out, "%e %e %e\n", r[0], r[1], r[2]); |
} |
fprintf(out, "\n"); |
} |
// strains at nodes |
if (Outdm->nog.selnstra.st != sel_no){ |
fprintf(out, "TENSORS Strain float\n"); |
for (i=0; i<Mt->nn; i++){ |
ncomp = Mt->nodes[i].ncompstr; |
vector eps(ASTCKVEC(4)); |
matrix epst(ASTCKMAT(3,3)); |
nullv(eps); |
nullm(epst); |
for (j=0; j<ncomp; j++) |
eps[j] = Mt->nodes[i].strain[j]; |
switch (ncomp){ |
case 1:{ |
vector_tensor (eps, epst, bar, strain); |
break; |
} |
case 4:{ |
vector_tensor (eps, epst, planestrain, strain);//or planestress |
break; |
} |
case 6:{ |
vector_tensor (eps, epst, spacestress, strain); |
} |
} |
for (k=0; k<3; k++){ |
fprintf(out, "%e %e %e\n", epst[k][0], epst[k][1], epst[k][2]); |
} |
fprintf(out, "\n"); |
} |
} |
// stresses at nodes |
if (Outdm->nog.selnstre.st != sel_no){ |
fprintf(out, "TENSORS Stress float\n"); |
for (i=0; i<Mt->nn; i++){ |
ncomp = Mt->nodes[i].ncompstr; |
vector sig(ASTCKVEC(4)); |
matrix sigt(ASTCKMAT(3,3)); |
nullv(sig); |
nullm(sigt); |
for (j=0; j<ncomp; j++) |
sig[j] = Mt->nodes[i].stress[j]; |
switch (ncomp){ |
case 1:{ |
vector_tensor (sig, sigt, bar, stress); |
break; |
} |
case 4:{ |
vector_tensor (sig, sigt, planestrain, stress);//or planestress |
break; |
} |
case 6:{ |
vector_tensor (sig, sigt, spacestress, stress); |
} |
} |
for (k=0; k<3; k++){ |
fprintf(out, "%e %e %e\n", sigt[k][0], sigt[k][1], sigt[k][2]); |
} |
fprintf(out, "\n"); |
} |
} |
// other values at nodes |
if (Outdm->nog.selnoth.st != sel_no){ |
max_ncomp = 0; |
for (k=0; k<Mm->tnip; k++){//find maximum eqother components |
max_ncomp > Mm->ip[k].ncompother ? max_ncomp = Mm->ip[k].ncompother : 0; |
} |
for(i=0; i<max_ncomp; i++){// other[i] |
for (j=0; j<Outdm->nog.selnoth.n; j++){ |
if (Outdm->nog.seloth[j].presence_id(i)){ |
fprintf(out, "\nSCALARS Eq_other_s%ld_%ld double\nLOOKUP_TABLE default\n", j+1, i+1); |
for (k=0; k < Mt->nn; k++) |
fprintf(out, "%e\n", Mt->nodes[k].giveother(i)); |
} |
} |
} |
/* fprintf(out, "TENSORS Other float\n"); |
for (i=0; i<Mt->nn; i++){ |
ncomp = Mt->nodes[i].ncompother; |
vector oth(ASTCKVEC(4)); |
matrix otht(ASTCKMAT(3,3)); |
nullv(oth); |
nullm(otht); |
for (j=0; j<ncomp; j++) |
oth[j] = Mt->nodes[i].other[j]; |
switch (ncomp){ |
case 1:{ |
vector_tensor (oth, otht, bar, stress); |
break; |
} |
case 4:{ |
vector_tensor (oth, otht, planestrain, stress);//or planestress |
break; |
} |
case 6:{ |
vector_tensor (oth, otht, spacestress, stress); |
} |
} |
for (k=0; k<3; k++){ |
fprintf(out, "%e %e %e\n", otht[k][0], otht[k][1], otht[k][2]); |
} |
fprintf(out, "\n"); |
}*/ |
} |
// reactions - not implemented |
} |
/trunk/SIFEL/MEFEL/SRC/mechprint.h |
---|
1,8 → 1,11 |
#ifndef MECHPRINT_H |
#define MECHPRINT_H |
#include "alias.h" |
#include <stdio.h> |
#include "alias.h" |
#include <set> |
class gtopology; |
class probdesc; |
class mechtop; |
35,6 → 38,8 |
void write_gid_elemtensor(FILE *out, strastre q, long lcid, long sid, const char *desclcid); |
void write_gid_elem_type_tensor(FILE *out, strastre q, long lcid, long sid, const char *desclcid, elemtype te); |
void write_gid_elem_set(FILE *out, const std::set<elemtype> &reqet, const char *header, long idn1, long ide1); |
void export_femcad(FILE *out); |
void write_nodes(FILE *out); |
void write_elements(FILE *out); |
89,6 → 94,14 |
//void print_default_2_dx (gtopology *gt,probdesc *mp,mechtop *mt,long lcid,const char *file); |
/* termitovo */ |
/// prints header, points and used elements to the VTK file |
void print_default_vtk(FILE *out, long lcid, long istep, double lambda); |
///prints data to the VTK file |
void write_vtk_unkn(FILE *out, long lcid); |
void print_vtk_header(FILE *out, long istep, double time); |
void aux_mech_nonlin_print (FILE *aux,double *r,double l); |
void aux_mech_time_print (FILE *aux,double *r,double l); |
/trunk/SIFEL/MEFEL/SRC/mechtop.cpp |
---|
20,6 → 20,8 |
#include "saddpoint.h" |
#include "vecttens.h" |
#include "ipmap.h" |
#include "gnodvalvm.h" |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
712,10 → 714,11 |
case linearhexrot:{ ndofe=Lhexrot->ndofe; break; } |
case linearwed:{ ndofe=Lwed->ndofe; break; } |
case quadrwed:{ ndofe=Qwed->ndofe; break; } |
case hexintface:{ ndofe=Hexifc->ndofe; break; } |
case particleelem:{ ndofe=Pelem->ndofe; break; } |
case tetralatt:{ ndofe=Tlatt->ndofe; break; } |
default:{ |
print_err("unknown element type is required",__FILE__,__LINE__,__func__); |
print_err("unknown element type '%d' is required on element %ld",__FILE__,__LINE__,__func__, te, eid+1); |
} |
} |
return ndofe; |
852,6 → 855,7 |
case linearhexrot:{ nne=Lhexrot->nne; break; } |
case linearwed:{ nne=Lwed->nne; break; } |
case quadrwed:{ nne=Qwed->nne; break; } |
case hexintface:{ nne=Hexifc->nne; break; } |
case particleelem:{ nne=Pelem->nne; break; } |
case tetralatt:{ nne=Tlatt->nne; break; } |
default:{ |
931,6 → 935,7 |
case linearhexrot:{ nip=Lhexrot->nip[ri][ci]; break; } |
case linearwed:{ nip=Lwed->nip[ri][ci]; break; } |
case quadrwed:{ nip=Qwed->nip[ri][ci]; break; } |
case hexintface:{ nip=Hexifc->nip[ri][ci]; break; } |
case particleelem:{ nip=Pelem->nip[ri][ci]; break; } |
case tetralatt:{ nip=Tlatt->nip[ri][ci]; break; } |
default:{ |
1083,6 → 1088,7 |
case linearhexrot:{ tnip=Lhexrot->tnip; break; } |
case linearwed:{ tnip=Lwed->tnip; break; } |
case quadrwed:{ tnip=Qwed->tnip; break; } |
case hexintface:{ tnip=Hexifc->tnip; break; } |
case particleelem:{ tnip=1; break; } |
case tetralatt:{ tnip=Tlatt->tnip; break; } |
default:{ |
1219,6 → 1225,7 |
case linearhexrot:{ ncomp=Lhexrot->tncomp; break; } |
case linearwed:{ ncomp=Lwed->tncomp; break; } |
case quadrwed:{ ncomp=Qwed->tncomp; break; } |
case hexintface:{ ncomp=Hexifc->tncomp; break; } |
case particleelem:{ ncomp=Pelem->ndofe; break; } |
case tetralatt:{ ncomp=Tlatt->tncomp; break; } |
default:{ |
1316,6 → 1323,7 |
case linearhexrot:{ tncomp=Lhexrot->tncomp; break; } |
case linearwed:{ tncomp=Lwed->tncomp; break; } |
case quadrwed:{ tncomp=Qwed->tncomp; break; } |
case hexintface:{ tncomp=Hexifc->tncomp; break; } |
case particleelem:{ tncomp=Pelem->ndofe; break; } |
case tetralatt:{ tncomp=Tlatt->tncomp; break; } |
default:{ |
1675,6 → 1683,7 |
case linearhexrot:{ dim=3; break; } |
case linearwed:{ dim=3; break; } |
case quadrwed:{ dim=3; break; } |
case hexintface:{ dim=3; break; } |
case particleelem:{ break; } |
case tetralatt:{ dim=3; break; } |
default:{ |
1775,6 → 1784,7 |
case linearhexrot:{ nb=Lhexrot->nb; break; } |
case linearwed:{ nb=Lwed->nb; break; } |
case quadrwed:{ nb=Qwed->nb; break; } |
case hexintface:{ nb=Hexifc->nb; break; } |
case particleelem:{ nb=Pelem->nb; break; } |
case tetralatt:{ nb=Tlatt->nb; break; } |
default:{ |
1849,6 → 1859,7 |
case linearhexrot:{ nb=Lhexrot->nb; break; } |
case linearwed:{ nb=Lwed->nb; break; } |
case quadrwed:{ nb=Qwed->nb; break; } |
case hexintface:{ nb=Hexifc->nb; break; } |
case particleelem:{ nb=Pelem->nb; break; } |
case tetralatt:{ nb=Tlatt->nb; break; } |
default:{ |
1964,6 → 1975,7 |
case linearhexrot:{ ssst = Lhexrot->ssst; break; } |
case linearwed:{ ssst = Lwed->ssst; break; } |
case quadrwed:{ ssst = Qwed->ssst; break; } |
case hexintface:{ ssst = Hexifc->ssst; break; } |
case particleelem:{ break; } |
case tetralatt:{ ssst = Tlatt->ssst; break; } |
default:{ |
2037,6 → 2049,7 |
case linearhexrot:{ deg=1; break; } |
case linearwed:{ deg=1; break; } |
case quadrwed:{ deg=2; break; } |
case hexintface:{ deg=1; break; } |
case particleelem:{ break; } |
default:{ |
print_err("unknown element type is required",__FILE__,__LINE__,__func__); |
2889,6 → 2902,355 |
/** |
The function returns required scalar qunatity in the given node. |
The quantity IS returned in the argument qv. |
@param[in] nid - nodal id |
@param[in] mqn - quantity name |
@param[in] reftensq - referenced tensor quantity, it is used only if the mqn |
is an tensor derived value (invariant, norm,...) |
@param[in] lcid - load case id or eigenvalue id. |
@param[out] qv - required quantity value. |
@return The function returns the quantity components in the argument qv. |
Created by Tomas Koudelka 09.2023 |
*/ |
void mechtop::give_nodal_quant(long nid, mechquant mqn, mechquant reftensq, long lcid, double &qv) |
{ |
matrix auxm; |
vector eps, epst, sig; |
qv = 0.0; |
switch (mqn){ |
case time_q: // time (constant scalar quantity at whole domain) |
qv = Mp->time; |
break; |
case step_id_q: // step id (constant scalar quantity at whole domain) |
qv = Mp->istep; |
break; |
case load_fact_q: // load factor in nonlinear statics problem type (constant scalar quantity at whole domain) |
qv = Mp->lambda; |
break; |
case eigval_q: // eigen values in eigenvalue problem type (constant scalar quantity at whole domain) |
//qv = Lsrs->eigv[lcid]; |
break; |
case first_inv: // A11 + A22 + A33 |
reallocm(RSTCKMAT(3, 3, auxm)); |
give_nodal_quant(nid, reftensq, nomech_q, lcid, auxm); |
qv = first_invar(auxm);; |
break; |
case second_inv: // A11*A22 + A11*A33 + A22*A33 - A12^2 - A13^2 - A23^2 |
reallocm(RSTCKMAT(3, 3, auxm)); |
give_nodal_quant(nid, reftensq, nomech_q, lcid, auxm); |
qv = second_invar(auxm);; |
break; |
case third_inv: // det|A| |
reallocm(RSTCKMAT(3, 3, auxm)); |
give_nodal_quant(nid, reftensq, nomech_q, lcid, auxm); |
qv = third_invar(auxm);; |
break; |
case tensor_norm: // ||A|| : sqrt(a_ij*a_ij) |
reallocm(RSTCKMAT(3, 3, auxm)); |
give_nodal_quant(nid, reftensq, nomech_q, lcid, auxm); |
qv = norm(auxm);; |
break; |
case strain_vol: // eps_v : eps_x + eps_y + eps_z |
reallocv(RSTCKVEC(6, eps)); |
give_full_vector(eps, nodes[nid].strain, guess_ssst(nodes[nid].ncompstr)); |
qv = first_invar(eps); |
break; |
case mean_stress: // sig_m : (sig_x + sig_y + sig_z)/3 |
reallocv(RSTCKVEC(6, sig)); |
give_full_vector(sig, nodes[nid].stress, guess_ssst(nodes[nid].ncompstr)); |
qv = (1.0/3.0)*first_invar(sig); |
break; |
case j2inv: // negative value of the second invariant of stress deviator, i.e. J2 : 1/2 s_ij s_ij |
reallocv(RSTCKVEC(6, sig)); |
give_full_vector(sig, nodes[nid].stress, guess_ssst(nodes[nid].ncompstr)); |
qv = j2_stress_invar(sig); |
break; |
case von_mises_stress:// sig_eff : sqrt(3*J2) |
reallocv(RSTCKVEC(6, sig)); |
give_full_vector(sig, nodes[nid].stress, guess_ssst(nodes[nid].ncompstr)); |
qv = 3.0*j2_stress_invar(sig); |
qv = sqrt(qv); |
break; |
//case cons_param: // consistency parameter gamma |
//case damage_scal: // scalar damage (omega) |
//case damaget_scal: // scalar damage (omega_t) in tension |
//case damagec_scal: // scalar damage (omega_c) in compression |
case eps_x: // strain components as scalars |
reallocv(RSTCKVEC(6, eps)); |
give_full_vector(eps, nodes[nid].strain, guess_ssst(nodes[nid].ncompstr)); |
qv = eps(0); |
break; |
case eps_y: |
reallocv(RSTCKVEC(6, eps)); |
give_full_vector(eps, nodes[nid].strain, guess_ssst(nodes[nid].ncompstr)); |
qv = eps(1); |
break; |
case eps_z: |
reallocv(RSTCKVEC(6, eps)); |
give_full_vector(eps, nodes[nid].strain, guess_ssst(nodes[nid].ncompstr)); |
qv = eps(2); |
break; |
case gamma_yz: |
reallocv(RSTCKVEC(6, eps)); |
give_full_vector(eps, nodes[nid].strain, guess_ssst(nodes[nid].ncompstr)); |
qv = eps(3); |
break; |
case gamma_xz: |
reallocv(RSTCKVEC(6, eps)); |
give_full_vector(eps, nodes[nid].strain, guess_ssst(nodes[nid].ncompstr)); |
qv = eps(4); |
break; |
case gamma_xy: |
reallocv(RSTCKVEC(6, eps)); |
give_full_vector(eps, nodes[nid].strain, guess_ssst(nodes[nid].ncompstr)); |
qv = eps(5); |
break; |
case eps_yz: |
reallocv(RSTCKVEC(6, eps)); |
give_full_vector(eps, nodes[nid].strain, guess_ssst(nodes[nid].ncompstr)); |
qv = 0.5*eps(3); |
break; |
case eps_xz: |
reallocv(RSTCKVEC(6, eps)); |
give_full_vector(eps, nodes[nid].strain, guess_ssst(nodes[nid].ncompstr)); |
qv = 0.5*eps(4); |
break; |
case eps_xy: |
reallocv(RSTCKVEC(6, eps)); |
give_full_vector(eps, nodes[nid].strain, guess_ssst(nodes[nid].ncompstr)); |
qv = 0.5*eps(5); |
break; |
case sig_x: // stress components as scalars |
reallocv(RSTCKVEC(6, sig)); |
give_full_vector(sig, nodes[nid].stress, guess_ssst(nodes[nid].ncompstr)); |
qv = sig(0); |
break; |
case sig_y: |
reallocv(RSTCKVEC(6, sig)); |
give_full_vector(sig, nodes[nid].stress, guess_ssst(nodes[nid].ncompstr)); |
qv = sig(1); |
break; |
case sig_z: |
reallocv(RSTCKVEC(6, sig)); |
give_full_vector(sig, nodes[nid].stress, guess_ssst(nodes[nid].ncompstr)); |
qv = sig(2); |
break; |
case tau_yz: |
reallocv(RSTCKVEC(6, sig)); |
give_full_vector(sig, nodes[nid].stress, guess_ssst(nodes[nid].ncompstr)); |
qv = sig(3); |
break; |
case tau_xz: |
reallocv(RSTCKVEC(6, sig)); |
give_full_vector(sig, nodes[nid].stress, guess_ssst(nodes[nid].ncompstr)); |
qv = sig(4); |
break; |
case tau_xy: |
reallocv(RSTCKVEC(6, sig)); |
give_full_vector(sig, nodes[nid].stress, guess_ssst(nodes[nid].ncompstr)); |
qv = sig(5); |
break; |
//case eps_px: // components of plastic strains considered as scalars, will be implemented with the help of new materialpoint concept |
//case eps_py: |
//case eps_pz: |
//case eps_pyz: |
//case eps_pxz: |
//case eps_pxy: |
default: |
print_err("unknown scalar quantity type (%d) is required at node %ld.\n", |
__FILE__, __LINE__, __func__, int(mqn), nid+1); |
abort(); |
} |
} |
/** |
The function returns required components of a vector qunatity in the given node. |
The quantity components are returned in the argument qv. |
@param[in] nid - nodal id |
@param[in] mqn - quantity name |
@param[in] lcid - load case id or eigenvalue id. |
@param[out] qv - required quantity value. |
@return The function returns the quantity components in the argument qv. |
Created by Tomas Koudelka 09.2023 |
*/ |
void mechtop::give_nodal_quant(long nid, mechquant mqn, long lcid, sel &selcomp, gnodvalvm &nv, vector &qv) |
{ |
long i, j, id=0; |
gnode &nod = Gtm->gnodes[nid]; |
switch (mqn){ |
case displ_q: // displacement vector |
for(i=0, j=0; i<nod.ndofn; i++){ |
if(selcomp.presence_id(i)){ |
qv(id) = nv.displv[nod.cn[i]]; |
id++; |
} |
} |
break; |
case react_q: // reactions vector at nodes |
for(i=0; i<nod.ndofn; i++){ |
if(selcomp.presence_id(i)){ |
qv(id) = nodes[nid].r[i]; |
id++; |
} |
} |
break; |
case load_vect_q: // load vector at nodes |
for(i=0; i<nod.ndofn; i++){ |
if(selcomp.presence_id(i)){ |
qv(id) = nv.loadv[nod.cn[i]]; |
id++; |
} |
} |
break; |
case int_force_q: // internal force vector |
for(i=0; i<nod.ndofn; i++){ |
if(selcomp.presence_id(i)){ |
qv(id) = nv.iforv[nod.cn[i]]; |
id++; |
} |
} |
break; |
case resid_vect_q: // residual vector |
for(i=0, j=0; i<nod.ndofn; i++){ |
if(selcomp.presence_id(i)){ |
qv(id) = nv.residv[nod.cn[i]]; |
id++; |
} |
} |
break; |
//case nonmech_q: // nonmechanical quantities are defined on ip |
case other_q: // other array values as a vector |
for(i=0; i < nodes[nid].ncompother; i++){ |
if (selcomp.presence_id(i)){ |
qv(id) = nodes[nid].other[i]; |
id++; |
} |
} |
break; |
default: |
print_err("unknown vector quantity type (%d) is required at node %ld.\n", |
__FILE__, __LINE__, __func__, int(mqn), nid+1); |
abort(); |
} |
} |
/** |
The function returns a required tensor qunatity in a given node. |
The quantity components are returned in the argument qv. |
@param[in] nid - nodal id |
@param[in] mqn - quantity name |
@param[in] reftensq - referenced quantity handled as an ordinary tensor |
@param[in] lcid - load case id or eigenvalue id. |
@param[out] qv - required quantity value. |
@return The function returns the quantity components in the argument qv. |
Created by Tomas Koudelka 09.2023 |
*/ |
void mechtop::give_nodal_quant(long nid, mechquant mqn, mechquant reftensq, long lcid, matrix &qv) |
{ |
vector eps, meps, sig, msig; |
double *epsptr, *sigptr; |
long ncompstr; |
double inv; |
switch (mqn){ |
case strain_q: // strain tensor |
ncompstr = nodes[nid].ncompstr; |
epsptr = nodes[nid].strain+lcid*ncompstr; |
makerefv(eps, epsptr, ncompstr); |
vector_tensor(eps, qv, guess_ssst(nodes[nid].ncompstr), strain); |
break; |
case stress_q: // stress tensor |
ncompstr = nodes[nid].ncompstr; |
sigptr = nodes[nid].stress+lcid*ncompstr; |
makerefv(sig, sigptr, ncompstr); |
vector_tensor(sig, qv, guess_ssst(nodes[nid].ncompstr), stress); |
break; |
//case tempr_strain_q: // temperature strain tensor |
//case eig_strain_q: // eigenstrain tensor |
//case eig_stress_q: // eigenstress tensor |
case macrostrain_q: // macrostrain (constant tensor quantity at whole domain) |
reallocv(RSTCKVEC(Mt->max_ncompstr, meps)); |
macrostrains(lcid, meps); |
vector_tensor(meps, qv, guess_ssst(nodes[nid].ncompstr), strain); |
break; |
case macrostress_q: // macrostress (constant tensor quantity at whole domain) |
reallocv(RSTCKVEC(Mt->max_ncompstr, msig)); |
macrostresses(lcid, msig); |
vector_tensor(msig, qv, guess_ssst(nodes[nid].ncompstr), stress); |
break; |
case tensdeviator: // D_ij : A_ij - delta_ij*A_kk/3 |
give_nodal_quant(nid, reftensq, nomech_q, lcid, qv); |
inv = (qv(0,0)+qv(1,1)+qv(2,2))/3.0; |
qv(0,0) -= inv; |
qv(1,1) -= inv; |
qv(2,2) -= inv; |
break; |
case strain_deviator: // e_ij : eps_ij - delta_ij*eps_v/3 |
makerefv(eps, nodes[nid].strain, nodes[nid].ncompstr); |
vector_tensor(eps, qv, guess_ssst(nodes[nid].ncompstr), strain); |
inv = (qv(0,0)+qv(1,1)+qv(2,2))/3.0; |
qv(0,0) -= inv; |
qv(1,1) -= inv; |
qv(2,2) -= inv; |
break; |
case stress_deviator: // s_ij : sig_ij - delta_ij*sig_m |
makerefv(sig, nodes[nid].stress, nodes[nid].ncompstr); |
vector_tensor(sig, qv, guess_ssst(nodes[nid].ncompstr), stress); |
inv = (qv(0,0)+qv(1,1)+qv(2,2))/3.0; |
qv(0,0) -= inv; |
qv(1,1) -= inv; |
qv(2,2) -= inv; |
break; |
//case strain_pl: // plastic strain tensor |
//case damage_tens: // damage tensor (Omega) |
//case damaget_tens: // damage tensor (Omega_t) in tension |
//case damagec_tens: // damage tensor (Omega_c) in compression |
default: |
print_err("unknown tensor quantity type (%d) is required at node %ld.\n", |
__FILE__, __LINE__, __func__, int(mqn), nid+1); |
abort(); |
} |
} |
void mechtop::give_nodal_quant(long nid, mechquant mq, mechquant reftensq, long lcid, quantrep qr, |
sel &selcomp, gnodvalvm &nv, double &sv, vector &vv, matrix &tv) |
{ |
switch(qr){ |
case scalq: |
give_nodal_quant(nid, mq, reftensq, lcid, sv); |
break; |
case vectq: |
give_nodal_quant(nid, mq, lcid, selcomp, nv, vv); |
break; |
case tensq: |
give_nodal_quant(nid, mq, reftensq, lcid, tv); |
break; |
default: |
print_err("unknown qunatity character type (%d)\n", __FILE__, __LINE__, __func__, int(qr)); |
abort(); |
} |
} |
/** |
The function converts code numbers stored at nodes to code numbers |
stored on elements. It is used for mixed 2D mesh of plane elements, |
bars and springs. |
/trunk/SIFEL/MEFEL/SRC/mechtop.h |
---|
2,6 → 2,7 |
#define MECHTOP_H |
#include <stdio.h> |
#include "galias.h" |
#include "alias.h" |
#include "iotools.h" |
class node; |
14,6 → 15,8 |
struct vector; |
struct ivector; |
class dofrange; |
class gnodvalvm; |
class sel; |
175,6 → 178,19 |
void other_nodal_values (ivector &nod,vector &nx,vector &ny,vector &nz, |
double *lhs,long dim,long fi,long ncomp); |
/// returns value of the required scalar quantity in the given node |
void give_nodal_quant(long nid, mechquant mqn, mechquant reftensq, long lcid, double &qv); |
/// returns value of the required %vector quantity in the given node |
void give_nodal_quant(long nid, mechquant mqn, long lcid, sel &selcomp, gnodvalvm &nv, vector &qv); |
/// returns value of the required %tensor quantity in the given node |
void give_nodal_quant(long nid, mechquant mqn, mechquant reftensq, long lcid, matrix &qv); |
/// returns value of the required quantity defined in the given node |
void give_nodal_quant(long nid, mechquant mq, mechquant reftensq, long lcid, quantrep qr, |
sel &selcomp, gnodvalvm &nv, double &sv, vector &vv, matrix &tv); |
void store_code_num_elem(void); |
void alloc_nodes_arrays (void); |
void alloc_nodal_strains(void); |
/trunk/SIFEL/MEFEL/SRC/node.cpp |
---|
760,3 → 760,25 |
nodval = new double [ndofn]; |
memset(nodval, 0, sizeof(*nodval)*ndofn); |
} |
void node::give_transfmat(long ndofn, matrix &tmat) |
{ |
tmat[0][0]=e1[0]; |
tmat[1][0]=e1[1]; |
tmat[0][1]=e2[0]; |
tmat[1][1]=e2[1]; |
if (transf == 3){ |
tmat[0][2]=e3[0]; |
tmat[1][2]=e3[1]; |
tmat[2][0]=e1[2]; |
tmat[2][1]=e2[2]; |
tmat[2][2]=e3[2]; |
} |
else{ |
if (ndofn == 3) // 2D beam |
tmat[2][2]=1.0; |
} |
} |
/trunk/SIFEL/MEFEL/SRC/node.h |
---|
5,6 → 5,7 |
#include "alias.h" |
#include "xfile.h" |
struct vector; |
struct matrix; |
/** |
Class node: |
45,6 → 46,7 |
void clean (long nlc); |
void alloc_meaning (long nid); |
void alloc_growstr (long nid); |
void give_transfmat(long ndofn, matrix &tmat); |
/// type of cross section |
crsectype crst; |
/trunk/SIFEL/MEFEL/SRC/outdriverm.cpp |
---|
1,4 → 1,5 |
#include "outdriverm.h" |
#include "outquantm.h" |
#include "gfmatrix.h" |
#include "iotools.h" |
#include "galias.h" |
16,6 → 17,9 |
#include "elemswitch.h" |
#include "vecttens.h" |
#include "list.h" |
#include "outresfilem.h" |
#include "gnodvalvm.h" |
#include "outquantm.h" |
#include <math.h> |
50,8 → 54,8 |
vtk_num = 0; |
nlcs = 0L; |
lcs = NULL; |
ngfq = 0; |
gfq = NULL; |
nofq = 0; |
ofq = NULL; |
} |
66,7 → 70,7 |
delete [] outdiagf; |
delete [] odiag; |
delete [] lcs; |
delete [] gfq; |
delete [] ofq; |
} |
91,7 → 95,7 |
*/ |
long outdriverm::read(XFILE *in) |
{ |
long i, n; |
long i; |
const char *str; |
xfscanf(in, "%k%m", "textout", &flagsw_kwdset, &textout); |
146,14 → 150,16 |
Mp->reactcomp = 1; |
} |
if (gf == grfmt_sep_files_quant){ |
xfscanf(in, "%k%ld", "num_gr_files", &ngfq); |
if (ngfq < 1){ |
print_err("wrong number of graphic files for output (%ld), it must be positive number", __FILE__, __LINE__, __func__, ngfq); |
xfscanf(in, "%k%ld", "num_gr_files", &nofq); |
if (nofq < 0){ |
print_err("wrong number of output result files (%ld < 0)", __FILE__, __LINE__, __func__, nofq); |
abort(); |
} |
gfq = new outgrfile[ngfq]; |
//for(i=0; i<ngfq; i++) |
//gfq[i].read(in); |
if (nofq){ |
ofq = new outresfilem[nofq]; |
//for(i=0; i<nofq; i++) |
//ofq[i].read(in); |
} |
} |
else if (gf != grfmt_no){ |
if (xfscanf(in, " %a", outgrfn) != 1){ |
195,23 → 201,37 |
fprintf(stdout, "\n Filename of graphic output : %s", outgrfn); |
break; |
case grfmt_sep_files_quant: |
fprintf(stdout, "\n Graphic output will be in sparated files with selected quantities"); |
fprintf(stdout, "\n Number of files: %ld", ngfq); |
for(i=0; i<ngfq; i++){ |
switch (gfq[i].gf){ |
case grfmt_gid: |
fprintf(stdout, "\n %ld. filename of graphic output in %s format: %s", i+1, "GiD", gfq[i].outfn); |
fprintf(stdout, "\n Output will be in sparated files with selected quantities"); |
fprintf(stdout, "\n Number of files: %ld", nofq); |
for(i=0; i<nofq; i++){ |
ofq[i].read(in); |
switch (ofq[i].rffmt){ |
case resfmt_open_dx: |
fprintf(stdout, "\n %ld. filename of graphic output in %s format: %s", i+1, "OpenDX", ofq[i].outfbn); |
break; |
case grfmt_vtk: |
fprintf(stdout, "\n %ld. filename of graphic output in %s format: %s", i+1, "VTK", gfq[i].outfn); |
case resfmt_gid: |
fprintf(stdout, "\n %ld. filename of graphic output in %s format: %s", i+1, "GiD", ofq[i].outfbn); |
break; |
case resfmt_vtk: |
fprintf(stdout, "\n %ld. filename of graphic output in %s format: %s", i+1, "VTK", ofq[i].outfbn); |
break; |
case resfmt_plain_out: |
fprintf(stdout, "\n %ld. filename of graphic output in %s format: %s", i+1, "PlainOut", ofq[i].outfbn); |
break; |
case resfmt_diag_dat: |
fprintf(stdout, "\n %ld. filename of graphic output in %s format: %s", i+1, "DiagramDat", ofq[i].outfbn); |
break; |
default: |
print_err("unknown/unsupported file format (%d) is required in %ld. output file %s", |
__FILE__, __LINE__, __func__, gfq[i].gf, i+1, gfq[i].outfn); |
__FILE__, __LINE__, __func__, ofq[i].rffmt, i+1, ofq[i].outfbn); |
abort(); |
} |
} |
break; |
default: |
print_err("unknown/unsupported file format (%d) is required", |
__FILE__, __LINE__, __func__, gf); |
abort(); |
} |
if ((gf != grfmt_no) && (gf != grfmt_sep_files_quant)) |
283,21 → 303,10 |
print_err("wrong number of local coordinate systems", __FILE__, __LINE__, __func__); |
return 9; |
} |
lcs = new gfmatrix[nlcs]; |
lcs = new lcoordsys[nlcs]; |
for (i=0; i<nlcs; i++) |
{ |
xfscanf(in, "%k%ld", "ncomp", &n); |
if ((n < 2) || (n > 3)) |
{ |
print_err("wrong number of base vector component %ld.\nIt must be either 2 or 3", __FILE__, __LINE__, __func__); |
return 9; |
} |
// create identity matrix (3,3) |
allocim(3, lcs[i]); |
lcs[i].m = lcs[i].n = n; |
readm(in, lcs[i]); |
lcs[i].m = lcs[i].n = 3; |
lcs[i].read(in); |
} |
} |
return 0; |
328,6 → 337,13 |
fprintf(out, "%d\n", (int)gf); |
if (gf != grfmt_no) |
{ |
if (gf == grfmt_sep_files_quant){ |
fprintf(out, "%ld", nofq); |
if (nofq){ |
for(i=0; i<nofq; i++) |
ofq[i].print(out); |
} |
} |
fprintf(out, "%s\n", outgrfn); |
nog.print(out); |
eog.print(out); |
358,8 → 374,8 |
fprintf(out, "%ld # number of local coordinate systems defined", nlcs); |
for (i=0; i<nlcs; i++) |
{ |
fprintf(out, "\n# Transformation matrix of %ld. lcs\n%ld # number of nonzero components\n", i+1, 3L); |
printm(out, lcs[i]); |
fprintf(out, "\n# Transformation matrix of %ld. lcs\n", i+1); |
lcs[i].print(out); |
} |
} |
} |
383,13 → 399,6 |
fprintf(out, "%15s * * * * *\n", " "); |
fprintf(out, "%15s**** * * **** **** MEFEL OUTPUT\n", " "); |
/* |
long i; |
for (i=0; i<72; i++) |
fprintf(out, "*"); |
fprintf(out, "\n\n*%15s SIFEL - MEFEL OUTPUT %15s*\n\n", " ", " "); |
for (i=0; i<72; i++) |
fprintf(out, "*");*/ |
fprintf(out, "\n%s\n", Mp->name); |
fprintf(out, "\n\n\n\n\n"); |
} |
655,8 → 664,8 |
sprintf(dlcid, "%.15e", lambda/3600.0); |
if(Mp->tpr == days) |
sprintf(dlcid, "%.15e", lambda/86400.0); |
print_default_vtk(vtk_file, lcid, istep, (double) atof(dlcid));//print header,points,nodes,elements |
write_vtk_unkn(vtk_file, lcid, dlcid);//print datapoints in sections |
print_vtk_header(vtk_file, istep, (double) atof(dlcid));//print header,points,nodes,elements |
write_vtk_unkn(vtk_file, lcid);//print datapoints in sections |
fclose(vtk_file); |
vtk_num++; |
break; |
720,8 → 729,8 |
{ |
case mat_nonlinear_statics: |
case mech_timedependent_prob: |
print_default_vtk(vtk_file, lcid, istep, (double) atof(dlcid)); //print header,points,nodes,elements |
write_vtk_unkn(vtk_file, lcid, dlcid); //print datapoints in sections |
print_vtk_header(vtk_file, istep, (double) atof(dlcid)); //print header,points,nodes,elements |
write_vtk_unkn(vtk_file, lcid); //print datapoints in sections |
fclose(vtk_file); |
vtk_num++; |
break; |
785,8 → 794,8 |
{ |
case mat_nonlinear_statics: |
case mech_timedependent_prob: |
print_default_vtk(vtk_file, lcid, istep, (double) atof(dlcid));//print header,points,nodes,elements |
write_vtk_unkn(vtk_file, lcid, dlcid);//print datapoints in sections |
print_vtk_header(vtk_file, istep, (double) atof(dlcid));//print header,points,nodes,elements |
write_vtk_unkn(vtk_file, lcid);//print datapoints in sections |
fclose(vtk_file); |
vtk_num++; |
break; |
798,6 → 807,9 |
} |
break; |
} |
case grfmt_sep_files_quant: |
print_sep_files_quant(lcid, lambda, istep, Lsrs->give_lhs(lcid), NULL, fi, NULL); |
break; |
default: |
print_err("unknown type of graphics format is required", __FILE__, __LINE__, __func__); |
} |
914,8 → 926,8 |
{ |
case mat_nonlinear_statics: |
case mech_timedependent_prob: |
print_default_vtk(vtk_file, lcid, istep, (double) atof(dlcid));//print header,points,nodes,elements |
write_vtk_unkn(vtk_file, lcid, dlcid);//print datapoints in sections |
print_vtk_header(vtk_file, istep, (double) atof(dlcid));//print header,points,nodes,elements |
write_vtk_unkn(vtk_file, lcid);//print datapoints in sections |
fclose(vtk_file); |
vtk_num++; |
break; |
978,8 → 990,8 |
{ |
case mat_nonlinear_statics: |
case mech_timedependent_prob: |
print_default_vtk(vtk_file, lcid, istep, (double) atof(dlcid));//print header,points,nodes,elements |
write_vtk_unkn(vtk_file, lcid, dlcid);//print datapoints in sections |
print_vtk_header(vtk_file, istep, (double) atof(dlcid));//print header,points,nodes,elements |
write_vtk_unkn(vtk_file, lcid);//print datapoints in sections |
fclose(vtk_file); |
vtk_num++; |
break; |
1043,8 → 1055,8 |
{ |
case mat_nonlinear_statics: |
case mech_timedependent_prob: |
print_default_vtk(vtk_file, lcid, istep, (double) atof(dlcid));//print header,points,nodes,elements |
write_vtk_unkn(vtk_file, lcid, dlcid);//print datapoints in sections |
print_vtk_header(vtk_file, istep, (double) atof(dlcid));//print header,points,nodes,elements |
write_vtk_unkn(vtk_file, lcid);//print datapoints in sections |
fclose(vtk_file); |
vtk_num++; |
break; |
1127,25 → 1139,25 |
char *rp2 = new char[FILENAME_MAX]; |
char *p1 = new char[FILENAME_MAX]; |
char *p2 = new char[FILENAME_MAX]; |
ivector idl(ngfq); |
ivector idl(nofq); |
list fnlist; |
long i, j, fndiff; |
char *aux; |
char *aux = NULL; |
if (gf != grfmt_sep_files_quant){ |
print_err("wrong graphics format is required", __FILE__, __LINE__, __func__); |
abort(); |
} |
reallocv(ngfq, cf); |
reallocv(nofq, cf); |
// search for identical file names and formats of the graphic files |
for (i=0; i<ngfq; i++){ |
get_path(gfq[i].outfn, p1); |
for (i=0; i<nofq; i++){ |
get_path(ofq[i].outfbn, p1); |
if (realpath(p1, rp1) == NULL){ |
print_err("required path'%s' does not exist\n", __FILE__, __LINE__, __func__, p1); |
abort(); |
} |
// append format specifier to the path |
sprintf(p1, "%s%d", rp1, int(gfq[i].gf)); |
sprintf(p1, "%s%d", rp1, int(ofq[i].rffmt)); |
fndiff = 1; |
for(j=0; j<fnlist.count(); j++){ |
get_path((char*)fnlist.at(j), p2); |
1154,7 → 1166,7 |
abort(); |
} |
// append format specifier to the path |
sprintf(p2, "%s%d", rp2, int(gfq[i].gf)); |
sprintf(p2, "%s%d", rp2, int(ofq[i].rffmt)); |
if (strcmp(rp1, rp2) == 0){ |
fndiff = 0; // do not create new file |
cf[i] = idl[j]; // store index of file which has identical name and format |
1169,47 → 1181,27 |
fnlist.append(aux); // store path with format identfier in the list of created files |
} |
} |
for (i=0; i<ngfq; i++){ |
if (cf[i] > 0){ |
//create file, print header |
if (ftell(gfq[i].outf) == 0){ // new file -> only print header |
switch(gfq[i].gf){ |
case grfmt_gid: |
gfq[i].outf = fopen(gfq[i].outfn, mode); |
if (gfq[i].outf == NULL){ |
print_err("cannot open graphics file '%s'", __FILE__, __LINE__, __func__, gfq[i].outfn); |
abort(); |
} |
fseek(gfq[i].outf, 0, SEEK_END); // MS Visual C++ requires that |
fprintf(gfq[i].outf, "GiD Post Results File 1.0\n"); |
break; |
case grfmt_vtk: |
if (dlcid){ |
char *path; |
char *name; |
char *suffix; |
char fname[FILENAME_MAX]; |
filename_decomposition (outgrfn,path,name,suffix); |
sprintf(fname,"%s%s%04ld%s", path, name, istep, suffix); //increase index in filename |
delete [] path; delete [] name; delete [] suffix; |
gfq[i].outf = fopen(gfq[i].outfn, mode); |
if (gfq[i].outf == NULL){ |
print_err("cannot open graphics file '%s'", __FILE__, __LINE__, __func__, fname); |
abort(); |
} |
fseek(gfq[i].outf, 0, SEEK_END); // MS Visual C++ requires that |
print_default_vtk(gfq[i].outf, lcid, istep, (double) atof(dlcid)); //print header, points, nodes, elements |
} |
break; |
default: |
print_err("unknown type of file format (%d) is required in the %ld. output file '%s'.", |
__FILE__, __LINE__, __func__, int(gfq[i].gf), i+1, gfq[i].outfn); |
abort(); |
} |
for (i=0; i<nofq; i++){ |
if ((cf[i] > 0) && (ofq[i].outf == NULL)){ |
// open file |
// create file name |
long stochid = -1; |
if(St) stochid = Mp->ns+1; |
ofq[i].get_modified_fname(stochid, istep); |
ofq[i].outf = fopen(ofq[i].outfmn, mode); |
if (ofq[i].outf == NULL){ |
print_err("cannot open output file '%s'", __FILE__, __LINE__, __func__, ofq[i].outfmn); |
abort(); |
} |
fseek(ofq[i].outf, 0, SEEK_END); // MS Visual C++ requires that |
} |
// print header if the file is new |
if (ftell(ofq[i].outf) == 0){ |
// new file -> only print header |
ofq[i].print_header(istep, Mp->time); |
} |
else |
gfq[i].outf = gfq[-(cf[i]+1)].outf; |
ofq[i].outf = ofq[-(cf[i]+1)].outf; |
} |
// release memory of the list of file names |
for (i=0; i<fnlist.count(); i++){ |
1219,6 → 1211,7 |
delete [] rp2; |
delete [] p1; |
delete [] p2; |
delete [] aux; |
} |
1316,9 → 1309,9 |
return 1; |
} |
} |
for(i=0; i<ngfq; i++){ |
for(j=0; j<gfq[i].nqnt; j++){ |
if (gfq[i].qnt[j].lcs){ |
for(i=0; i<nofq; i++){ |
for(j=0; j<ofq[i].nqnt; j++){ |
if (ofq[i].qnt[j].lcs){ |
return 1; |
} |
} |
1823,7 → 1816,6 |
{ |
long i, j, ncomp, id, ir; |
vector aux; |
const char *namevar[] = {"x", "y", "z"}; |
matrix t; |
vector str, p; |
1848,7 → 1840,7 |
str.n = ncomp; |
str.a = Mt->nodes[i].strain+id; |
Mt->give_nodal_coord(i, p); |
Outdm->lcs[transtra[ir]-1].evaluate_t(p, namevar, t); |
Outdm->lcs[transtra[ir]-1].give_transfmat(t, p, Mp->time); |
if (ncomp == 4) |
gl_engvectortransf(str, aux, t, planestrain, strain); |
if (ncomp == 6) |
1918,7 → 1910,6 |
{ |
long i, ir, j, ncomp, id; |
vector aux; |
const char *namevar[] = {"x", "y", "z"}; |
matrix t; |
vector str, p; |
1943,7 → 1934,7 |
str.n = ncomp; |
str.a = Mt->nodes[i].strain+id; |
Mt->give_nodal_coord(i, p); |
Outdm->lcs[transtre[ir]-1].evaluate_t(p, namevar, t); |
Outdm->lcs[transtre[ir]-1].give_transfmat(t, p, Mp->time); |
if (ncomp == 4) |
gl_engvectortransf(str, aux, t, planestrain, stress); |
if (ncomp == 6) |
3957,7 → 3948,6 |
{ |
long i, j, k, ncomp, id, ipp, tnipe, ir; |
vector aux; |
const char *namevar[] = {"x", "y", "z"}; |
matrix t; |
vector str, p; |
3986,7 → 3976,7 |
str.n = ncomp; |
str.a = Mm->ip[ipp+j].strain+id; |
ipcoord(Mm->elip[ipp+j], ipp+j, 0, 0, p); |
Outdm->lcs[transtra[ir]-1].evaluate_t(p, namevar, t); |
Outdm->lcs[transtra[ir]-1].give_transfmat(t, p, Mp->time); |
gl_engvectortransf(str, aux, t, planestrain, strain); |
str.a = NULL; |
} |
4025,7 → 4015,6 |
{ |
long i, j, k, ncomp, ipp, tnipe, id, ir; |
vector aux; |
const char *namevar[] = {"x", "y", "z"}; |
matrix t; |
vector str, p; |
4057,7 → 4046,7 |
str.n = ncomp; |
str.a = Mm->ip[ipp+j].stress+id; |
ipcoord(Mm->elip[ipp+j], ipp+j, 0, 0, p); |
Outdm->lcs[transtre[ir]-1].evaluate_t(p, namevar, t); |
Outdm->lcs[transtre[ir]-1].give_transfmat(t, p, Mp->time); |
gl_engvectortransf(str, aux, t, planestrain, strain); |
str.a = NULL; |
} |
5922,447 → 5911,51 |
double **outquantm::qvv = NULL; |
double *outquantm::qvs = NULL; |
long outquantm::maxnpnt = 0; |
long outquantm::maxncmp = 0; |
outquantm::outquantm() |
{ |
mqn = nomech_q; |
qlabel[0] = '\0'; |
tpnt = atnode; |
nudp = 0; |
ksi = eta = zeta = NULL; |
qt = qf = scalq; |
qstf = no; |
lcs = 0; |
outfname = NULL; |
outf = NULL; |
ide1 = 0; |
} |
outquantm::~outquantm() |
{ |
delete [] ksi; |
delete [] eta; |
delete [] zeta; |
} |
/** |
The function reads description of printed quantity to the file for the graphic postprocessor. |
@param in[in] - pointer to the opened input file |
The function prints required quantities to the separated files. |
@retval 0 - on success |
@retval 1 - in the case of reading error |
Created by Tomas Koudelka, 07.2021 |
*/ |
long outquantm::read(XFILE *in) |
{ |
long i, n; |
@param[in] lcid - required load case id |
@param[in] time - actual time or load parameter |
@param[in] istep - actual step id |
@param[in] r - array of the nodal values |
@param[in] fl - array with values of the load vector |
@param[in] fi - array with values of the internal force vector (it should be almost identical with fl) |
@param[in] fr - array with values of the residual vector (fl-fi) |
// read name id of required quantity |
xfscanf(in, "%k%m","qname", &mechquant_kwdset, &mqn); |
@return The function does not return anything, but modifies the content of the output files. |
// read string with label of required quantity, use "@" for automatic label |
xfscanf(in, "%k%255s", "qlabel", qlabel); |
// read type of points where quantity values willl be printed out |
xfscanf(in, "%k%m", "pnt_type", &nodip_kwdset, &tpnt); |
// read selection of node/elem numbers where the quantity will be printed out |
xfscanf(in, "%k", "pnt_sel"); |
selid.read(in); |
switch (tpnt){ |
case atnode: // no additional data are necessary in the case of nodes |
n = Mt->nn; |
break; |
case atip: // read selection of integration points on selected elements (local ordering numbers) |
n = Mm->tnip; |
seleip.read(in); |
break; |
case atxyz: // read set of user defined points (UDP) for selected elements |
xfscanf(in, "%k%ld", "num_udp", &nudp); // number of UDPs |
ksi = new double[nudp]; |
eta = new double[nudp]; |
zeta = new double[nudp]; |
for(i=0; i<nudp; i++){ // reading of natrual coordinates of UDPs |
xfscanf(in, "%le %le", ksi+i, eta+i); |
if (Mp->dim == 3) |
xfscanf(in, "%le", zeta+i); |
else |
zeta[i] = 0.0; |
} |
n = Mt->ne*nudp; |
break; |
default: |
print_err("unknown type of point is required (%d)", __FILE__, __LINE__, __func__, int(tpnt)); |
abort(); |
} |
// set the first dimension of auxiliary arrays qvs and qvv |
if (n > maxnpnt) maxnpnt = n; |
// read quatity format in which will be printed out (scalar/vector/tensor) |
xfscanf(in, "%k%m", "quant_out_fmt", &quantchar_kwdset, &qf); |
// get quantity type and its number of components according to mechmat and number of quantity components |
//qt = Mm->give_quant_type(mqn, n); |
switch(qt){ |
case scalq: |
break; |
case vectq: |
case tensq: // read component selection for vector and tensor types of quantities |
seliq.read(in); |
break; |
default: |
print_err("unknown type of quantity (%d) is required", __FILE__, __LINE__, __func__, int(qt)); |
abort(); |
} |
// set the second dimension of auxiliary array qvv |
if (n > maxncmp) maxncmp = n; |
// function for scaling/tranformation of the quantity (constant function means the scaling factor, pars |
xfscanf(in, "%k%m", "scaling", answertype_kwdset, &qstf); |
if (qstf == yes) |
qst.read(in); // read scaling function, const type of function means scaling factor, parser is used for the complex transformations |
// read id of transformation for vector or tensor quantity type |
switch(qt){ |
case scalq: |
break; |
case vectq: |
case tensq: // read id of local coordinate system (LCS) |
xfscanf(in, "%k%ld", "lcs", &lcs); |
break; |
default: |
print_err("unknown type of quantity (%d) is required", __FILE__, __LINE__, __func__, int(qt)); |
abort(); |
} |
return 0; |
} |
/** |
The function prints description of printed quantity to the text file. |
@param out[in] - pointer to the opened output file |
@return The function does not return anything. |
Created by Tomas Koudelka, 07.2021 |
Created by Tomas Koudelka |
*/ |
void outquantm::print(FILE *out) |
void outdriverm::print_sep_files_quant(long lcid, double time, long istep, double *r, double *fl, double *fi, double *fr) |
{ |
long i; |
gnodvalvm gnv(r, fl, fi, fr); |
// print name id of required quantity |
fprintf(out, "%d ", int(mqn)); |
// print string with label of required quantity |
fprintf(out, "%s ", qlabel); |
// print type of points where quantity values willl be printed out |
fprintf(out, "%d ", int(tpnt)); |
// print selection of node/elem numbers where the quantity will be printed out |
selid.print(out); |
switch (tpnt){ |
case atnode: // no additional data are necessary in the case of nodes |
break; |
case atip: // read selection of integration points on selected elements (local ordering numbers) |
seleip.print(out); |
break; |
case atxyz: // read set of user defined points (UDP) for selected elements |
fprintf(out, "%ld\n", nudp); // number of UDPs |
for(i=0; i<nudp; i++){ // reading of natrual coordinates of UDPs |
fprintf(out, "%le %le", ksi[i], eta[i]); |
if (Mp->dim == 3) |
fprintf(out, " %le", zeta[i]); |
fprintf(out, "\n"); |
} |
break; |
default: |
print_err("unknown type of point is required (%d)", __FILE__, __LINE__, __func__, int(tpnt)); |
abort(); |
for (i=0; i<nofq; i++){ // loop over all files |
ofq[i].print_quants(lcid, time, istep, lcs, gnv, idn1, ide1); |
} |
} |
// print quatity format in which will be printed out (scalar/vector/tensor) |
fprintf(out, "%d ", int(qf)); |
switch(qt){ |
case scalq: |
break; |
case vectq: |
case tensq: // print component selection for vector and tensor types of quantities |
seliq.print(out); |
break; |
default: |
print_err("unknown type of quantity (%d) is required", __FILE__, __LINE__, __func__, int(qt)); |
abort(); |
} |
// function for scaling/tranformation of the quantity (constant function means the scaling factor, pars |
fprintf(out, "%d ", int(qstf)); |
if (qstf == yes) |
qst.print(out); // print scaling function, const type of function means scaling factor, parser is used for the complex transformations |
// print id of transformation for vector or tensor quantity type |
switch(qt){ |
case scalq: |
break; |
case vectq: |
case tensq: // read id of local coordinate system (LCS) |
fprintf(out, "%ld", lcs); |
break; |
default: |
print_err("unknown type of quantity (%d) is required", __FILE__, __LINE__, __func__, int(qt)); |
abort(); |
} |
fprintf(out, "\n"); |
} |
/** |
The function prints header, points and used elements to the VTK file |
The function prints header for the plain text output file format. |
@param fname - pointer to the opened VTK file |
@param lcid - load case id |
@param istep - integration step |
@param lambda - actual time in either s,h,days |
@param[in,out] out - pointer to the opened text file. |
@return The function does not return anything. |
@return The function does not return anything, but changes the content of the file out. |
Created by Vit Smilauer |
Created by Tomas Koudelka, 10.2023 |
*/ |
void outdriverm::print_default_vtk(FILE *fname, long /*lcid*/, long istep, double lambda){ |
long int i,j,nn; |
int tr[20]; |
fprintf(fname, "# vtk DataFile Version 1.0\n"); |
fprintf(fname, "Time step %ld time %lf\n",istep,lambda); |
fprintf(fname, "ASCII\n\n"); |
fprintf(fname, "DATASET UNSTRUCTURED_GRID\n"); |
fprintf(fname, "POINTS %ld float\n", Mt->nn); |
for (i=0; i<Mt->nn; i++){ |
fprintf(fname, "%e %e %e\n", Gtm->gnodes[i].x, Gtm->gnodes[i].y, Gtm->gnodes[i].z); |
} |
void outdriverm::print_header_plain_out(FILE *out) |
{ |
fprintf(out, "%15s **** * **** **** *\n", " "); |
fprintf(out, "%15s * * * * *\n", " "); |
fprintf(out, "%15s * * *** *** *\n", " "); |
fprintf(out, "%15s * * * * *\n", " "); |
fprintf(out, "%15s**** * * **** **** MEFEL OUTPUT\n", " "); |
long int ncells = 0; |
for (i=0; i < Mt->ne; i++){ |
ncells += Mt->give_nne (i); |
} |
fprintf(fname, "\nCELLS %ld %ld\n", Mt->ne, ncells+Mt->ne); |
for (i=0; i < Mt->ne; i++){ |
fprintf(fname, "%ld ", Mt->give_nne(i));//number of nodes on element |
for(j=0;j<Mt->give_nne(i);j++){ |
switch(Mt->elements[i].te){//for nodes renumbering |
case linearhex: |
tr[0] = 6; tr[1] = 7; tr[2] = 4; tr[3] = 5;//xy, z=0, xi=x,nu=y, theta=z |
tr[4] = 2; tr[5] = 3; tr[6] = 0; tr[7] = 1;//xy, z<>0 |
nn=tr[j]; |
break; |
case quadrhex: |
tr[0] = 6; tr[1] = 7; tr[2] = 4; tr[3] = 5;//xy, z=0, xi=x,nu=y, theta=z |
tr[4] = 2; tr[5] = 3; tr[6] = 0; tr[7] = 1; |
tr[8] = 18; tr[9] = 19; tr[10] = 16; tr[11] = 17; |
tr[12] = 10; tr[13] = 11; tr[14] = 8; tr[15] = 9; |
tr[16] = 14; tr[17] = 15; tr[18] = 12; tr[19] = 13; |
nn=tr[j]; |
break; |
default: |
nn=j; |
break; |
} |
fprintf(fname, "%ld ", Gtm->gelements[i].nodes[nn]); |
} |
fprintf(fname, "\n"); |
} |
//output cell types |
fprintf(fname, "\nCELL_TYPES %ld\n", Mt->ne); |
for (i=0; i < Mt->ne; i++){ |
switch(Mt->elements[i].te){ |
case bar2d: |
case beam2d: |
case bar3d: |
case beam3d: |
fprintf(fname, "3\n");//VTK_LINE |
break; |
case barq2d: |
case barq3d: |
fprintf(fname, "21\n");//VTK_QUADRATIC_EDGE |
break; |
case planeelementlt: |
case axisymmlt: |
fprintf(fname, "5\n");//VTK_TRIANGLE |
break; |
case planeelementlq: |
case axisymmlq: |
fprintf(fname, "9\n");//VTK_QUAD |
break; |
case planeelementqq: |
case axisymmqq: |
fprintf(fname, "23\n");//VTK_QUADRATIC_QUAD |
break; |
case lineartet: |
fprintf(fname, "10\n");//VTK_TETRA |
break; |
case linearhex: |
fprintf(fname, "12\n");//VTK_HEXAHEDRON - Renumbered nodes |
break; |
case quadrhex: |
fprintf(fname, "25\n");//VTK_QUADRATIC_HEXAHEDRON - Renumbered nodes |
break; |
default: |
print_err("unknown element type in VTK export", __FILE__, __LINE__, __func__); |
abort(); |
break; |
} |
} |
fprintf(out, "\n%s\n", Mp->name); |
fprintf(out, "\n\n\n\n\n"); |
} |
/** |
The function prints data to the VTK file. |
@param fname - pointer to the opened VTK file |
@param lcid - load case id |
@param desclcid - load case description |
@return The function does not return anything. |
Created by Vit Smilauer |
*/ |
//VTK can not handle integration points directly, results in nodes only |
void outdriverm::write_vtk_unkn(FILE *fname, long lcid, const char */*desclcid*/){ |
vector r; |
long i, j, k, ncomp, max_ncomp; |
fprintf(fname, "\nPOINT_DATA %ld\n", Mt->nn); |
//displacements at nodes |
if (nog.selndisp.st != sel_no){ |
fprintf(fname, "VECTORS Nodal_displacements float\n"); |
reallocv(RSTCKVEC(3, r)); |
for (i=0; i<Mt->nn; i++){ |
r[0]=r[1]=r[2]=0; |
noddispl (lcid, r.a, i); |
fprintf(fname, "%e %e %e\n", r[0], r[1], r[2]); |
} |
fprintf(fname, "\n"); |
} |
// strains at nodes |
if (nog.selnstra.st != sel_no){ |
fprintf(fname, "TENSORS Strain float\n"); |
for (i=0; i<Mt->nn; i++){ |
ncomp = Mt->nodes[i].ncompstr; |
vector eps(ASTCKVEC(4)); |
matrix epst(ASTCKMAT(3,3)); |
nullv(eps); |
nullm(epst); |
for (j=0; j<ncomp; j++) |
eps[j] = Mt->nodes[i].strain[j]; |
switch (ncomp){ |
case 1:{ |
vector_tensor (eps, epst, bar, strain); |
break; |
} |
case 4:{ |
vector_tensor (eps, epst, planestrain, strain);//or planestress |
break; |
} |
case 6:{ |
vector_tensor (eps, epst, spacestress, strain); |
} |
} |
for (k=0; k<3; k++){ |
fprintf(fname, "%e %e %e\n", epst[k][0], epst[k][1], epst[k][2]); |
} |
fprintf(fname, "\n"); |
} |
} |
// stresses at nodes |
if (nog.selnstre.st != sel_no){ |
fprintf(fname, "TENSORS Stress float\n"); |
for (i=0; i<Mt->nn; i++){ |
ncomp = Mt->nodes[i].ncompstr; |
vector sig(ASTCKVEC(4)); |
matrix sigt(ASTCKMAT(3,3)); |
nullv(sig); |
nullm(sigt); |
for (j=0; j<ncomp; j++) |
sig[j] = Mt->nodes[i].stress[j]; |
switch (ncomp){ |
case 1:{ |
vector_tensor (sig, sigt, bar, stress); |
break; |
} |
case 4:{ |
vector_tensor (sig, sigt, planestrain, stress);//or planestress |
break; |
} |
case 6:{ |
vector_tensor (sig, sigt, spacestress, stress); |
} |
} |
for (k=0; k<3; k++){ |
fprintf(fname, "%e %e %e\n", sigt[k][0], sigt[k][1], sigt[k][2]); |
} |
fprintf(fname, "\n"); |
} |
} |
// other values at nodes |
if (nog.selnoth.st != sel_no){ |
max_ncomp = 0; |
for (k=0; k<Mm->tnip; k++){//find maximum eqother components |
max_ncomp > Mm->ip[k].ncompother ? max_ncomp = Mm->ip[k].ncompother : 0; |
} |
for(i=0; i<max_ncomp; i++){// other[i] |
for (j=0; j<Outdm->nog.selnoth.n; j++){ |
if (Outdm->nog.seloth[j].presence_id(i)){ |
fprintf(fname, "\nSCALARS Eq_other_s%ld_%ld double\nLOOKUP_TABLE default\n", j+1, i+1); |
for (k=0; k < Mt->nn; k++) |
fprintf(fname, "%e\n", Mt->nodes[k].giveother(i)); |
} |
} |
} |
/* fprintf(fname, "TENSORS Other float\n"); |
for (i=0; i<Mt->nn; i++){ |
ncomp = Mt->nodes[i].ncompother; |
vector oth(ASTCKVEC(4)); |
matrix otht(ASTCKMAT(3,3)); |
nullv(oth); |
nullm(otht); |
for (j=0; j<ncomp; j++) |
oth[j] = Mt->nodes[i].other[j]; |
switch (ncomp){ |
case 1:{ |
vector_tensor (oth, otht, bar, stress); |
break; |
} |
case 4:{ |
vector_tensor (oth, otht, planestrain, stress);//or planestress |
break; |
} |
case 6:{ |
vector_tensor (oth, otht, spacestress, stress); |
} |
} |
for (k=0; k<3; k++){ |
fprintf(fname, "%e %e %e\n", otht[k][0], otht[k][1], otht[k][2]); |
} |
fprintf(fname, "\n"); |
}*/ |
} |
// reactions - not implemented |
} |
/trunk/SIFEL/MEFEL/SRC/outdriverm.h |
---|
1,14 → 1,17 |
#ifndef OUTDRIVERM_H |
#define OUTDRIVERM_H |
#include <stdio.h> |
#include "galias.h" |
#include "selection.h" |
#include "xfile.h" |
#include "alias.h" |
#include "outdiagm.h" |
#include "outresfilem.h" |
#include "siftop.h" |
#include "lcoordsys.h" |
#include <stdio.h> |
#ifndef FNAMELEN |
#define FNAMELEN 1001 |
#endif |
21,6 → 24,7 |
//class outdriverm; |
struct matrix; |
struct gfmatrix; |
class outquantm; |
class nodeoutm |
387,99 → 391,6 |
class outquantm |
{ |
public: |
/// constructor |
outquantm(); |
/// destructor |
~outquantm(); |
/// reads data from file |
long read(XFILE *in); |
/// prints description data to file |
void print(FILE *out); |
/// converts selections given by property id to list or range type |
void conv_sel_prop(siftop *top); |
/// prints values for selected items to grahics file |
void print_graphics(FILE *out, long lcid, const char *desclcid, graphfmt gf, long idelem1); |
/// name of the required mechanical quantity |
mechquant mqn; |
/// quantity label (if '@' is the first character then automatic label will be generated) |
char qlabel[256]; |
/// type of point where the quantity is to be printed out (node/elem ipp/elem UDP) |
nodip tpnt; |
/// selection nodal/element ids where the quantity will be printed out |
sel selid; |
/// selected integration points element |
sel seleip; |
/// number of user defined points on selected elements |
long nudp; |
/// natural coordinates of selected user defined points |
double *ksi, *eta, *zeta; |
/// output format of the given quantity (scalar/vector/tensor2d) |
quantchar qf; |
/// indeces of selected quantity components (displacement comps, strain/stres comps, ...) |
sel seliq; |
/// quantity scaling/tranformation flag |
answertype qstf; |
/// function for scaling/tranformation of the quantity |
gfunct qst; |
/// local coordinate system for vector and tensor2d quantities |
long lcs; |
// auxiliary members not read in the quantity record, read/handled in outdriverm |
/// type of the given quantity (scalar/vector/tensor2d) determined in mechmat |
quantchar qt; |
/// pointer to the output file name string |
char *outfname; |
/// pointer to the associated output file of the given quantity |
FILE *outf; |
/// index shift of the first element |
long ide1; |
/** Auxiliary array of quantity values, qvv[i] represents pointer to array of the given vector/tensor2d quantity components |
at i-th node/element ip/element UDP. In the case of elements ip or UDP, qvv[i][k*ncomp+j] is the value of j-th selected |
quantity component at k-th element ip or UDP and ncomp is the maximum number of vector/tensor2d components. |
*/ |
static double **qvv; |
/** Auxiliary array of quantity values, qvv[i] represents value of the selected quantity cpomponent |
at i-th node/element ip/element UDP in the case of scalar output format */ |
static double *qvs; |
/// maximum number of points where the quantities will be printed out, it is the first dimension of arrays qvv and qvs |
static long maxnpnt; |
/// maximum number of components of quantities that will be printed out, it is the second dimension of array qvv |
static long maxncmp; |
}; |
class outgrfile |
{ |
public: |
/// reads data from file |
long read(XFILE *in); |
/// prints description data to file |
void print(FILE *out); |
/// output file name |
char outfn[1025]; |
/// format of the given output graphic file |
graphfmt gf; |
/// selection of steps which the quantities will be printed in |
sel selstep; |
/// selection of load cases which the quantities will be printed in |
sel sellc; |
/// number of quantities to be printed out |
long nqnt; |
/// array of records with quantity output desprition |
outquantm *qnt; |
/// pointer to the associated output file of the given quantity |
FILE *outf; |
}; |
class outdriverm |
{ |
public : |
511,12 → 422,11 |
void create_files_gidsp(const char *mode); |
/// creates output graphics files and their headers for general quantity output (grfmt_quant) |
void create_files_quant(const char *mode, long lcid, long istep, const char *dlcid); |
/// prints result files for the given load case and (time) step |
void print_sep_files_quant(long lcid, double time, long istep, double *r, double *fl, double *fi, double *fr); |
/// prints header to the result file in plain text output format |
void print_header_plain_out(FILE *out); |
/// prints header, points and used elements to the VTK file |
void print_default_vtk(FILE *fname, long lcid, long istep, double lambda); |
///prints data to the VTK file |
void write_vtk_unkn(FILE *fname, long lcid, const char *desclcid); |
/// tests the output setting whether it requires some local coordinate system |
long testlcs(); |
/// converts selections given by property id to list or range type |
560,7 → 470,7 |
rows of the matrix contains base vectors of the given lcs in the global |
coordinate system {e'} = [T]*{e} = lcs[i]*{e} |
*/ |
gfmatrix *lcs; |
lcoordsys *lcs; |
/// format of grahics file - 0 - none, 1 - openDX, 2 - FemCAD, 3 - GiD |
graphfmt gf; |
578,13 → 488,13 |
///number of file sequence in VTK graphic output |
long vtk_num; |
/// number of files for grahic output of given quantities |
long ngfq; |
/// array of file and quantity description for graphic otuptu in the case gf == grfmt_quant |
outgrfile *gfq; |
/// number of output files with given quantities |
long nofq; |
/// array of file and quantity description for result output in the case gf == grfmt_quant |
outresfilem *ofq; |
/** |
array of indicators for creation of graphic file with quantities: cf[i] = 1 -> create i-th file, cf[i] = j < 0 -> i-th file is the same as -(j+1)-th, |
dimension of cf is ngfq. |
array of indicators for creation of output file with quantities: cf[i] = 1 -> create i-th file, cf[i] = j < 0 -> i-th file is the same as -(j+1)-th, |
dimension of cf is nofq. |
*/ |
ivector cf; |
}; |
/trunk/SIFEL/MEFEL/SRC/outquantm.cpp |
---|
0,0 → 1,1023 |
#include "outquantm.h" |
#include "global.h" |
#include "mechmat.h" |
#include "mechtop.h" |
#include "probdesc.h" |
#include "elemswitch.h" |
#include "node.h" |
#include "element.h" |
#include "vector.h" |
#include "matrix.h" |
#include "vecttens.h" |
#include "tensorcname.h" |
#include "vectorcnamem.h" |
#include "alias.h" |
#include "galias.h" |
#include "lcoordsys.h" |
#include <stdio.h> |
#include <stdlib.h> |
double **outquantm::qvv = NULL; |
double *outquantm::qvs = NULL; |
long outquantm::maxnpnt = 0; |
long outquantm::maxncmp = 0; |
const char *outquantm::namepar[] = {"x", "y", "z", "t", "q"}; |
// setup of the Jacobi method for the determination of principal tensor values |
long outquantm::ni_jac=30; |
double outquantm::err_jac=1.0e-10; |
double outquantm::zero=1.0e-15;; |
outquantm::outquantm() |
{ |
mqn = nomech_q; |
reftensq = nomech_q; |
qlabel[0] = '\0'; |
tpnt = atnode; |
tnpnt = 0; |
nudp = 0; |
ksi = eta = zeta = NULL; |
qr = qrf = scalq; |
qstf = no; |
lcs = 0; |
ncmp = ncmpr = 0; |
outfname = NULL; |
outf = NULL; |
ide1 = 0; |
} |
outquantm::~outquantm() |
{ |
delete [] ksi; |
delete [] eta; |
delete [] zeta; |
} |
/** |
The function reads description of printed quantity to the file for the graphic postprocessor. |
@param in[in] - pointer to the opened input file |
@retval 0 - on success |
@retval 1 - in the case of reading error |
Created by Tomas Koudelka, 07.2021 |
*/ |
long outquantm::read(XFILE *in) |
{ |
long i, n; |
// read name id of required quantity |
xfscanf(in, "%k%m","qname", &mechquant_kwdset, &mqn); |
switch(mqn){ |
case first_inv: |
case second_inv: |
case third_inv: |
case tensor_norm: |
case tensdeviator: |
xfscanf(in, "%k%m","reftens_qname", &mechquant_kwdset, &reftensq); |
if ((reftensq == other_q) || (reftensq == nonmech_q)){ |
xfscanf(in, "%k%m","reftens_strastre", &mechquant_kwdset, &other_tens_strastre); |
} |
break; |
default: |
break; |
} |
// read string with label of required quantity, use "@" for automatic label |
xfscanf(in, "%k%255s", "qlabel", qlabel); |
if (qlabel[0] == '@') defqlabel = true; |
// read type of points where quantity values willl be printed out |
xfscanf(in, "%k%m", "pnt_type", &nodip_kwdset, &tpnt); |
// read selection of node/elem numbers where the quantity will be printed out |
xfscanf(in, "%k", "pnt_sel"); |
selid.read(in); |
switch (tpnt){ |
case atnode: // no additional data are necessary in the case of nodes |
tnpnt = n = Mt->nn; |
break; |
case atip: // read selection of integration points on selected elements (local ordering numbers) |
tnpnt = n = Mm->tnip; |
seleip.read(in); |
break; |
case atxyz: // read set of user defined points (UDP) for selected elements |
xfscanf(in, "%k%ld", "num_udp", &nudp); // number of UDPs |
ksi = new double[nudp]; |
eta = new double[nudp]; |
zeta = new double[nudp]; |
for(i=0; i<nudp; i++){ // reading of natrual coordinates of UDPs |
xfscanf(in, "%le %le", ksi+i, eta+i); |
if (Mp->dim == 3) |
xfscanf(in, "%le", zeta+i); |
else |
zeta[i] = 0.0; |
} |
tnpnt = n = Mt->ne*nudp; |
break; |
default: |
print_err("unknown type of point is required (%d)", __FILE__, __LINE__, __func__, int(tpnt)); |
abort(); |
} |
// set the first dimension of auxiliary arrays qvs and qvv |
if (n > maxnpnt) maxnpnt = n; |
// get quantity represenation and its number of components according to mechmat and number of quantity components |
qr = Mm->give_quant_rep(mqn, reftensq, ncmp, tsn, tti); |
ncmpr = ncmp; |
switch(qr){ |
case scalq: |
seliq.st = sel_all; |
break; |
case vectq: |
xfscanf(in, "%k", "vect_comp_sel"); |
// read component selection for vector types of quantities |
seliq.read(in); |
ncmpr = seliq.give_nselcomp(ncmp); // reduce the maximum according to the number of selected components |
// read quatity representation in which will be printed out (scalar/vector/tensor) |
xfscanf(in, "%k%m", "quant_out_rep", &quantrep_kwdset, &qrf); |
break; |
case tensq: |
xfscanf(in, "%k", "vect_comp_sel"); |
// read component selection for tensor types of quantities |
seliq.read(in); |
ncmpr = seliq.give_nselcomp(ncmp); // reduce the maximum according to the number of selected components |
// read quatity representation in which will be printed out (scalar/vector/tensor) |
xfscanf(in, "%k%m", "quant_out_rep", &quantrep_kwdset, &qrf); |
break; |
default: |
print_err("unknown type of quantity (%d) is required", __FILE__, __LINE__, __func__, int(qr)); |
abort(); |
} |
// set the second dimension of auxiliary array qvv |
if (ncmpr > maxncmp) maxncmp = ncmpr; |
// function for scaling/tranformation of the quantity (constant function means the scaling factor, pars |
xfscanf(in, "%k%m", "scaling", answertype_kwdset, &qstf); |
if (qstf == yes) |
qst.read(in); // read scaling function, const type of function means scaling factor, parser is used for other transformations |
// read id of transformation for vector or tensor quantity representation |
switch(qr){ |
case scalq: |
break; |
case vectq: |
case tensq: // read id of local coordinate system (LCS) |
xfscanf(in, "%k%ld", "lcs", &lcs); |
break; |
default: |
print_err("unknown representation of quantity (%d) is required", __FILE__, __LINE__, __func__, int(qr)); |
abort(); |
} |
return 0; |
} |
/** |
The function prints description of printed quantity to the text file. |
@param out[in] - pointer to the opened output file |
@return The function does not return anything. |
Created by Tomas Koudelka, 07.2021 |
*/ |
void outquantm::print(FILE *out) |
{ |
long i; |
// print name id of required quantity |
fprintf(out, "%d ", int(mqn)); |
// print string with label of required quantity |
fprintf(out, "%s ", qlabel); |
// print type of points where quantity values willl be printed out |
fprintf(out, "%d ", int(tpnt)); |
// print selection of node/elem numbers where the quantity will be printed out |
selid.print(out); |
switch (tpnt){ |
case atnode: // no additional data are necessary in the case of nodes |
break; |
case atip: // read selection of integration points on selected elements (local ordering numbers) |
seleip.print(out); |
break; |
case atxyz: // read set of user defined points (UDP) for selected elements |
fprintf(out, "%ld\n", nudp); // number of UDPs |
for(i=0; i<nudp; i++){ // reading of natrual coordinates of UDPs |
fprintf(out, "%le %le", ksi[i], eta[i]); |
if (Mp->dim == 3) |
fprintf(out, " %le", zeta[i]); |
fprintf(out, "\n"); |
} |
break; |
default: |
print_err("unknown type of point is required (%d)", __FILE__, __LINE__, __func__, int(tpnt)); |
abort(); |
} |
// print quatity format in which will be printed out (scalar/vector/tensor) |
fprintf(out, "%d ", int(qrf)); |
switch(qr){ |
case scalq: |
break; |
case vectq: |
case tensq: // print component selection for vector and tensor types of quantities |
seliq.print(out); |
break; |
default: |
print_err("unknown type of quantity (%d) is required", __FILE__, __LINE__, __func__, int(qr)); |
abort(); |
} |
// function for scaling/tranformation of the quantity (constant function means the scaling factor, pars |
fprintf(out, "%d ", int(qstf)); |
if (qstf == yes) |
qst.print(out); // print scaling function, const type of function means scaling factor, parser is used for the complex transformations |
// print id of transformation for vector or tensor quantity represenation |
switch(qr){ |
case scalq: |
break; |
case vectq: |
case tensq: // read id of local coordinate system (LCS) |
fprintf(out, "%ld", lcs); |
break; |
default: |
print_err("unknown type of quantity (%d) is required", __FILE__, __LINE__, __func__, int(qr)); |
abort(); |
} |
fprintf(out, "\n"); |
} |
/** |
The function converts selection of points with the required quantity output to the regular selection |
in the cases where the selction is given by the property number. It is used in preprocessor especially. |
@param[in] top - pointer to the general topology of the problem solved |
@return The function does not return anything but it changes the selid data members. |
Created by TKO, 09.2023 |
*/ |
void outquantm::conv_sel_prop(siftop *top) |
{ |
if (selid.st == sel_prop){ |
if (tpnt == atnode) |
selid.conv_selprop(top, gnod); |
else |
selid.conv_selprop(top, gelem); |
} |
} |
/** |
The function prints the reuired quantity to the output file given by argument out. |
@param[in] lcid - load case id. |
@param[in] time - actual time or load coefficient |
@param[in] stepid - time/load step identfier |
@param[in] lcsarray - array of the local coordinate system definitions |
@param[in] nv - actual nodal values of quantities related to nodes only |
@param[in] fmt - format of the output result file. |
@return The function does not return anything but it makes output to the file given by argument out. |
Created by TKo, 09.2023 |
*/ |
void outquantm::print_quant(long lcid, double time, long stepid, lcoordsys *lcsarray, gnodvalvm &nv, resfilefmt fmt) |
{ |
collect_quant_val(lcid, lcsarray, nv); |
switch (fmt){ |
case resfmt_open_dx: |
case resfmt_femcad: |
case resfmt_gid: |
case resfmt_vtk: |
case resfmt_plain_out: |
case resfmt_diag_dat: |
//print_diag_dat(outf, selid, seleip, tnpnt, selip, ncmpr, |
break; |
default: |
print_err("unknown format of the output file (%d) is required.\n", __FILE__ , __LINE__, __func__, int(fmt)); |
abort(); |
} |
} |
/** |
The function collects quantity values in arrays qvv or qvs according to the natural quantity |
representation. The transformations or scaling of the selected quantity is being performed |
according to the appropriate options. |
@param[in] lcid - load case id |
@param[in] lcsarray - array of the local coordinate system defintions |
@return The function does not return anything but changes values either in array qvs or qvv. |
Created by Tomas Koudelka, 09.2023 |
*/ |
void outquantm::collect_quant_val(long lcid, lcoordsys *lcsarray, gnodvalvm &nv) |
{ |
vector auxv; |
matrix auxm; |
switch(qr){ |
case scalq: |
clean_qvs(); |
break; |
case vectq: |
clean_qvv(); |
break; |
case tensq: |
clean_qvv(); |
break; |
default: |
print_err("unknown cahracter type %d of the required quantity", __FILE__, __LINE__, __func__, int(qr)); |
abort(); |
} |
// collect values from nodes or elements |
switch (tpnt){ |
case atnode: |
collect_nodal_quant_val(lcid, nv); |
break; |
case atip: |
collect_elem_quant_val(lcid); |
break; |
default: |
print_err("unknown point type %d is required", __FILE__, __LINE__, __func__, int(tpnt)); |
abort(); |
} |
// make transformation to the required coordinate system |
make_coord_transf(lcsarray); |
// make quantity scaling or other transformation of the quantity values |
make_scale_transf(); |
} |
/** |
The function collects nodal quantity values in arrays qvv or qvs according to the natural |
quantity representation. |
@param[in] lcid - load case id |
@return The function does not return anything but changes values either in array qvs or qvv. |
Created by Tomas Koudelka, 09.2023 |
*/ |
void outquantm::collect_nodal_quant_val(long lcid, gnodvalvm &nv) |
{ |
long i; |
vector auxv; |
matrix auxm; |
if ((selid.st == sel_list) || (selid.st == sel_single)){ // list of nodal indices or single node are given |
for(i=0; i<selid.n; i++){ |
switch(qr){ |
case scalq: |
Mt->give_nodal_quant(selid.id1[i], mqn, reftensq, lcid, qvs[i]); |
break; |
case vectq: |
makerefv(auxv, qvv[selid.id1[i]], maxncmp); |
Mt->give_nodal_quant(selid.id1[i], mqn, lcid, seliq, nv, auxv); |
break; |
case tensq: |
makerefm(auxm, qvv[selid.id1[i]], 3, 3); |
Mt->give_nodal_quant(selid.id1[i], mqn, reftensq, lcid, auxm); |
break; |
default: |
print_err("unknown type %d of the required quantity", __FILE__, __LINE__, __func__, int(qr)); |
abort(); |
} |
} |
} |
else{ // all nodes or range of nodal indices are given |
for(i=0; i<Mt->nn; i++){ |
if(selid.presence_id(i)){ |
switch(qr){ |
case scalq: |
Mt->give_nodal_quant(i, mqn, reftensq, lcid, qvs[i]); |
break; |
case vectq: |
makerefv(auxv, qvv[i], maxncmp); |
Mt->give_nodal_quant(i, mqn, lcid, seliq, nv, auxv); |
break; |
case tensq: |
makerefm(auxm, qvv[i], 3, 3); |
Mt->give_nodal_quant(i, mqn, reftensq, lcid, auxm); |
break; |
default: |
print_err("unknown type %d of the required quantity", __FILE__, __LINE__, __func__, int(qr)); |
abort(); |
} |
} |
} |
} |
} |
/** |
The function collects element quantity values in arrays qvv or qvs according to the natural |
quantity representation. |
@param[in] compid - component id |
@return The function does not return anything but changes values either in array qvs or qvv. |
Created by Tomas Koudelka, 09.2023 |
*/ |
void outquantm::collect_elem_quant_val(long lcid) |
{ |
long i, j, ipp, tnip; |
vector auxv; |
matrix auxm; |
if ((selid.st == sel_list) || (selid.st == sel_single)){ // list of element indices is given |
for(i=0; i<selid.n; i++){ |
ipp=Mt->elements[selid.id1[i]].ipp[0][0]; |
tnip = Mt->give_tnip(selid.id1[i]); |
switch(qr){ |
case scalq: |
for(j=0; j<tnip; j++, ipp++){ |
if (seleip.presence_id(j)) |
Mm->give_quant(ipp, mqn, reftensq, lcid, seliq, other_tens_strastre, qvs[ipp]); |
} |
break; |
case vectq: |
for(j=0; j<tnip; j++, ipp++){ |
if (seleip.presence_id(j)){ |
makerefv(auxv, qvv[ipp], maxncmp); |
Mm->give_quant(i, mqn, lcid, seliq, auxv); |
} |
} |
break; |
case tensq: |
for(j=0; j<tnip; j++, ipp++){ |
if (seleip.presence_id(j)){ |
makerefm(auxm, qvv[ipp], 3, 3); |
Mm->give_quant(ipp, mqn, reftensq, lcid, seliq, other_tens_strastre, auxm); |
} |
} |
break; |
default: |
print_err("unknown type %d of the required quantity", __FILE__, __LINE__, __func__, int(qr)); |
abort(); |
} |
} |
} |
else{ // all elements or index ranges are selected |
for(i=0; i<Mt->ne; i++){ |
if(selid.presence_id(i)){ |
ipp=Mt->elements[i].ipp[0][0]; |
tnip = Mt->give_tnip(i); |
switch(qr){ |
case scalq: |
for(j=0; j<tnip; j++, ipp++){ |
if (seleip.presence_id(j)) |
Mm->give_quant(ipp, mqn, reftensq, lcid, seliq, other_tens_strastre, qvs[ipp]); |
} |
break; |
case vectq: |
for(j=0; j<tnip; j++, ipp++){ |
if (seleip.presence_id(j)){ |
makerefv(auxv, qvv[ipp], maxncmp); |
Mm->give_quant(i, mqn, lcid, seliq, auxv); |
} |
} |
break; |
case tensq: |
for(j=0; j<tnip; j++, ipp++){ |
if (seleip.presence_id(j)){ |
makerefm(auxm, qvv[ipp], 3, 3); |
Mm->give_quant(ipp, mqn, reftensq, lcid, seliq, other_tens_strastre, auxm); |
} |
} |
break; |
default: |
print_err("unknown type %d of the required quantity", __FILE__, __LINE__, __func__, int(qr)); |
abort(); |
} |
} |
} |
} |
} |
/** |
The function transforms %vector or tensor quantities stored in auxiliary array qvv |
to the coordinate system defined by lcs. |
@param[in] pid - point id, where the transformation %matrix will be assmebled |
@param[in] lcsarray - array of the local coordinate system definitions |
@return The function does not return anything, but changes values in the array qvv. |
*/ |
void outquantm::make_coord_transf(lcoordsys *lcsarray) |
{ |
long i, j, tmdim; |
matrix auxm, tmat; |
vector auxv; |
vector pc(ASTCKVEC(3)); |
// make transformation to the local coordinate system |
if (lcs > 0){ |
tmdim = lcsarray[lcs-1].dim; |
reallocm(RSTCKMAT(tmdim, tmdim, tmat)); |
if (qr == vectq){ |
for(i=0; i<tnpnt; i++){ |
give_pnt_coord(i, pc); |
lcsarray[lcs-1].give_transfmat(tmat, pc, Mp->time); |
makerefv(auxv, qvv[i], ncmpr); |
glvectortransfblock(auxv, tmat); |
} |
} |
if (qr == tensq){ |
for(i=0; i<tnpnt; i++){ |
give_pnt_coord(i, pc); |
lcsarray[lcs-1].give_transfmat(tmat, pc, Mp->time); |
makerefm(auxm, qvv[i], 3, 3); |
glmatrixtransfblock(auxm, tmat); |
} |
} |
} |
// make transformation of the nodal quantitiy vector values to the global coordinate system |
// if local coordinate system is defined at nodes |
if ((lcs == 0) && (qr == vectq) && (tpnt == atnode)){ |
for (i=0; i<tnpnt; i++){ |
tmdim = Mt->nodes[i].transf; |
if (tmdim > 0){ |
give_pnt_coord(i, pc); |
lcsarray[lcs-1].give_transfmat(tmat, pc, Mp->time); |
if ((tmdim == 2) && (Gtm->gnodes[i].ndofn == 3)){ |
// 2D beam problem |
tmdim = 3; |
tmat(2,2) = 1.0; |
} |
reallocm(RSTCKMAT(tmdim, tmdim, tmat)); |
switch(mqn){ |
case displ_q: // displacement vector |
case react_q: // reactions vector at nodes |
case load_vect_q: // load vector at nodes |
case int_force_q: // internal force vector |
case resid_vect_q: // residual vector |
makerefv(auxv, qvv[i], ncmpr); |
lgvectortransfblock(auxv, tmat); |
break; |
default: |
break; |
} |
} |
} |
} |
// make transformation to the principal coordinate system |
if ((lcs < 0) && (qr == tensq)){ |
long ret = 1; |
matrix tv, pvect(ASTCKMAT(3,3)); |
vector auxv, pval(ASTCKVEC(3)); |
strastrestate ssst = give_pnt_ssst(i); |
ivector id(ASTCKIVEC(3)); |
for(i=0; i<tnpnt; i++){ |
switch (tsn){ |
case voigtred: |
makerefv(auxv, qvv[i], ncmpr); |
reallocm(RSTCKMAT(3, 3, tv)); |
vector_tensor(auxv, tv, give_pnt_ssst(i), tti); |
break; |
default: |
break; |
} |
if (ncmpr <= 6){ |
makerefv(auxv, qvv[i], ncmpr); |
reallocm(RSTCKMAT(3, 3, tv)); |
vector_tensor(auxv, tv, give_pnt_ssst(i), tti); |
ret = 0; |
} |
if (ncmpr == 9){ |
makerefm(tv, qvv[i], 3, 3); |
ret = 0; |
} |
if (ret){ |
print_err("cannot assemble the second order tensor from %ld component array", |
__FILE__, __LINE__, __func__, ncmpr); |
abort(); |
} |
princ_val(tv, pval, pvect, ni_jac, err_jac, zero, Mp->dim, 1); |
give_all_normal_indices(ssst, id); |
memset(qvv[i], 0, sizeof(*qvv[i]*ncmpr)); |
for (j=0; j<3; j++){ |
if (id(j) >= 0) |
qvv[i][id(j)] = pval(j); |
} |
} |
} |
} |
/** |
The function performs additional scaling/transformation of the qunatities in the |
auxiliary arrays qvs or qvv according to the given quantity representation. It can be used |
for the unit conversion as well as for the other more complex transformations. The |
scaling/transformations is made with the help of general function qst. |
If the qst is a constant function then the simple qunatity scaling is performed. |
For another (complex) tansformations a parser function type can be used. The parser |
expression can refer to point coordinates denoted as x, y, z, time denoted as t |
and quantity value denoted as q. For vector/tensor qunatities, the same transformation |
formula is applied on all components. |
@return The function does not return anything, but it changes values in arrays qvs and qvv. |
Created by Tomas Koudelka, 09.2023 |
*/ |
void outquantm::make_scale_transf() |
{ |
long i, j, nc; |
if (qstf == yes){ |
vector pc(ASTCKVEC(5)); |
double *val; |
for(i=0; i<tnpnt; i++){ |
give_pnt_coord(i, pc); |
pc(3) = Mp->time; |
if (qr == scalq){ |
nc = 1; |
val = qvs+i; |
} |
else{ |
nc = ncmpr; |
val = qvv[i]; |
} |
for(j=0; j<nc; j++){ |
if (qst.tfunc == constant){ |
// the constant is considered to be a qunatity scaling factor |
val[j] *= qst.getval(Mp->time); |
} |
else{ |
// other (complex) transformation is made with the help of parser, |
// e.g. temperature conversion from K to deg C can be made with the help |
// of the following parser expression 'q-273.15' |
pc(4) = val[j]; |
val[j] = qst.getval(pc, namepar); |
} |
} |
} |
} |
} |
/** |
The function returns position vector of the given pid-th point. |
@param[in] pid - point id, i.e. nodal or element ip identifier |
@param[out] pc - resulting position %vector, it will contain point coordinates x, y, and z on the output |
@return The function returns position %vector in the argument pc. |
Created by Tomas Koudelka, 09.2023 |
*/ |
void outquantm::give_pnt_coord(long pid, vector &pc) |
{ |
nullv(pc); |
if (tpnt == atnode) Mt->give_nodal_coord(pid, pc); |
if (tpnt == atip) ipcoord(Mm->elip[pid], pid, 0, 0, pc); |
} |
/** |
The function returns stress/strain state at the given pid-th point. |
@param[in] pid - point id, i.e. nodal or element ip identifier |
@return The function returns stress/strain state of the given point. |
Created by Tomas Koudelka, 09.2023 |
*/ |
strastrestate outquantm::give_pnt_ssst(long pid) |
{ |
strastrestate ssst; |
if (tpnt == atnode) ssst = guess_ssst(Mt->nodes[pid].ncompstr); |
if (tpnt == atip) ssst = Mm->ip[pid].ssst; |
return ssst; |
} |
/** |
The function sets all values in the auxiliary array qs to zero. |
@return The function does not return anything but it zeroes array qs. |
Created by Tomas Koudelka, 09.2023 |
*/ |
void outquantm::clean_qvs() |
{ |
memset(qvs, 0, sizeof(*qvs)*tnpnt); |
} |
/** |
The function sets all component values in the auxiliary array qvv to zero. |
@return The function does not return anything but it zeroes array qvv. |
Created by Tomas Koudelka, 09.2023 |
*/ |
void outquantm::clean_qvv() |
{ |
long i; |
for (i=0; i<tnpnt; i++){ |
memset(qvv[i], 0, sizeof(*qvv[i])*maxncmp); |
} |
} |
/** |
The function creates string with default label of the required quantity. |
@param[in] mq - required mechanical quantity identifier |
@param[in] rmq - referenced mechanical qunatity for tensor calculations, otherwise it is ignored |
@param[in] maxll - maximum length of label |
@param[out] label - output string with default label of the required quantity, |
it must be allocated to the maxll length at least |
@return The function returns the default quantity label in the argument label. |
Created by Tomas Koudelka, 10.2023 |
*/ |
void outquantm::give_quant_deflabel(mechquant mq, mechquant rmq, long maxll, char *label) |
{ |
long l; |
label[0] = '\0'; |
switch (mq){ |
case displ_q: // displacements vector (r) |
snprintf(label, maxll, "r"); |
break; |
case strain_q: // strain tensor |
snprintf(label, maxll, "eps"); |
break; |
case stress_q: // stress tensor (sig) |
snprintf(label, maxll, "sig"); |
break; |
case other_q: // other array values as a vector (other) |
snprintf(label, maxll, "other"); |
break; |
case react_q: // reactions vector at nodes (R) |
snprintf(label, maxll, "R"); |
break; |
case load_vect_q: // load vector at nodes (f_l) |
snprintf(label, maxll, "f_l"); |
break; |
case int_force_q: // internal force vector (f_i) |
snprintf(label, maxll, "f_i"); |
break; |
case resid_vect_q: // residual vector (f_r) |
snprintf(label, maxll, "f_r"); |
break; |
case tempr_strain_q: // temperature strain tensor (epst) |
snprintf(label, maxll, "epst"); |
break; |
case eig_strain_q: // eigenstrain tensor (eps0) |
snprintf(label, maxll, "eps0"); |
break; |
case eig_stress_q: // eigenstress tensor (sig0) |
snprintf(label, maxll, "sig0"); |
break; |
case time_q: // time (constant scalar quantity at whole domain) |
snprintf(label, maxll, "t"); |
break; |
case step_id_q: // step id (constant scalar quantity at whole domain) |
snprintf(label, maxll, "step_id"); |
break; |
case load_fact_q: // load factor in nonlinear statics problem type (constant scalar quantity at whole domain) |
snprintf(label, maxll, "lambda"); |
break; |
case eigval_q: // eigen values in eigenvalue problem type (constant scalar quantity at whole domain) |
snprintf(label, maxll, "lambda"); |
break; |
case macrostrain_q: // macrostrain (constant tensor quantity at whole domain) (Sig) |
snprintf(label, maxll, "Eps"); |
break; |
case macrostress_q: // macrostress (constant tensor quantity at whole domain) (Eps) |
snprintf(label, maxll, "Sig"); |
break; |
case nonmech_q: // nonmechanical quantities at ip |
snprintf(label, maxll, "nonmechq"); |
break; |
case first_inv: // A11 + A22 + A33 (I_1) |
snprintf(label, maxll, "I_1("); |
give_quant_deflabel(rmq, nomech_q, maxll, label+4); |
l = strlen(label); |
snprintf(label+l, maxll-l, ")"); |
break; |
case second_inv: // A11*A22 + A11*A33 + A22*A33 - A12^2 - A13^2 - A23^2 (I_2) |
snprintf(label, maxll, "I_2("); |
give_quant_deflabel(rmq, nomech_q, maxll, label+4); |
l = strlen(label); |
snprintf(label+l, maxll-l, ")"); |
break; |
case third_inv: // det|A| (I_3) |
snprintf(label, maxll, "I_3("); |
give_quant_deflabel(rmq, nomech_q, maxll, label+4); |
l = strlen(label); |
snprintf(label+l, maxll-l, ")"); |
break; |
case tensor_norm: // ||A|| = sqrt(a_ij*a_ij) (||.||) |
snprintf(label, maxll, "||"); |
give_quant_deflabel(rmq, nomech_q, maxll, label+2); |
l = strlen(label); |
snprintf(label+l, maxll-l, "||"); |
break; |
case tensdeviator: // D_ij = A_ij - delta_ij*A_kk/3 (d) |
snprintf(label, maxll, "d("); |
give_quant_deflabel(rmq, nomech_q, maxll, label+2); |
l = strlen(label); |
snprintf(label+l, maxll-l, ")"); |
break; |
case strain_vol: // eps_v = eps_x + eps_y + eps_z (eps_v) |
snprintf(label, maxll, "eps_v"); |
break; |
case mean_stress: // sig_m = (sig_x + sig_y + sig_z)/3 (sig_m) |
snprintf(label, maxll, "sig_m"); |
break; |
case j2inv: // negative value of the second invariant of stress deviator, i.e. J2 = 1/2 s_ij s_ij (J2) |
snprintf(label, maxll, "J_2s"); |
break; |
case von_mises_stress:// sig_eff = sqrt(3*J2) (sig_vM) |
snprintf(label, maxll, "sig_vM"); |
break; |
case strain_deviator: // e_ij = eps_ij - delta_ij*eps_v/3 (d(eps)) |
snprintf(label, maxll, "d(eps)"); |
break; |
case stress_deviator: // s_ij = sig_ij - delta_ij*sig_m (d(sig)) |
snprintf(label, maxll, "d(sig)"); |
break; |
case strain_pl: // plastic strain tensor (epsp) |
snprintf(label, maxll, "epsp"); |
break; |
case cons_param: // consistency parameter gamma |
snprintf(label, maxll, "gamma"); |
break; |
case damage_scal: // scalar damage (omega) |
snprintf(label, maxll, "omega"); |
break; |
case damaget_scal: // scalar damage (omega_t) in tension |
snprintf(label, maxll, "omega_t"); |
break; |
case damagec_scal: // scalar damage (omega_c) in compression |
snprintf(label, maxll, "omega_c"); |
break; |
case damage_tens: // damage tensor (Omega) |
snprintf(label, maxll, "Omega"); |
break; |
case damaget_tens: // damage tensor (Omega_t) in tension |
snprintf(label, maxll, "Omega_t"); |
break; |
case damagec_tens: // damage tensor (Omega_c) in compression |
snprintf(label, maxll, "Omega_c"); |
default: |
snprintf(label, maxll, "%s", mechquant_kwdset.get_str(mq)); |
} |
return; |
} |
/** |
The function returns pointer to the string with default label of the required quantity component. |
@param[in] mq - required mechanical quantity identifier |
@param[in] rmq - referenced mechanical qunatity for tensor calculations, otherwise it is ignored |
@param[in] ssst - stress/strain state of the tensor quantity, not used for other representations (scalar/vector) |
of teh required mq. |
@param[in] compid - required component id |
@param[in] maxll - maximum length of label |
@param[out] label - output string with default label of the required quantity, |
it must be allocated to the maxll length at least |
@return The function returns the default quantity component label in the argument label. |
Created by Tomas Koudelka, 10.2023 |
*/ |
void outquantm::give_quant_comp_deflabel(mechquant mq, mechquant rmq, strastrestate ssst, long compid, long maxll, char *label) |
{ |
long l; |
label[0] = '\0'; |
give_quant_deflabel(mq, rmq, maxll, label); |
l = strlen(label); |
switch(mq){ |
case displ_q: // displacements vector (r) |
snprintf(label, maxll, "r_%s", vector_cnamem::displ_cmpstr(ssst, compid)); |
break; |
case strain_q: // strain tensor |
snprintf(label, maxll, "%s", tensor_cname::strain_cmpstr(ssst, compid)); |
break; |
case stress_q: // stress tensor (sig) |
snprintf(label, maxll, "%s", tensor_cname::stress_cmpstr(ssst, compid)); |
break; |
case other_q: // other array values as a vector (other) |
snprintf(label, maxll, "other_%ld", compid+1); |
break; |
case react_q: // reactions vector at nodes (R) |
snprintf(label, maxll, "%s", vector_cnamem::react_cmpstr(ssst, compid)); |
break; |
case load_vect_q: // load vector at nodes (f_l) |
snprintf(label, maxll, "f_l_%s", vector_cnamem::vect_indstr(ssst, compid)); |
break; |
case int_force_q: // internal force vector (f_i) |
snprintf(label, maxll, "f_i_%s", vector_cnamem::vect_indstr(ssst, compid)); |
break; |
case resid_vect_q: // residual vector (f_r) |
snprintf(label, maxll, "f_r_%s", vector_cnamem::vect_indstr(ssst, compid)); |
break; |
case tempr_strain_q: // temperature strain tensor (epst) |
snprintf(label, maxll, "epst_%s", tensor_cname::tens_indstr(ssst, compid)); |
break; |
case eig_strain_q: // eigenstrain tensor (eps0) |
snprintf(label, maxll, "eps0_%s", tensor_cname::tens_indstr(ssst, compid)); |
break; |
case eig_stress_q: // eigenstress tensor (sig0) |
snprintf(label, maxll, "sig0_%s", tensor_cname::tens_indstr(ssst, compid)); |
break; |
case macrostrain_q: // macrostrain (constant tensor quantity at whole domain) (Sig) |
snprintf(label, maxll, "Eps_%s", tensor_cname::tens_indstr(ssst, compid)); |
break; |
case macrostress_q: // macrostress (constant tensor quantity at whole domain) (Eps) |
snprintf(label, maxll, "Sig_%s", tensor_cname::tens_indstr(ssst, compid)); |
break; |
case nonmech_q: // nonmechanical quantities at ip |
snprintf(label, maxll, "nonmechq_%ld", compid+1); |
break; |
case tensdeviator: // D_ij = A_ij - delta_ij*A_kk/3 (d) |
snprintf(label, maxll, "d("); |
give_quant_deflabel(rmq, nomech_q, maxll-2, label+2); |
l = strlen(label); |
snprintf(label+l, maxll-l, ")_%s", tensor_cname::tens_indstr(ssst, compid)); |
break; |
case strain_deviator: // e_ij = eps_ij - delta_ij*eps_v/3 (d(eps)) |
snprintf(label, maxll, "d(eps)_%s", tensor_cname::tens_indstr(ssst, compid)); |
break; |
case stress_deviator: // s_ij = sig_ij - delta_ij*sig_m (d(sig)) |
snprintf(label, maxll, "d(sig)_%s", tensor_cname::tens_indstr(ssst, compid)); |
break; |
case strain_pl: // plastic strain tensor (epsp) |
snprintf(label, maxll, "epsp_%s", tensor_cname::tens_indstr(ssst, compid)); |
break; |
case cons_param: // consistency parameter gamma |
snprintf(label, maxll, "gamma"); |
break; |
case damage_scal: // scalar damage (omega) |
snprintf(label, maxll, "omega"); |
break; |
case damaget_scal: // scalar damage (omega_t) in tension |
snprintf(label, maxll, "omega_t"); |
break; |
case damagec_scal: // scalar damage (omega_c) in compression |
snprintf(label, maxll, "omega_c"); |
break; |
case damage_tens: // damage tensor (Omega) |
snprintf(label, maxll, "Omega_%s", tensor_cname::tens_indstr(ssst, compid)); |
break; |
case damaget_tens: // damage tensor (Omega_t) in tension |
snprintf(label, maxll, "Omega_t_%s", tensor_cname::tens_indstr(ssst, compid)); |
break; |
case damagec_tens: // damage tensor (Omega_c) in compression |
snprintf(label, maxll, "Omega_c_%s", tensor_cname::tens_indstr(ssst, compid)); |
default: |
snprintf(label, maxll, "%s", mechquant_kwdset.get_str(mq)); |
} |
return; |
} |
/trunk/SIFEL/MEFEL/SRC/outquantm.h |
---|
0,0 → 1,134 |
#ifndef OUTQUANTM_H |
#define OUTQUANTM_H |
#include "iotools.h" |
#include "selection.h" |
#include "alias.h" |
#include "galias.h" |
#include <stdio.h> |
class siftop; |
class lcoordsys; |
class gnodvalvm; |
class outquantm |
{ |
public: |
/// constructor |
outquantm(); |
/// destructor |
~outquantm(); |
/// reads data from file |
long read(XFILE *in); |
/// prints description data to file |
void print(FILE *out); |
/// converts selections given by property id to list or range type |
void conv_sel_prop(siftop *top); |
/// prints values for selected items to grahics file |
void print_quant(long lcid, double time, long stepid, lcoordsys *lcsarray, gnodvalvm &nv, resfilefmt fmt); |
/// collects required quantity values at all points |
void collect_quant_val(long lcid, lcoordsys *lcsarray, gnodvalvm &nv); |
/// collects the given quantity values at all nodes and store them in the auxiliary arrays qvs or qvv |
void collect_nodal_quant_val(long lcid, gnodvalvm &nv); |
/// collects the given quantity values on all elements and store them in the auxiliary arrays qvs or qvv |
void collect_elem_quant_val(long lcid); |
/// transforms values in auxiliary array qvv to the required coordinate system |
void make_coord_transf(lcoordsys *lcsarray); |
/// makes quantity value scaling or other transformation |
void make_scale_transf(); |
/// returns position %vector of the given point |
void give_pnt_coord(long pid, vector &pc); |
/// returns stress/strain state indicator in the given point |
strastrestate give_pnt_ssst(long pid); |
/// zeroes values in auxiliary array qvs |
void clean_qvs(); |
/// zeroes values in auxiliary array qvv |
void clean_qvv(); |
/// returns pointer to the string with default label of the required quantity |
static void give_quant_deflabel(mechquant mq, mechquant rmq, long maxll, char *label); |
/// returns pointer to the string with default label of the required quantity component |
static void give_quant_comp_deflabel(mechquant mq, mechquant rmq, strastrestate ssst, |
long compid, long maxll, char *label); |
/// name of the required mechanical quantity |
mechquant mqn; |
/// name of the referenced quantity if the mqn represents an ordinary tensor |
mechquant reftensq; |
/// identifier of tensor type (stress/strain/other) for tensors stored in other or nonmech arrays |
strastre other_tens_strastre; |
/// maximum length of quantity label string |
static const long maxl_qlabel = 256; |
/// quantity label (if '@' is the first character then automatic label will be generated) |
char qlabel[maxl_qlabel]; |
/// indicator whether to use default quantity name |
bool defqlabel; |
/// type of point where the quantity is to be printed out (node/elem ipp/elem UDP) |
nodip tpnt; |
/// total number of points (nodes or elems according to tpnt) defined in the problem solved, i.e. Mt->nn or Mm->tnip |
long tnpnt; |
/// selection nodal/element ids where the quantity will be printed out |
sel selid; |
/// selected integration points on elements given by selid |
sel seleip; |
/// number of user defined points on selected elements |
long nudp; |
/// natural coordinates of selected user defined points |
double *ksi, *eta, *zeta; |
/// the given quantity representation (scalar/vector/tensor2d) in the output format |
quantrep qrf; |
/// indices of selected quantity components (displacement comps, strain/stress comps, ...) |
sel seliq; |
/// quantity scaling/tranformation flag |
answertype qstf; |
/// function for scaling/tranformation of the quantity |
gfunct qst; |
/// local coordinate system for vector and tensor2d quantities |
long lcs; |
// auxiliary members determined in mechmat |
/// natural mathematical representation of the given quantity (scalar/vector/tensor2) determined in mechmat |
quantrep qr; |
/// number of quantity components in the case of vector or tensor quantity in the natural representation |
long ncmp; |
/// reduced number of quantity components in the case of vector or tensor quantity according to the component selection |
long ncmpr; |
/// tensor quantity storage notation (Voigt reduced/Voigt full/Full matrix 3x3) |
tensqnot tsn; |
/// tensor quantity type identifier (strain/stress/other) |
strastre tti; |
// auxiliary members not read in the quantity record, read/handled in outresfile, outdriverm |
/// pointer to the output file name string |
char *outfname; |
/// pointer to the associated output file of the given quantity |
FILE *outf; |
/// index shift of the first element |
long ide1; |
/// index shift of the first node |
long idn1; |
/** Auxiliary array of quantity values, qvv[i] represents pointer to array of the given vector/tensor2d quantity components |
at i-th node/element ip/element UDP. In the case of elements ip or UDP, qvv[i][j] is the value of j-th selected |
quantity component at k-th element ip or UDP and ncomp is the maximum number of vector/tensor2d components. |
*/ |
static double **qvv; |
/** Auxiliary array of quantity values, qvv[i] represents value of the selected quantity cpomponent |
at i-th node/element ip/element UDP in the case of scalar output format */ |
static double *qvs; |
/// maximum number of points where the quantities will be printed out, it is the first dimension of arrays qvv and qvs |
static long maxnpnt; |
/// maximum number of components of quantities that will be printed out, it is the second dimension of array qvv |
static long maxncmp; |
/// parameter names of the general function transformation matrix |
static const char *namepar[]; |
/// maximum number of iterations in Jacobi's method for the determination of the tensor's principal values |
static long ni_jac; |
/// tolerance of Jacobi's method for the determination of the tensor's principal values |
static double err_jac; |
/// zero treshold for the distinguishing of zero values in Jacobi's method |
static double zero; |
}; |
#endif |
/trunk/SIFEL/MEFEL/SRC/outresfilem.cpp |
---|
0,0 → 1,330 |
#include "outresfilem.h" |
#include "iotools.h" |
#include "outquantm.h" |
#include "mechprint.h" |
#include "global.h" |
#include "probdesc.h" |
#include "mechtop.h" |
#include "mechmat.h" |
#include "tensorcname.h" |
#include "vectorcnamem.h" |
#include "xfile.h" |
outresfilem::outresfilem() : outfbn{}, outfmn{} |
{ |
outfbnl = 0; |
outfbn[0] = '\0'; |
rffmt = resfmt_no; |
nqnt = 0; |
qnt = NULL; |
outf = NULL; |
outfmn[0] = '\0'; |
} |
outresfilem::~outresfilem() |
{ |
delete [] qnt; |
} |
/** |
The function reads the given output file description. |
@param[in] in - pointer to the opened text file |
@retval 0 - on success, |
@retval 1 - error in the reading of base output file name, |
@retval 2 - error in the reading of output file format, |
@retval 3 - error in the reading of time step selection, |
@retval 4 - error in the reading of load case selection, |
@retval 5 - error in the reading of number of required quantities, |
@retval 6 - error in the reading of some quantity description. |
Created by Tomas Koudelka, 10.2023 |
*/ |
long outresfilem::read(XFILE *in) |
{ |
long i, ret; |
// read name of the given result output file |
ret = xfscanf(in, "%s", outfbn); |
if (ret != 1){ |
print_err("cannot read base file name from file", __FILE__, __LINE__, __func__); |
return 1; |
} |
outfbnl = strlen(outfbn); |
// read format of the given result file |
ret = xfscanf(in, "%k%m", "res_file_fmt", &resfilefmt_kwdset, &rffmt); |
if (ret != 2){ |
print_err("cannot read result file format", __FILE__, __LINE__, __func__); |
return 2; |
} |
// read selection of the required time steps in which the output to the given file will be performed |
ret = selstep.read(in); |
if (ret){ |
print_err("cannot read selection of time step", __FILE__, __LINE__, __func__); |
return 3; |
} |
// read selection of the required load cases in which the output to the given file will be performed |
ret = sellc.read(in); |
if (ret){ |
print_err("cannot read load case selection", __FILE__, __LINE__, __func__); |
return 4; |
} |
// read number of required quantities |
ret = xfscanf(in, "%k%ld", "nquant", &nqnt); |
if (ret != 2){ |
print_err("cannot read number of required quantities", __FILE__, __LINE__, __func__); |
return 5; |
} |
// read particular quantities |
qnt = new outquantm[nqnt]; |
for(i=0; i<nqnt; i++){ |
ret = qnt[i].read(in); |
if (ret != 2){ |
print_err("cannot read %ld. quantity description", __FILE__, __LINE__, __func__, i+1); |
return 6; |
} |
} |
return 0; |
} |
/** |
The function prints the given output file description. |
@param[in,out] out - pointer to the opened text file |
@return The function does not return anything, but changes the content of the output file given by the argument out. |
Created by Tomas Koudelkam, 10.2023 |
*/ |
void outresfilem::print(FILE *out) |
{ |
long i; |
// print name of the given result output file |
fprintf(out, "%s\n", outfbn); |
// print format of the given result file |
fprintf(out, "%d\n", int(rffmt)); |
// print selection of the required time steps in which the output to the given file will be performed |
selstep.print(out); |
// read selection of the required load cases in which the output to the given file will be performed |
sellc.print(out); |
// read number of required quantities |
fprintf(out, "%ld\n", nqnt); |
// read particular quantities |
for(i=0; i<nqnt; i++) |
qnt[i].print(out); |
} |
/** |
The function prints initial header to the output file for |
particular result formats. |
@param[in] istep - time/load step identifier |
@param[in] time - actual time or load coefficient |
@return The function does not return anything, but changes content of the output file outf. |
Created by Tomas Koudelka, 10.2023 |
*/ |
void outresfilem::print_header(long istep, double time) |
{ |
long i, j; |
char *label = NULL; |
strastrestate ssst = strastrestate(0); |
switch(rffmt){ |
case resfmt_gid: |
fprintf(outf, "GiD Post Results File 1.0\n"); |
break; |
case resfmt_vtk: |
print_vtk_header(outf, istep, time); //print header, points, nodes, elements |
break; |
case resfmt_plain_out: |
fprintf(outf, "%15s **** * **** **** *\n", " "); |
fprintf(outf, "%15s * * * * *\n", " "); |
fprintf(outf, "%15s * * *** *** *\n", " "); |
fprintf(outf, "%15s * * * * *\n", " "); |
fprintf(outf, "%15s**** * * **** **** MEFEL OUTPUT\n", " "); |
// print specific header string |
fprintf(outf, "\n%s\n", Mp->name); |
fprintf(outf, "\n\n\n\n\n"); |
break; |
case resfmt_diag_dat: |
fprintf(outf, "#"); |
for (i=0; i<nqnt; i++){ |
if (qnt[i].defqlabel == true) |
label = new char[outquantm::maxl_qlabel]; |
ssst = qnt[i].give_pnt_ssst(qnt[i].selid.id1[0]); |
for(j=0; j<qnt[i].ncmp; j++){ |
if (qnt[i].seliq.presence_id(j)){ |
if (qnt[i].defqlabel == false){ |
fprintf(outf, " %s", qnt[i].qlabel); |
if (qnt[i].qr == tensq){ |
fprintf(outf, "_%s", tensor_cname::tens_indstr(ssst, j)); |
} |
if ((qnt[i].qr == vectq) && (qnt[i].mqn < tempr_strain_q)) // global nodal vectors |
fprintf(outf, "_%s", vector_cnamem::vect_indstr(ssst, j)); |
if ((qnt[i].qr == vectq) && (qnt[i].mqn >= tempr_strain_q)) // other, nonmechq |
fprintf(outf, "_%ld", j+1); |
} |
else{ |
ssst = qnt[i].give_pnt_ssst(qnt[i].selid.id1[0]); |
qnt[i].give_quant_comp_deflabel(qnt[i].mqn, qnt[i].reftensq, ssst, j, outquantm::maxl_qlabel, label); |
fprintf(outf, " %s", label); |
} |
} |
} |
} |
fprintf(outf, "\n"); |
break; |
default: |
print_err("unknown type of file format (%d) is required in the output file '%s'.", |
__FILE__, __LINE__, __func__, int(rffmt), outfmn); |
abort(); |
} |
delete [] label; |
} |
/** |
The function creates modifed file name of the given output file |
with the help of base file name outfbn decorated optionally by the additional |
filename modifiers according to the following rules: |
- if the argument step id given by the argument stepid is non-negative then |
this id is appended to the base file name |
- if the parameter set identfier in the stochastic calculations given by the argument stochid is |
non-negative then this id is appended to the base file name |
- if the base file name has no extension then the default one is appended |
@param[in] stochid - index of the parameter set in the case of stochastic calculation, otherwise stochid=-1 |
@param[in] stepid - time step index, the base file name is not decorated by stepid if stepid=-1 |
Created by Tomas Koudelka, 10.2023 |
*/ |
void outresfilem::get_modified_fname(long stochid, long stepid) |
{ |
char *path, *name, *ext; |
long pathl, namel, extl; |
long pc; |
// decompose base file name into path, name and extension |
filename_decomp_ptr(outfbn, path, name, ext); |
if (path) |
pathl = name - path; |
else |
pathl = 0; |
if (ext){ |
namel = ext - name; |
extl = strlen(ext); |
} |
else{ |
namel = outfbnl; |
extl = 0; |
} |
// take path and file name |
pc = sprintf(outfmn, "%*s", int(pathl+namel), outfbn); |
// add optional identifier of stochastic parameter set |
if (stochid >= 0) |
pc += snprintf(outfmn+pc, fnl-pc, ".%ld", stochid); |
// add optional identifier of stochastic parameter set |
if (stepid >= 0) |
pc += snprintf(outfmn+pc, fnl-pc, ".%ld", stepid); |
if (ext == NULL){ |
// no file extension is specified -> add default one |
const char *dext = give_fmt_dext(rffmt); |
pc += snprintf(outfmn+pc, fnl-pc, ".%s", dext); |
} |
} |
/** |
The function prints all required quantities to the given output file. |
@param[in] lcid - required load case id, |
@param[in] time - actual time or actual load coefficient, |
@param[in] istep - actual step id, |
@param[in] lcsarr - array of the local coordinte systems, |
@param[in] gnv - actual nodal values of quantities related to nodes only |
@param[in] idn1 - shift index of node numbers |
@param[in] ide1 - shift index of element numbers |
@return The function does not return anything but changes content of the file given by outf data member. |
Created by Tomas Koudelka, 10.2023 |
*/ |
void outresfilem::print_quants(long lcid, double time, long istep, lcoordsys *lcsarr, |
gnodvalvm &gnv, long idn1, long ide1) |
{ |
long i; |
for(i=0; i<nqnt; i++){ // loop over all quantities in the file |
qnt[i].outf = outf; |
qnt[i].outfname = outfmn; |
qnt[i].idn1 = idn1; |
qnt[i].ide1 = ide1; |
qnt[i].print_quant(lcid, time, istep, lcsarr, gnv, rffmt); |
} |
} |
/** |
The function returns default file extension for the required result file format. |
@param[in] fmt - required result file format |
@return The function returns pointer to the constant string with result file extension. |
Created by Tomas Koudelka, 10.2023 |
*/ |
const char*outresfilem::give_fmt_dext(resfilefmt fmt) |
{ |
switch(fmt){ |
case resfmt_no: |
return ""; |
case resfmt_open_dx: |
return ""; |
case resfmt_femcad: |
return ""; |
case resfmt_gid: |
return ".res"; |
case resfmt_vtk: |
return ".vtk"; |
case resfmt_plain_out: |
return ".out"; |
case resfmt_diag_dat: |
return ".dat"; |
default: |
print_err("unknown type %d of the result file format", __FILE__, __LINE__, __func__); |
abort(); |
} |
return ""; |
} |
/trunk/SIFEL/MEFEL/SRC/outresfilem.h |
---|
0,0 → 1,62 |
#ifndef OUTRESFILE |
#define OUTRESFILE |
#include "galias.h" |
#include "selection.h" |
#include <stdio.h> |
class lcoordsys; |
class outquantm; |
class stochdriver; |
class gnodvalvm; |
struct XFILE; |
/** |
The class represents description of the result ouput file |
*/ |
class outresfilem |
{ |
public: |
outresfilem(); |
~outresfilem(); |
/// reads data from file |
long read(XFILE *in); |
/// prints description data to file |
void print(FILE *out); |
/// printf header to the output file |
void print_header(long istep, double time); |
/// creates modified file name (default format extension, stepid and parameter set id are added optionally) |
void get_modified_fname(long stochid, long stepid); |
/// prints required quantities to the given output file |
void print_quants(long lcid, double time, long istep, lcoordsys *lcsarr, gnodvalvm &gnv, long idn1, long ide1); |
/// returns default extension of output file format |
static const char* give_fmt_dext(resfilefmt fmt); |
/// maximum length of file name strings |
static const long fnl = 1025; |
/// base name of the output file |
char outfbn[fnl]; |
/// length of outfn string - it is set in outgrfile::read |
long outfbnl; |
/// format of the given result file |
resfilefmt rffmt; |
/// selection of steps which the quantities will be printed in |
sel selstep; |
/// selection of load cases which the quantities will be printed in |
sel sellc; |
/// number of quantities to be printed out |
long nqnt; |
/// array of records with quantity output desprition |
outquantm *qnt; |
/// pointer to the associated output file of the given quantity |
FILE *outf; |
/// modified output file name which corresponds to the opened file in outf |
char outfmn[fnl]; |
}; |
#endif |
/trunk/SIFEL/MEFEL/SRC/plquadiface.cpp |
---|
56,7 → 56,7 |
/** |
The function initializes basic data on elements. |
@param eid - element id |
@param[in] eid - element id |
JK, 11.6.2006 |
87,8 → 87,8 |
by shape functions of the element. The point is given in the |
natural coordinate system of the element. |
@param xi - natural coordinate on element |
@param nodval - nodal values |
@param[in] xi - natural coordinate on element |
@param[in] nodval - nodal values |
@return The function returns the value approximated. |
115,10 → 115,9 |
The function computes integration point values from the given nodal |
values of selected quantity. |
@param eid - number of element |
@param nodval - %vector of nodal values of the given quantity (input) |
@param ipval - %vector of integration point values approximated form |
the nodval. (ouput) |
@param[in] eid - number of element |
@param[in] nodval - %vector of nodal values of the given quantity |
@param[out] ipval - %vector of integration point values approximated form the nodval. |
Created by Tomas Koudelka, 13.1.2016 |
*/ |
155,19 → 154,19 |
/** |
The function assembles transformation %matrix x_g = T x_l |
for transformation from the local nodal coordinate systems. |
The function assembles transformation %matrix x_g = T x_l |
for transformation from the local nodal coordinate systems. |
@param nodes - array containing node numbers |
@param tmat - transformation %matrix |
@param[in] nodes - array containing node numbers |
@param[out] tmat - transformation %matrix |
JK, 11.6.2006 |
JK, 11.6.2006 |
*/ |
void plquadinterface::transf_matrix(ivector &nod, matrix &tmat) |
{ |
long i,n,m; |
fillm (0.0,tmat); |
nullm(tmat); |
n=nod.n; |
m=tmat.m; |
186,16 → 185,16 |
/** |
The function computes stiffness %matrix of plane rectangular |
finite element for contact problems. |
The function computes stiffness %matrix of plane rectangular |
finite element for contact problems. |
@param eid - number of element |
@param ri,ci - row and column indices |
@param sm - resulting stiffness %matrix |
@param[in] eid - number of element |
@param[in] ri,ci - row and column indices |
@param[out] sm - resulting stiffness %matrix |
@return The function returns resulting stiffnes %matrix in the parameter sm. |
@return The function returns resulting stiffnes %matrix in the parameter sm. |
JF, 29.10.2012 |
JF, 29.10.2012 |
*/ |
void plquadinterface::stiffness_matrix(long eid, long ri, long ci, matrix &sm) |
{ |
206,7 → 205,7 |
vector x(ASTCKVEC(nne)), y(ASTCKVEC(nne)), t(ASTCKVEC(nne)); |
matrix gm(ASTCKMAT(ncomp[0], ndofe)), d(ASTCKMAT(tncomp,tncomp)); |
fillm (0.0,sm); |
nullm(sm); |
Mt->give_node_coord2d(x,y,eid); |
Mt->give_elemnodes (eid,nodes); |
239,8 → 238,8 |
Function computes stiffness %matrix of one element. If it is required, nodal values |
are transformed to the local nodal coordinate systems. |
@param eid - number of element |
@param sm - stiffness %matrix (output) |
@param[in] eid - number of element |
@param[out] sm - stiffness %matrix |
@return The function returns required stiffness %matrix in the parameter sm. |
271,8 → 270,8 |
defined loacal nodal coordinate systems then the corresponding |
components of the dislacement %vector are transformed. |
@param lcid - load case id |
@param eid - element id |
@param[in] lcid - load case id |
@param[in] eid - element id |
@return The function stores resulting strains in the array strains |
of the element integration points. |
282,7 → 281,7 |
void plquadinterface::res_mainip_strains (long lcid, long eid) |
{ |
vector aux, x(ASTCKVEC(nne)), y(ASTCKVEC(nne)), r(ASTCKVEC(ndofe)); |
vector aux, r(ASTCKVEC(ndofe)); |
ivector nodes(ASTCKIVEC(nne)); |
matrix tmat; |
295,7 → 294,6 |
reallocv(RSTCKVEC(ndofe, aux)); |
reallocm(RSTCKMAT(ndofe, ndofe, tmat)); |
transf_matrix(nodes, tmat); |
//locglobtransf (aux,r,tmat); |
lgvectortransf(aux, r, tmat); |
copyv(aux, r); |
} |
305,19 → 303,18 |
/** |
The function computes strains at integration points of element. |
It is used in geometrically linear problems. |
The function computes strains at integration points of element. |
It is used in geometrically linear problems. |
@param lcid - load case id |
@param eid - element id |
@param ri,ci - row and column indices |
@param ii - number of block |
@param r - %vector of nodal displacements |
@param[in] lcid - load case id |
@param[in] eid - element id |
@param[in] ri,ci - row and column indices |
@param[in] r - %vector of nodal displacements |
@return The function stores resulting strains in the array strains |
of the element integration points. |
@return The function stores resulting strains in the array strains |
of the element integration points. |
JK, 11.6.2006 |
JK, 11.6.2006 |
*/ |
void plquadinterface::mainip_strains (long lcid, long eid, long ri, long ci, vector &r) |
{ |
329,7 → 326,7 |
matrix gm(ASTCKMAT(ncomp[0],ndofe)), d(ASTCKMAT(tncomp,tncomp)); |
vector eps(ASTCKVEC(tncomp)); |
fillm (0.0,gm); |
nullm (gm); |
Mt->give_node_coord2d(x,y,eid); |
Mt->give_elemnodes (eid,nodes); |
357,10 → 354,10 |
/** |
The function assembles strain-displacement (geometric) %matrix. |
@param gm - resulting geometric %matrix (output) |
@param x,y - nodal coordinates |
@param xi - natural coordinate of required integration point |
@param jac - Jacobian of transformation (output) |
@param[out] gm - resulting geometric %matrix |
@param[in] x,y - nodal coordinates |
@param[in] xi - natural coordinate of required integration point |
@param[out] jac - Jacobian of transformation |
@return The function returns resulting geometric %matrix in the parameter gm. |
377,9 → 374,9 |
dx = x[1] - x[0]; |
dy = y[1] - y[0]; |
fillm(0.0,gm); |
fillm(0.0,transf); |
fillm(0.0,pom); |
nullm(gm); |
nullm(transf); |
nullm(pom); |
double n1 = 0.5*(1-xi); |
double n2 = 0.5*(1+xi); |
428,32 → 425,32 |
/** |
The function computes stresses at element integration points |
The function computes stresses at element integration points |
@param lcid - load case id |
@param eid - element id |
@param[in] lcid - load case id |
@param[in] eid - element id |
@return The function stores resulting stresses in the stress array |
of the element integration points. |
TKo, 11.2012 |
@return The function stores resulting stresses in the stress array |
of the element integration points. |
Created by TKo, 11.2012 |
*/ |
void plquadinterface::res_mainip_stresses (long lcid, long eid) |
{ |
long ri,ci; |
ri=0; |
ci=0; |
compute_nlstress (lcid,eid,ri,ci); |
long ri, ci; |
ri = 0; |
ci = 0; |
compute_nlstress(lcid, eid, ri, ci); |
} |
/** |
Function computes correct stresses at integration points on element. |
The function computes actual stresses at integration points on element. |
@param lcid - number of load case |
@param eid - element id |
@param ri,ci - row and column indices |
@param[in] lcid - number of load case |
@param[in] eid - element id |
@param[in] ri,ci - row and column indices |
@return The function stores resulting stresses in the stress array |
of the element integration points. |
460,7 → 457,6 |
Created by Tomas Koudelka, 11.2008 |
*/ |
void plquadinterface::compute_nlstress (long /*lcid*/, long eid, long ri, long ci) |
{ |
long i,ipp; |
467,11 → 463,11 |
ipp=Mt->elements[eid].ipp[ri][ci]; |
for(i=0;i<intordsm[0][0];i++) |
for(i=0; i<intordsm[0][0]; i++) |
{ |
// computation of correct stresses |
if (Mp->strcomp==1) |
Mm->computenlstresses(ipp,Mm->ip[ipp]); |
Mm->computenlstresses(ipp, Mm->ip[ipp]); |
ipp++; |
} |
} |
479,13 → 475,13 |
/** |
Function computes internal forces in the case of geometrical linear computation. |
The function computes internal forces due to actual stresses in the global coordinate system. |
@param lcid - number of load case |
@param eid - element id |
@param ri,ci - row and column indices |
@param ifor - %vector of internal forces (output) |
@param x,y - %vectors of nodal coordinates |
@param[in] lcid - number of load case |
@param[in] eid - element id |
@param[in] ri,ci - row and column indices |
@param[out] ifor - %vector of internal forces |
@param[in] x,y - %vectors of nodal coordinates |
@return The function returns %vector of internal forces in the parameter ifor. |
506,11 → 502,12 |
/** |
Function computes resulting internal forces (from correct stresses) |
The function computes resulting internal forces from actual stresses. If required, the transformation |
to the nodal coordinate system is performed. |
@param lcid - number of load case |
@param eid - element id |
@param ifor - %vector of internal forces |
@param[in] lcid - number of load case |
@param[in] eid - element id |
@param[out] ifor - %vector of internal forces |
@return The function returns resulting %vector of internal forces in the parameter ifor. |
522,9 → 519,9 |
ivector nodes(ASTCKIVEC(nne)); |
vector v(ASTCKVEC(ndofe)), x(ASTCKVEC(nne)), y(ASTCKVEC(nne)); |
Mt->give_node_coord2d (x,y,eid); |
Mt->give_node_coord2d(x, y, eid); |
internal_forces (lcid,eid,0,0,ifor,x,y); |
internal_forces(lcid, eid, 0, 0, ifor, x, y); |
// transformation of nodal forces |
// (in the case of nodal coordinate systems) |
545,12 → 542,12 |
The function integrates selected quantity on the selected finite element. |
It results in nodal values. |
@param iq - type of integrated quantity (see alias.h) |
@param lcid - number of load case |
@param eid - element id |
@param ri,ci - row and column indices |
@param nv - nodal values |
@param x,y - nodal coordinates |
@param[in] iq - type of integrated quantity (see alias.h) |
@param[in] lcid - number of load case |
@param[in] eid - element id |
@param[in] ri,ci - row and column indices |
@param[out] nv - nodal values |
@param[in] x,y - nodal coordinates |
@return The function returns nodal values of the integrated quantity in the parameter nv. |
568,7 → 565,7 |
vector gp(ASTCKVEC(intordsm[0][0])); |
fillv(0.0,nv); |
nullv(nv); |
gauss_points (gp.a,w.a,intordsm[0][0]); |
/trunk/SIFEL/MEFEL/SRC/sequent.cpp |
---|
44,6 → 44,7 |
// long *tmp_adjip; |
// double *tmp_dist; |
vector coord(3),auxcoord(3); |
double *ipc; // array of ip coordinates, ipc+3*i = pointer to the array of 3 coordinates of the i-th int. point |
// maximum reached sizes of often reallocated arrays |
long adjelel_max = 0; |
long adjelelback_max = 0; |
61,9 → 62,27 |
Mt->nadjip = new long [totnip]; |
Mt->adjip = new long* [totnip]; |
Mt->dist = new double* [totnip]; |
ipc = new double[3*totnip]; |
memset(Mt->nadjip, 0, sizeof(*Mt->nadjip)*totnip); |
memset(Mt->adjip, 0, sizeof(*Mt->adjip)*totnip); |
memset(Mt->dist, 0, sizeof(*Mt->dist)*totnip); |
memset(ipc, 0, sizeof(*ipc)*3*totnip); |
// coordinates of integration points |
for(i=0; i<Gtm->ne; i++){ |
nb = Mt->give_nb (i); |
for (ii=0;ii<nb;ii++){ |
for (jj=0;jj<nb;jj++){ |
ipp=Mt->elements[i].ipp[ii][jj]; |
nip = Mt->give_nip (i,ii,jj); |
for (j=0;j<nip;j++){ |
makerefv(coord, ipc+3*ipp, 3); |
ipcoord(i, ipp, ii, jj, coord); |
ipp++; |
} |
} |
} |
} |
fprintf(stdout, "\n Adjacent integration points\n"); |
// max_nadjip = give_max_adjacip(); |
97,7 → 116,8 |
rlim = Mm->nonlocradius (ipp,nlmid); |
// coordinates of integration points |
ipcoord (i,ipp,ii,jj,coord); |
makerefv(coord, ipc+3*ipp, 3); |
//ipcoord (i,ipp,ii,jj,coord); |
// number of adjacent integration points determination |
Mt->nadjip[ipp]=0; |
116,7 → 136,7 |
// these integration points will be used in nonlocal models |
// the number of integration points are stored in the array Mt->nadjip[ipp] |
do{ |
in_dist (ipp,coord,adjelel,nae,rlim); |
in_dist (ipp,coord,ipc,adjelel,nae,rlim); |
reallocate(adjelelback, nae, adjelelback_max); |
170,7 → 190,7 |
} |
do{ |
dist (ipp,max_nadjip,coord,adjelel,nae,rlim); |
dist (ipp,max_nadjip,coord,ipc,adjelel,nae,rlim); |
reallocate(adjelelback, nae, adjelelback_max); |
212,6 → 232,7 |
delete [] adjelel; |
delete [] treatedel; |
delete [] change; |
delete [] ipc; |
// compression of arrays with adjacent integration points and distances |
/* for (ipp=0; ipp<totnip; ipp++) |
686,11 → 707,13 |
Function is used in adjacip. |
@param ipp - integration point pointer |
@param coord - coordinates of one of integration points |
@param adjelel - array of adjacent elements |
@param nae - number of adjacent elements |
@param rlim - limit distance |
@param[in] ipp - integration point pointer |
@param[in] coord - coordinates of one of integration points |
@param[in] ipc - array of coordinates of all integration points, |
ipc+3*i = pointer to array of 3 coordinates of i-th integration point |
@param[in,out] adjelel - array of adjacent elements |
@param[in] nae - number of adjacent elements |
@param[in] rlim - limit distance |
@return The function does not return anything. |
697,7 → 720,7 |
Created by JK, |
Modified by TKo, 04.2018 |
*/ |
void in_dist (long ipp,vector &coord,long *adjelel,long &nae,double rlim) |
void in_dist (long ipp, vector &coord, double *ipc, long *adjelel, long nae, double rlim) |
{ |
long i,j,ri,ci,lj,uj,ii,eid,nip,nb; |
double r; |
715,7 → 738,8 |
for (j=lj;j<uj;j++){ |
if (Mm->ip[j].hmt & 2){ |
// integration point number j contains nonlocal material model |
ipcoord (eid, j, ri, ci, auxcoord); |
makerefv(auxcoord, ipc+j*3, 3); |
//ipcoord (eid, j, ri, ci, auxcoord); |
r = length (coord, auxcoord); |
if (r<rlim){ |
Mt->nadjip[ipp]++; |
738,12 → 762,14 |
Function is used in adjacip. |
@param ipp - integration point pointer |
@param max_nadjip - maximum number of adjacent integration points |
@param coord - coordinates of one of integration points |
@param adjelel - array of adjacent elements |
@param nae - number of adjacent elements |
@param rlim - limit distance |
@param[in] ipp - integration point pointer |
@param[in] max_nadjip - maximum number of adjacent integration points |
@param[in] coord - coordinates of one of integration points |
@param[in] ipc - array of coordinates of all integration points, |
ipc+3*i = pointer to array of 3 coordinates of i-th integration point |
@param[in,out] adjelel - array of adjacent elements |
@param[in] nae - number of adjacent elements |
@param[in] rlim - limit distance |
@return The function does not return anything. |
750,7 → 776,7 |
Created by JK, |
Modified by TKo, 04.2018 |
*/ |
void dist (long ipp,long /*max_nadjip*/,vector &coord,long *adjelel,long &nae,double rlim) |
void dist (long ipp,long /*max_nadjip*/,vector &coord, double *ipc, long *adjelel, long nae, double rlim) |
{ |
long i,j,ri,ci,lj,uj,ii,eid,nip,nb; |
double r; |
769,7 → 795,8 |
for (j=lj;j<uj;j++){ |
if (Mm->ip[j].hmt & 2){ |
// integration point number j contains nonlocal material model |
ipcoord (eid,j,ri,ci,auxcoord); |
makerefv(auxcoord, ipc+j*3, 3); |
//ipcoord (eid,j,ri,ci,auxcoord); |
r = length (coord,auxcoord); |
if (r<rlim){ |
Mt->adjip[ipp][Mt->nadjip[ipp]]=j; |
/trunk/SIFEL/MEFEL/SRC/sequent.h |
---|
31,8 → 31,8 |
/// creates list of adjacent elements |
void newadjelel (long *adjelelback,long *adjelel,long &nae,long &nnae,long *treatedel,long &nte); |
/// computes number of adjacent integration points closer than given limit |
void in_dist (long ipp,vector &coord,long *adjelel,long &nae,double rlim); |
void in_dist (long ipp,vector &coord,double *ipc,long *adjelel,long nae,double rlim); |
/// computes distances of adjacent integration points closer than given limit |
void dist (long ipp,long max_nadjip,vector &coord,long *adjelel,long &nae,double rlim); |
void dist (long ipp,long max_nadjip,vector &coord,double *ipc,long *adjelel,long nae,double rlim); |
#endif |
/trunk/SIFEL/MEFEL/SRC/tensorcname.cpp |
---|
0,0 → 1,188 |
#include "tensorcname.h" |
#include "iotools.h" |
#include <stdlib.h> |
// strain component names for particular strain states |
const char*tensor_cname::strain_comp_names_bar[] = {"eps_x"}; |
const char*tensor_cname::strain_comp_names_plbeam[] = {"u_l", "w_l", "phi"}; |
const char*tensor_cname::strain_comp_names_spbeam[] = {"u_l", "v_l", "w_l", "phi_xl", "phi_yl", "phi_zl"}; |
const char*tensor_cname::strain_comp_names_plstr[] = {"eps_x", "eps_y", "gamma_xy", "eps_z"}; |
const char*tensor_cname::strain_comp_names_plcont[] = {"eps_n", "eps_tx", "eps_ty"}; |
const char*tensor_cname::strain_comp_names_platek[] = {"kappa_x", "kappa_y", "kappa_xy"}; |
const char*tensor_cname::strain_comp_names_plates[] = {"kappa_x", "kappa_y", "kappa_xy", "gamma_xz", "gamma_yz"}; |
const char*tensor_cname::strain_comp_names_axisym[] = {"eps_r", "eps_y", "eps_phi", "gamma_ry"}; |
const char*tensor_cname::strain_comp_names_shell[] = {"eps_x", "eps_y", "gamma_xy", "kappa_x", "kappa_y", "kappa_xy"}; |
const char*tensor_cname::strain_comp_names_space[] = {"eps_x", "eps_y", "eps_z", "gamma_yz", "gamma_xz", "gamma_xy"}; |
// stress component names for particular stress states |
const char*tensor_cname::stress_comp_names_bar[] = {"sig_x"}; |
const char*tensor_cname::stress_comp_names_plbeam[] = {"N", "V", "M"}; |
const char*tensor_cname::stress_comp_names_spbeam[] = {"N", "V_yl", "V_zl", "M_xl", "M_yl", "M_zl"}; |
const char*tensor_cname::stress_comp_names_plstr[] = {"sig_x", "sig_y", "tau_xy", "sig_z"}; |
const char*tensor_cname::stress_comp_names_plcont[] = {"sig_n", "tau_tx", "tau_ty"}; |
const char*tensor_cname::stress_comp_names_platek[] = {"m_x", "m_y", "m_xy"}; |
const char*tensor_cname::stress_comp_names_plates[] = {"m_x", "m_y", "m_xy", "q_xz", "q_yz"}; |
const char*tensor_cname::stress_comp_names_axisym[] = {"sig_r", "sig_y", "sig_phi", "tau_ry"}; |
const char*tensor_cname::stress_comp_names_shell[] = {"n_x", "n_y", "n_xy", "m_x", "m_y", "m_xy"}; |
const char*tensor_cname::stress_comp_names_space[] = {"sig_x", "sig_y", "sig_z", "tau_yz", "tau_xz", "tau_xy"}; |
// tensor component indices for particular strain/stress states |
const char*tensor_cname::tens_indices_bar[] = {"x"}; |
const char*tensor_cname::tens_indices_plbeam[] = {"x", "z", "phi"}; |
const char*tensor_cname::tens_indices_spbeam[] = {"xl", "yl", "zl", "xl", "yl", "zl"}; |
const char*tensor_cname::tens_indices_plstr[] = {"x", "y", "xy", "z"}; |
const char*tensor_cname::tens_indices_plcont[] = {"n", "tx", "ty"}; |
const char*tensor_cname::tens_indices_platek[] = {"x", "y", "xy"}; |
const char*tensor_cname::tens_indices_plates[] = {"x", "y", "xy", "xz", "yz"}; |
const char*tensor_cname::tens_indices_axisym[] = {"r", "y", "phi", "ry"}; |
const char*tensor_cname::tens_indices_shell[] = {"x", "y", "xy", "x", "y", "xy"}; |
const char*tensor_cname::tens_indices_space[] = {"x", "y", "z", "yz", "xz", "xy"}; |
/** |
The function returns pointer to string with indices for the given second order tensor component. |
@param[in] ssst - tensor stress/strain state |
@param[in] compid - required tensor component, tensor storage in Voigt notation is considered |
@return The function returns pointer to string representation of the given index of required |
tensor component. |
Created by Tomas Koudelka, 10.2023 |
*/ |
const char*tensor_cname::tens_indstr(strastrestate ssst, long compid) |
{ |
const char *ret = NULL; |
switch (ssst){ |
case bar: |
ret = tens_indices_bar[compid]; |
break; |
case planestress: |
case planestrain: |
ret = tens_indices_plstr[compid]; |
break; |
case planecontact: |
ret = tens_indices_plcont[compid]; |
break; |
case platek: |
ret = tens_indices_platek[compid]; |
break; |
case plates: |
ret = tens_indices_plates[compid]; |
break; |
case axisymm: |
ret = tens_indices_axisym[compid]; |
break; |
case shell: |
ret = tens_indices_shell[compid]; |
break; |
case spacestress: |
ret = tens_indices_space[compid]; |
break; |
default: |
print_err("unknown stress/strain state %d is required", __FILE__, __LINE__, __func__, int(ssst)); |
abort(); |
} |
return ret; |
} |
/** |
The function returns pointer to string with label for the given strain tensor component in Voigt notation. |
@param[in] ssst - tensor strain state |
@param[in] compid - required tensor component, tensor storage in Voigt notation is considered |
@return The function returns pointer to string representation of the required strain tensor component in Voigt notation. |
Created by Tomas Koudelka, 10.2023 |
*/ |
const char*tensor_cname::strain_cmpstr(strastrestate ssst, long compid) |
{ |
const char *ret = NULL; |
switch (ssst){ |
case bar: |
ret = strain_comp_names_bar[compid]; |
break; |
case planestress: |
case planestrain: |
ret = strain_comp_names_plstr[compid]; |
break; |
case planecontact: |
ret = strain_comp_names_plcont[compid]; |
break; |
case platek: |
ret = strain_comp_names_platek[compid]; |
break; |
case plates: |
ret = strain_comp_names_plates[compid]; |
break; |
case axisymm: |
ret = strain_comp_names_axisym[compid]; |
break; |
case shell: |
ret = strain_comp_names_shell[compid]; |
break; |
case spacestress: |
ret = strain_comp_names_space[compid]; |
break; |
default: |
print_err("unknown strain state %d is required", __FILE__, __LINE__, __func__, int(ssst)); |
abort(); |
} |
return ret; |
} |
/** |
The function returns pointer to string with label for the given stress tensor component in Voigt notation. |
@param[in] ssst - tensor stress state |
@param[in] compid - required tensor component, tensor storage in Voigt notation is considered |
@return The function returns pointer to string representation of the required stress tensor component in Voigt notation. |
Created by Tomas Koudelka, 10.2023 |
*/ |
const char*tensor_cname::stress_cmpstr(strastrestate ssst, long compid) |
{ |
const char *ret = NULL; |
switch (ssst){ |
case bar: |
ret = stress_comp_names_bar[compid]; |
break; |
case planestress: |
case planestrain: |
ret = stress_comp_names_plstr[compid]; |
break; |
case planecontact: |
ret = stress_comp_names_plcont[compid]; |
break; |
case platek: |
ret = stress_comp_names_platek[compid]; |
break; |
case plates: |
ret = stress_comp_names_plates[compid]; |
break; |
case axisymm: |
ret = stress_comp_names_axisym[compid]; |
break; |
case shell: |
ret = stress_comp_names_shell[compid]; |
break; |
case spacestress: |
ret = stress_comp_names_space[compid]; |
break; |
default: |
print_err("unknown stress state %d is required", __FILE__, __LINE__, __func__, int(ssst)); |
abort(); |
} |
return ret; |
} |
/trunk/SIFEL/MEFEL/SRC/tensorcname.h |
---|
0,0 → 1,95 |
#ifndef TENSORCNAME |
#define TENSORCNAME |
#include "alias.h" |
/** |
Class that defines stress/strain tensor component names and |
index names of a general tensors for particular stress/strain states. |
Created by Tomas Koudelka, 10.2023 |
*/ |
class tensor_cname |
{ |
public: |
// |
// the second order tensor indices for particular stress/strain states |
// |
/// tensor indices for uniaxial stress/strain state |
static const char*tens_indices_bar[]; |
/// tensor indices for stress/strain arrays on 2D beam |
static const char*tens_indices_plbeam[]; |
/// tensor indices for stress/strain arrays on 3D beam |
static const char*tens_indices_spbeam[]; |
/// tensor indices for plane stress/strain state |
static const char*tens_indices_plstr[]; |
/// tensor indices for plane contact stress/strain state |
static const char*tens_indices_plcont[]; |
/// tensor indices for stress/strain state in Kirchoff's plates |
static const char*tens_indices_platek[]; |
/// tensor indices for stress/strain state in Mindlin's plates |
static const char*tens_indices_plates[]; |
/// tensor indices for axisymmetric stress/strain state |
static const char*tens_indices_axisym[]; |
/// tensor indices for stress/strain state in shells |
static const char*tens_indices_shell[]; |
/// tensor indices for fully 3D stress/strain state |
static const char*tens_indices_space[]; |
// |
// strain tensor component names for particular strain states, Voigt notation is considered |
// |
/// strain tensor component names for uniaxial strain state |
static const char*strain_comp_names_bar[]; |
/// strain tensor component names of strains for 2D beams |
static const char*strain_comp_names_plbeam[]; |
/// strain tensor component names of strains for 3D beams |
static const char*strain_comp_names_spbeam[]; |
/// strain tensor component names for plane strain state |
static const char*strain_comp_names_plstr[]; |
/// strain tensor component names for plane constact strain state |
static const char*strain_comp_names_plcont[]; |
/// curvature component names for Krichof's plate |
static const char*strain_comp_names_platek[]; |
/// curvature nad shear strain component names for Mindlin's plate |
static const char*strain_comp_names_plates[]; |
/// strain tensor component names for axisymmetric strain state |
static const char*strain_comp_names_axisym[]; |
/// strain tensor component names for strain state on shells |
static const char*strain_comp_names_shell[]; |
/// strain tensor component names for fully 3D strain state |
static const char*strain_comp_names_space[]; |
// |
// stress tensor component names for particular stress states, Voigt notation is considered |
// |
/// stress tensor component names for uniaxial stress state |
static const char*stress_comp_names_bar[]; |
/// strain tensor component names of strains for 2D beams |
static const char*stress_comp_names_plbeam[]; |
/// strain tensor component names of strains for 3D beams |
static const char*stress_comp_names_spbeam[]; |
/// stress tensor component names for plane stress state |
static const char*stress_comp_names_plstr[]; |
/// stress tensor component names for plane constact stress state |
static const char*stress_comp_names_plcont[]; |
/// stress resultant component names for Krichof's plate |
static const char*stress_comp_names_platek[]; |
/// stress resultant component names for Mindlin's plate |
static const char*stress_comp_names_plates[]; |
/// stress tensor component names for axisymmetric stress state |
static const char*stress_comp_names_axisym[]; |
/// stress resultant component names on shells |
static const char*stress_comp_names_shell[]; |
/// stress tensor component names for fully 3D stress state |
static const char*stress_comp_names_space[]; |
/// returns pointer to string with indices for the given second order tensor component |
static const char* tens_indstr(strastrestate ssst, long compid); |
/// returns pointer to string with label for the given second order stress tensor component |
static const char* stress_cmpstr(strastrestate ssst, long compid); |
/// returns pointer to string with label for the given second order strain tensor component |
static const char* strain_cmpstr(strastrestate ssst, long compid); |
}; |
#endif |
/trunk/SIFEL/MEFEL/SRC/tetralattice.cpp |
---|
1,1032 → 1,1032 |
#include "tetralattice.h" |
#include "global.h" |
#include "probdesc.h" |
#include "mechtop.h" |
#include "mechmat.h" |
#include "mechcrsec.h" |
#include "globmat.h" |
#include "genfile.h" |
#include "intpoints.h" |
#include "node.h" |
#include "element.h" |
#include "loadcase.h" |
#include "mathem.h" |
tetralattice::tetralattice(void) { |
long i; |
// number of DOFs per node |
ndof = 6; |
// number nodes on element |
nne = 4; |
// number of DOFs on element |
ndofe = nne * ndof; |
// number of strain/stress components |
tncomp = 3; |
// number of functions approximated |
napfun = 3; |
// order of numerical integration of mass matrix |
intordmm = 1; |
// number of edges on element |
ned = 6; |
// number of nodes on one edge |
nned = 2; |
// number of surfaces |
nsurf = 4; |
// number of nodes on one surface |
nnsurf = 3; |
// order of numerical integration on element edges (boundaries) |
intordb = 3; |
// strain/stress state |
ssst = spacestress; |
// number of blocks (parts of geometric matrix) |
nb = 1; |
// number of strain/stress components |
ncomp = new long[nb]; |
ncomp[0] = 3; |
// cumulative number of components approximated |
cncomp = new long[nb]; |
cncomp[0] = 0; |
// number of integration points = 12 (fixed) |
tnip = 12; |
nip = new long* [nb]; |
for (i = 0; i < nb; i++) { |
nip[i] = new long[nb]; |
} |
nip[0][0] = tnip; |
// nodes belonging to edge |
nbe[0][0] = 0; nbe[0][1] = 1; |
nbe[1][0] = 0; nbe[1][1] = 2; |
nbe[2][0] = 1; nbe[2][1] = 2; |
nbe[3][0] = 1; nbe[3][1] = 3; |
nbe[4][0] = 2; nbe[4][1] = 3; |
nbe[5][0] = 0; nbe[5][1] = 3; |
// edge belonging to facet |
ebf[0] = 0; |
ebf[1] = 0; |
ebf[2] = 1; |
ebf[3] = 1; |
ebf[4] = 2; |
ebf[5] = 2; |
ebf[6] = 3; |
ebf[7] = 3; |
ebf[8] = 4; |
ebf[9] = 4; |
ebf[10] = 5; |
ebf[11] = 5; |
// nodes beloging to surface - surfaces indexed according to the oposite node |
nbs[0][0] = 1; nbs[0][1] = 2; nbs[0][2] = 3; // surface oposite node 0 |
nbs[1][0] = 0; nbs[1][1] = 3; nbs[1][2] = 2; // surface oposite node 1 |
nbs[2][0] = 0; nbs[2][1] = 1; nbs[2][2] = 3; // surface oposite node 2 |
nbs[3][0] = 0; nbs[3][1] = 2; nbs[3][2] = 1; // surface oposite node 3 |
// edges beloging to surface (with accordance to nbe) |
ebs[0][0] = 2; ebs[0][1] = 4; ebs[0][2] = 3; |
ebs[1][0] = 5; ebs[1][1] = 4; ebs[1][2] = 1; |
ebs[2][0] = 0; ebs[2][1] = 3; ebs[2][2] = 5; |
ebs[3][0] = 1; ebs[3][1] = 2; ebs[3][2] = 0; |
// nodes oposite the edge-node (surfacewise) |
enbs[0][0] = 4; enbs[0][1] = 3; enbs[0][2] = 2; |
enbs[1][0] = 4; enbs[1][1] = 1; enbs[1][2] = 5; |
enbs[2][0] = 3; enbs[2][1] = 5; enbs[2][2] = 0; |
enbs[3][0] = 2; enbs[3][1] = 0; enbs[3][2] = 1; |
// surface belonging to facet |
sbf[0] = 2; |
sbf[1] = 3; |
sbf[2] = 1; |
sbf[3] = 3; |
sbf[4] = 0; |
sbf[5] = 3; |
sbf[6] = 0; |
sbf[7] = 2; |
sbf[8] = 0; |
sbf[9] = 1; |
sbf[10] = 1; |
sbf[11] = 2; |
/// nodes belonging to facet |
for (i = 0; i < tnip; i++) { |
nbf[i][0] = nbe[ebf[i]][0]; |
nbf[i][1] = nbe[ebf[i]][1]; |
} |
} |
tetralattice::~tetralattice(void) { |
long i; |
for (i = 0; i < nb; i++) { |
delete[] nip[i]; |
delete[] intordsm[i]; |
} |
delete[] nip; |
delete[] intordsm; |
delete[] cncomp; |
delete[] ncomp; |
} |
/** |
function creates facets in tetrahedral element used by lattice discrete particle model |
@param eid - element ID |
JV, 2.2021 |
*/ |
void tetralattice::create_facets(long eid, matrix& mm) { |
// lambda expresion for length |
auto length = [](double x0, double y0, double z0, double x1, double y1, double z1) -> double { |
return sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0) + (z1 - z0) * (z1 - z0)); |
}; |
// lambda expression for moments of inertia of tetrahedron to the first node |
auto moi = [](double x0, double y0, double z0, double x1, double y1, double z1, double x2, double y2, double z2, double x3, double y3, double z3, double mass, double& ixx, double& iyy, double& izz, double& iyz, double& ixz, double& ixy) { |
double dumx, dumy, dumz, cx, cy, cz, dx, dy, dz; |
dumx = x0 * x0 + x0 * x1 + x1 * x1 + x0 * x2 + x1 * x2 + x2 * x2 + x0 * x3 + x1 * x3 + x2 * x3 + x3 * x3; |
dumy = y0 * y0 + y0 * y1 + y1 * y1 + y0 * y2 + y1 * y2 + y2 * y2 + y0 * y3 + y1 * y3 + y2 * y3 + y3 * y3; |
dumz = z0 * z0 + z0 * z1 + z1 * z1 + z0 * z2 + z1 * z2 + z2 * z2 + z0 * z3 + z1 * z3 + z2 * z3 + z3 * z3; |
cx = 0.25 * (x0 + x1 + x2 + x3); |
cy = 0.25 * (y0 + y1 + y2 + y3); |
cz = 0.25 * (z0 + z1 + z2 + z3); |
dx = cx - x0; |
dy = cy - y0; |
dz = cz - z0; |
ixx = 0.1 * mass * (dumy + dumz) + mass * (dy * dy + dz * dz); |
iyy = 0.1 * mass * (dumx + dumz) + mass * (dx * dx + dz * dz); |
izz = 0.1 * mass * (dumx + dumy) + mass * (dx * dx + dy * dy); |
iyz = 0.05 * mass * (2.0 * y0 * z0 + y1 * z0 + y2 * z0 + y3 * z0 + y0 * z1 + 2.0 * y1 * z1 + y2 * z1 + y3 * z1 + |
y0 * z2 + y1 * z2 + 2.0 * y2 * z2 + y3 * z2 + y0 * z3 + y1 * z3 + y2 * z3 + 2.0 * y3 * z3) + |
mass * dy * dz; |
ixz = 0.05 * mass * (2.0 * x0 * z0 + x1 * z0 + x2 * z0 + x3 * z0 + x0 * z1 + 2.0 * x1 * z1 + x2 * z1 + x3 * z1 + |
x0 * z2 + x1 * z2 + 2.0 * x2 * z2 + x3 * z2 + x0 * z3 + x1 * z3 + x2 * z3 + 2.0 * x3 * z3) + |
mass * dx * dz; |
ixy = 0.05 * mass * (2.0 * x0 * y0 + x1 * y0 + x2 * y0 + x3 * y0 + x0 * y1 + 2.0 * x1 * y1 + x2 * y1 + x3 * y1 + |
x0 * y2 + x1 * y2 + 2.0 * x2 * y2 + x3 * y2 + x0 * y3 + x1 * y3 + x2 * y3 + 2.0 * x3 * y3) + |
mass * dx * dy; |
}; |
// according to: Lattice Discrete Particle Model (LDPM) for failure behavior of concrete. I: Theory, Gianluca Cusatis, Daniele Pelessone, Andrea Mencarelli |
long i, j, ipp, n0, n1, ne, ns, dumn; |
double dum1, dum2, dum3; |
double fnx, fny, fnz, flx, fly, flz, fmx, fmy, fmz; |
double vol, density, mass, ixx, iyy, izz, iyz, ixz, ixy; |
bool orderNCES; |
vector x(ASTCKVEC(nne)), y(ASTCKVEC(nne)), z(ASTCKVEC(nne)); // nodes coordinates |
vector r(ASTCKVEC(nne)), ele(ASTCKVEC(ned)); // node radius, element edge length |
// new nodes |
vector enx(ASTCKVEC(ned)), eny(ASTCKVEC(ned)), enz(ASTCKVEC(ned)); // edge nodes |
vector snx(ASTCKVEC(ned)), sny(ASTCKVEC(ned)), snz(ASTCKVEC(ned)); // surface nodes |
double tx, ty, tz; // element center node |
vector fx(ASTCKVEC(tnip)), fy(ASTCKVEC(tnip)), fz(ASTCKVEC(tnip)); // facet centroids |
vector fa(ASTCKVEC(tnip)); // projected facet area |
ivector nodes(ASTCKIVEC(nne)); // element nodes IDs |
vector dens(ASTCKVEC(nne)); // nodal densities |
//matrix mm(ASTCKMAT(ndofe, ndofe)); |
// cleaning of mass matrix |
nullm(mm); |
// node IDs |
Mt->give_elemnodes(eid, nodes); |
// nodal densities |
Mc->give_density(eid, nodes, dens); |
// node coordinates |
Mt->give_node_coord3d(x, y, z, eid); |
// all node densities are the same |
density = dens[0]; |
// particle (node) radii |
for (i = 0; i < nne; i++) { |
r[i] = Mt->node_radius[nodes[i]]; |
} |
// edge mid-nodes - E12, E13, E14, E23, E24, E34 |
for (i = 0; i < ned; i++) { |
n0 = nbe[i][0]; |
n1 = nbe[i][1]; |
// edge lengths |
ele[i] = length(x[n0], y[n0], z[n0], x[n1], y[n1], z[n1]); |
dum1 = ele[i] - r[n0] - r[n1]; // gap between particles |
if (dum1 < 0.0) { |
print_err("Wrong 3D tetrahedral lattice element number %ld, negative gap! gap = %e", __FILE__, __LINE__, __func__, eid + 1, dum1); |
abort(); |
} |
dum2 = (r[n0] + 0.5 * dum1) / ele[i]; |
enx[i] = x[n0] + dum2 * (x[n1] - x[n0]); |
eny[i] = y[n0] + dum2 * (y[n1] - y[n0]); |
enz[i] = z[n0] + dum2 * (z[n1] - z[n0]); |
} |
// element surface nodes - F1, F2, F3, F4 |
for (i = 0; i < nsurf; i++) { |
snx[i] = sny[i] = snz[i] = 0.0; |
for (j = 0; j < nnsurf; j++) { |
n0 = nbs[i][j]; |
n1 = enbs[i][j]; |
dum3 = length(x[n0], y[n0], z[n0], enx[n1], eny[n1], enz[n1]); |
dum1 = dum3 - r[n0]; // gap between particle and edge |
if (dum1 < 0.0) { |
print_err("Wrong 3D tetrahedral lattice element number %ld, negative gap! gap = %e", __FILE__, __LINE__, __func__, eid + 1, dum1); |
abort(); |
} |
dum2 = (r[n0] + 0.5 * dum1) / dum3; |
snx[i] += x[n0] + dum2 * (enx[n1] - x[n0]); |
sny[i] += y[n0] + dum2 * (eny[n1] - y[n0]); |
snz[i] += z[n0] + dum2 * (enz[n1] - z[n0]); |
} |
snx[i] /= nnsurf; |
sny[i] /= nnsurf; |
snz[i] /= nnsurf; |
} |
// element centroid - t |
tx = ty = tz = 0.0; |
for (i = 0; i < nsurf; i++) { |
// surfaces indexed according to the oposite node |
n0 = n1 = i; |
dum3 = length(x[n0], y[n0], z[n0], snx[n1], sny[n1], snz[n1]); |
dum1 = dum3 - r[n0]; // gap between particle and edge |
if (dum1 < 0.0) { |
print_err("Wrong 3D tetrahedral lattice element number %ld, negative gap! gap = %e", __FILE__, __LINE__, __func__, eid + 1, dum1); |
abort(); |
} |
dum2 = (r[n0] + 0.5 * dum1) / dum3; |
tx += x[n0] + dum2 * (snx[n1] - x[n0]); |
ty += y[n0] + dum2 * (sny[n1] - y[n0]); |
tz += z[n0] + dum2 * (snz[n1] - z[n0]); |
} |
tx /= nsurf; |
ty /= nsurf; |
tz /= nsurf; |
// facets - centroid + area - 12x |
nullm(mm); |
ipp = Mt->elements[eid].ipp[0][0]; |
for (i = 0; i < tnip; i++) { |
ne = ebf[i]; // edge node |
ns = sbf[i]; // surface node |
n0 = nbf[i][0]; // first edge node |
n1 = nbf[i][1]; // second edge node |
// local coordinate system of the projected facet - alligned with the edge, order of axes N-L-M |
fnx = (x[n1] - x[n0]) / ele[ne]; |
fny = (y[n1] - y[n0]) / ele[ne]; |
fnz = (z[n1] - z[n0]) / ele[ne]; |
// facet centroid |
fx[i] = (enx[ne] + snx[ns] + tx) / 3.; |
fy[i] = (eny[ne] + sny[ns] + ty) / 3.; |
fz[i] = (enz[ne] + snz[ns] + tz) / 3.; |
// fl,fm - vectors in the facet plane |
flx = enx[ne] - tx; |
fly = eny[ne] - ty; |
flz = enz[ne] - tz; |
fmx = snx[ns] - tx; |
fmy = sny[ns] - ty; |
fmz = snz[ns] - tz; |
// cross product - fl x fm, vector length = twice the facet area |
dum1 = fly * fmz - flz * fmy; |
dum2 = flz * fmx - flx * fmz; |
dum3 = flx * fmy - fly * fmx; |
// projected facet area into the direction of perpedincular to the edge |
// scalar product of the facet area vector and edge unit vector |
fa[i] = fabs(0.5 * (dum1 * fnx + dum2 * fny + dum3 * fnz)); |
// local coordinate system of the projected facet - remaining axis, order of axes N-L-M |
// fl - vector perpedincular to fn by means of already defined vector fm (we could use any random vector instead of fm) |
flx = fmy * fnz - fmz * fny; |
fly = fmz * fnx - fmx * fnz; |
flz = fmx * fny - fmy * fnx; |
dum1 = sqrt(flx * flx + fly * fly + flz * flz); |
flx /= dum1; |
fly /= dum1; |
flz /= dum1; |
// remaining axis m => fm vector perpedincular to fn and fl vectors |
fmx = fny * flz - fnz * fly; |
fmy = fnz * flx - fnx * flz; |
fmz = fnx * fly - fny * flx; |
// volume and moments of inertia |
// tetrahedron nodeOfOriginalElement-centroid(t)-edgeNode(en)-surfaceNode(sn) |
for (j = 0; j < 2; j++) { |
dumn = n0; |
if (j == 1) dumn = n1; |
vol = tetVol(x[dumn], y[dumn], z[dumn], tx, ty, tz, enx[ne], eny[ne], enz[ne], snx[ns], sny[ns], snz[ns]); |
orderNCES = true; |
if (vol < 0.0) { |
// tetrahedron nodeOfOriginalElement-edgeNode(en)-centroid(t)-surfaceNode(sn) |
vol = tetVol(x[dumn], y[dumn], z[dumn], enx[ne], eny[ne], enz[ne], tx, ty, tz, snx[ns], sny[ns], snz[ns]); |
orderNCES = false; |
} |
if (vol <= Mp->zero) { |
print_err("Wrong 3D tetrahedral lattice element number %ld, zero volume! vol = %e", __FILE__, __LINE__, __func__, eid + 1, vol); |
abort(); |
} |
// @todo get density |
mass = vol * density; |
if (orderNCES) { |
moi(x[dumn], y[dumn], z[dumn], tx, ty, tz, enx[ne], eny[ne], enz[ne], snx[ns], sny[ns], snz[ns], mass, ixx, iyy, izz, iyz, ixz, ixy); |
} else { |
moi(x[dumn], y[dumn], z[dumn], enx[ne], eny[ne], enz[ne], tx, ty, tz, snx[ns], sny[ns], snz[ns], mass, ixx, iyy, izz, iyz, ixz, ixy); |
} |
// mass |
mm[dumn * 6 + 0][dumn * 6 + 0] += mass; |
mm[dumn * 6 + 1][dumn * 6 + 1] += mass; |
mm[dumn * 6 + 2][dumn * 6 + 2] += mass; |
// inertia |
mm[dumn * 6 + 3][dumn * 6 + 3] += ixx; |
mm[dumn * 6 + 4][dumn * 6 + 4] += iyy; |
mm[dumn * 6 + 5][dumn * 6 + 5] += izz; |
mm[dumn * 6 + 3][dumn * 6 + 4] -= ixy; |
mm[dumn * 6 + 3][dumn * 6 + 5] -= ixz; |
mm[dumn * 6 + 4][dumn * 6 + 5] -= iyz; |
mm[dumn * 6 + 4][dumn * 6 + 3] -= ixy; |
mm[dumn * 6 + 5][dumn * 6 + 3] -= ixz; |
mm[dumn * 6 + 5][dumn * 6 + 4] -= iyz; |
// additonal momentum |
// tetrahedron centroid |
dum1 = 0.25 * (x[dumn] + tx + enx[ne] + snx[ns]); |
dum2 = 0.25 * (y[dumn] + ty + eny[ne] + sny[ns]); |
dum3 = 0.25 * (z[dumn] + tz + enz[ne] + snz[ns]); |
mm[dumn * 6 + 0][dumn * 6 + 4] += mass * (z[dumn] - dum3); |
mm[dumn * 6 + 0][dumn * 6 + 5] -= mass * (y[dumn] - dum2); |
mm[dumn * 6 + 1][dumn * 6 + 3] -= mass * (z[dumn] - dum3); |
mm[dumn * 6 + 1][dumn * 6 + 5] += mass * (x[dumn] - dum1); |
mm[dumn * 6 + 2][dumn * 6 + 3] += mass * (y[dumn] - dum2); |
mm[dumn * 6 + 2][dumn * 6 + 4] -= mass * (x[dumn] - dum1); |
mm[dumn * 6 + 4][dumn * 6 + 0] += mass * (z[dumn] - dum3); |
mm[dumn * 6 + 5][dumn * 6 + 0] -= mass * (y[dumn] - dum2); |
mm[dumn * 6 + 3][dumn * 6 + 1] -= mass * (z[dumn] - dum3); |
mm[dumn * 6 + 5][dumn * 6 + 1] += mass * (x[dumn] - dum1); |
mm[dumn * 6 + 3][dumn * 6 + 2] += mass * (y[dumn] - dum2); |
mm[dumn * 6 + 4][dumn * 6 + 2] -= mass * (x[dumn] - dum1); |
} |
/*---------- DATA SAVING ----------*/ |
// save values on IP |
Mm->ip[ipp].other[0] = fx[i]; |
Mm->ip[ipp].other[1] = fy[i]; |
Mm->ip[ipp].other[2] = fz[i]; |
// local coordinates |
Mm->ip[ipp].other[3] = fnx; |
Mm->ip[ipp].other[4] = fny; |
Mm->ip[ipp].other[5] = fnz; |
Mm->ip[ipp].other[6] = flx; |
Mm->ip[ipp].other[7] = fly; |
Mm->ip[ipp].other[8] = flz; |
Mm->ip[ipp].other[9] = fmx; |
Mm->ip[ipp].other[10] = fmy; |
Mm->ip[ipp].other[11] = fmz; |
// facet area |
Mm->ip[ipp].other[12] = fa[i]; |
// edge length |
Mm->ip[ipp].other[13] = ele[ebf[i]]; |
// volumetric strain |
Mm->ip[ipp].other[14] = 0.0; |
ipp++; |
} |
// diagonalization of the mass matrix |
// @todo |
//diagonalization (mm); |
} |
/** |
function assembles strain-displacement (geometric) %matrix for all facets in tetrahedral element |
vector of strains has following ordering eps=(e_N, e_L, e_M) |
geometric %matrix size is (tncomp*tnip, 2*ndof) |
@param eid - element ID |
@param gm - geometric %matrix |
JV, 2.2021 |
*/ |
void tetralattice::geom_matrix(long eid, matrix& gm) { |
long i, ri, ipp, n0, n1; |
double dum1; |
double* a; |
double fx, fy, fz; |
double fnx, fny, fnz, flx, fly, flz, fmx, fmy, fmz; |
double A04_0, A05_0, A15_0, A04_1, A05_1, A15_1; |
vector x(ASTCKVEC(nne)), y(ASTCKVEC(nne)), z(ASTCKVEC(nne)); // nodes coordinates |
// node coordinates |
Mt->give_node_coord3d(x, y, z, eid); |
nullm(gm); |
ipp = Mt->elements[eid].ipp[0][0]; |
ri = 0; |
for (i = 0; i < tnip; i++) { |
n0 = nbf[i][0]; // first edge node |
n1 = nbf[i][1]; // second edge node |
dum1 = 1. / Mm->ip[ipp].other[13]; // 1. / edge length |
fx = Mm->ip[ipp].other[0]; |
fy = Mm->ip[ipp].other[1]; |
fz = Mm->ip[ipp].other[2]; |
fnx = Mm->ip[ipp].other[3] * dum1; |
fny = Mm->ip[ipp].other[4] * dum1; |
fnz = Mm->ip[ipp].other[5] * dum1; |
flx = Mm->ip[ipp].other[6] * dum1; |
fly = Mm->ip[ipp].other[7] * dum1; |
flz = Mm->ip[ipp].other[8] * dum1; |
fmx = Mm->ip[ipp].other[9] * dum1; |
fmy = Mm->ip[ipp].other[10] * dum1; |
fmz = Mm->ip[ipp].other[11] * dum1; |
A04_0 = (fz - z[n0]); |
A05_0 = (y[n0] - fy); |
A15_0 = (fx - x[n0]); |
A04_1 = (fz - z[n1]); |
A05_1 = (y[n1] - fy); |
A15_1 = (fx - x[n1]); |
// eps_N |
a = gm[ri++]; |
a[0] = -fnx; |
a[1] = -fny; |
a[2] = -fnz; |
a[3] = fny * A04_0 + fnz * A05_0; |
a[4] = -fnx * A04_0 + fnz * A15_0; |
a[5] = -fnx * A05_0 - fny * A15_0; |
a[6] = fnx; |
a[7] = fny; |
a[8] = fnz; |
a[9] = -fny * A04_1 - fnz * A05_1; |
a[10] = fnx * A04_1 - fnz * A15_1; |
a[11] = fnx * A05_1 + fny * A15_1; |
// eps_L |
a = gm[ri++]; |
a[0] = -flx; |
a[1] = -fly; |
a[2] = -flz; |
a[3] = fly * A04_0 + flz * A05_0; |
a[4] = -flx * A04_0 + flz * A15_0; |
a[5] = -flx * A05_0 - fly * A15_0; |
a[6] = flx; |
a[7] = fly; |
a[8] = flz; |
a[9] = -fly * A04_1 - flz * A05_1; |
a[10] = flx * A04_1 - flz * A15_1; |
a[11] = flx * A05_1 + fly * A15_1; |
// eps_M |
a = gm[ri++]; |
a[0] = -fmx; |
a[1] = -fmy; |
a[2] = -fmz; |
a[3] = fmy * A04_0 + fmz * A05_0; |
a[4] = -fmx * A04_0 + fmz * A15_0; |
a[5] = -fmx * A05_0 - fmy * A15_0; |
a[6] = fmx; |
a[7] = fmy; |
a[8] = fmz; |
a[9] = -fmy * A04_1 - fmz * A05_1; |
a[10] = fmx * A04_1 - fmz * A15_1; |
a[11] = fmx * A05_1 + fmy * A15_1; |
ipp++; |
} |
} |
/** |
function computes internal forces |
@param lcid - load case id |
@param eid - element id |
@param ri,ci - row and column indices |
@param ifor - vector of internal forces |
JV 2.2021 |
*/ |
void tetralattice::internal_forces(long lcid, long eid, long ri, long ci, vector& ifor) { |
integratedquant iq; |
iq = locstress; |
// computation of stresses |
compute_nlstress(lcid, eid, ri, ci); // stresses on facets |
// integration of stresses over the element |
elem_integration(iq, lcid, eid, ri, ci, ifor); |
} |
/** |
The function integrates selected stress type quantity over the finite element, i.e. |
it performs \int_{\Omega} \mbf{B}^T \mbf{\sigma} d\Omega. It results in nodal values. |
@param iq - type of integrated quantity (see alias.h) |
@param lcid - number of load case |
@param eid - element id |
@param ri,ci - row and column indices |
@param nv - nodal values (output) |
@return The function returns nodal values calculated in the %vector nv |
JV 2.2021 |
*/ |
void tetralattice::elem_integration(integratedquant iq, long lcid, long eid, long /*ri*/, long /*ci*/, vector& nv) { |
long i, ii, k, l, n0, n1, ipp; |
double vol, ipv0, ipv1, ipv2; |
double* a0, * a1, * a2, * b; |
matrix gm(ASTCKMAT(tncomp * tnip, 2 * ndof)); // geoetric matrix |
vector ipv(ASTCKVEC(tncomp)); // itegration point values |
nullv(nv); |
ipp = Mt->elements[eid].ipp[0][0]; |
geom_matrix(eid, gm); |
ii = 0; |
for (i = 0; i < tnip; i++) { |
n0 = nbf[i][0]; // first edge node |
n1 = nbf[i][1]; // second edge node |
vol = Mm->ip[ipp].other[12] * Mm->ip[ipp].other[13]; // facet area * edge length |
Mm->givequantity(iq, lcid, ipp, cncomp[0], ipv); // function assembles required quantity at integration point |
ipv0 = ipv[0]; |
ipv1 = ipv[1]; |
ipv2 = ipv[2]; |
a0 = gm[ii++]; // first row of corresponding B matrix |
a1 = gm[ii++]; // second row of corresponding B matrix |
a2 = gm[ii++]; // third row of corresponding B matrix |
// first node |
b = nv.a + n0 * ndof; |
for (k = 0; k < ndof; k++) { |
b[k] += vol * (ipv0 * a0[k] + ipv1 * a1[k] + ipv2 * a2[k]); |
} |
// second node |
b = nv.a + n1 * ndof; |
for (k = ndof, l = 0; l < ndof; k++, l++) { |
b[l] += vol * (ipv0 * a0[k] + ipv1 * a1[k] + ipv2 * a2[k]); |
} |
ipp++; |
} |
} |
/** |
The function integrates selected stress type quantity over the finite element, i.e. |
it performs \int_{\Omega} \mbf{B}^T \mbf{\sigma} d\Omega. It results in nodal values. |
@param iq - type of integrated quantity (see alias.h) |
@param lcid - number of load case |
@param eid - element id |
@param ri,ci - row and column indices |
@param nv - nodal values (output) |
@return The function returns nodal values calculated in the %vector nv |
JV 2.2021 |
*/ |
void tetralattice::elem_integration2(integratedquant /*iq*/, long /*lcid*/, long eid, long /*ri*/, long /*ci*/, vector& nv, intpoints *ip) { |
long i, ii, k, l, n0, n1, ipp; |
double vol, ipv0, ipv1, ipv2; |
double* a0, * a1, * a2, * b; |
matrix gm(ASTCKMAT(tncomp * tnip, 2 * ndof)); // geoetric matrix |
vector ipv(ASTCKVEC(tncomp)); // itegration point values |
nullv(nv); |
ipp = Mt->elements[eid].ipp[0][0]; |
geom_matrix(eid, gm); |
ii = 0; |
for (i = 0; i < tnip; i++) { |
n0 = nbf[i][0]; // first edge node |
n1 = nbf[i][1]; // second edge node |
// toto ne |
//vol = Mm->ip[ipp].other[12] * Mm->ip[ipp].other[13]; // facet area * edge length |
// neco takoveho |
vol = ip[i].other[12] * ip[i].other[13]; // facet area * edge length |
// toto ne |
//Mm->givequantity(iq, lcid, ipp, cncomp[0], ipv); // function assembles required quantity at integration point |
//ipv0 = ipv[0]; |
//ipv1 = ipv[1]; |
//ipv2 = ipv[2]; |
ipv0 = ip[i].stress[0]; |
ipv1 = ip[i].stress[1]; |
ipv2 = ip[i].stress[2]; |
a0 = gm[ii++]; // first row of corresponding B matrix |
a1 = gm[ii++]; // second row of corresponding B matrix |
a2 = gm[ii++]; // third row of corresponding B matrix |
// first node |
b = nv.a + n0 * ndof; |
for (k = 0; k < ndof; k++) { |
b[k] += vol * (ipv0 * a0[k] + ipv1 * a1[k] + ipv2 * a2[k]); |
} |
// second node |
b = nv.a + n1 * ndof; |
for (k = ndof, l = 0; l < ndof; k++, l++) { |
b[l] += vol * (ipv0 * a0[k] + ipv1 * a1[k] + ipv2 * a2[k]); |
} |
ipp++; |
} |
} |
/** |
function computes correct stresses at integration points on element |
@param lcid - number of load case |
@param eid - element id |
@param ri,ci - row and column indices |
JV 2.2021 |
*/ |
void tetralattice::compute_nlstress(long /*lcid*/, long eid, long ri, long ci) { |
long i, ipp; |
// computation of correct stresses |
ipp = Mt->elements[eid].ipp[ri][ci]; |
if (Mp->strcomp == 1) { |
for (i = 0; i < tnip; i++) { |
Mm->computenlstresses(ipp,Mm->ip[ipp]); |
ipp++; |
} |
} |
} |
/** |
function for strain calculation |
@param lcid - load case id |
@param eid - element id |
@param ri - row index |
@param ci - column index |
JV 2.2021 |
*/ |
void tetralattice::strains(long lcid, long eid, long ri, long ci) { |
//double** stra = NULL; |
vector coord, eps; |
if (Mp->strainaver == 0) { |
fprintf(stderr, "\n\n unknown strain averaging is required in function tetralattice::strains (%s, line %d).\n", __FILE__, __LINE__); |
} |
switch (Mm->stra.tape[eid]) { |
case nowhere: { |
break; |
} |
case intpts: { |
// strains are computed at integration points/facets |
ip_strains(lcid, eid, ri, ci); |
break; |
} |
default: { |
fprintf(stderr, "\n\n unknown strain point is required in function tetralattice::strains (%s, line %d).\n", __FILE__, __LINE__); |
} |
} |
if (Mp->strainaver == 0) { |
// deletion of cretaed vectors |
} |
} |
/** |
function computes strains in all integration points/facets of element |
@param lcid - load case id |
@param eid - element id |
@param ri - row index |
@param ci - column index |
JV 2.2021 |
*/ |
void tetralattice::ip_strains(long lcid, long eid, long ri, long ci) { |
long i, k, l, n0, n1, aca, ipp; |
double dum, epsVol; |
double* a, * b; |
vector x(ASTCKVEC(nne)), y(ASTCKVEC(nne)), z(ASTCKVEC(nne)); // coordinates of nodes |
vector r(ASTCKVEC(ndofe)); // nodal displacements and rotations |
vector eps(ASTCKVEC(tncomp)); // facet strain vector |
ivector nodes(ASTCKIVEC(nne)); // element nodes IDs |
vector aux; |
matrix gm(ASTCKMAT(tncomp * tnip, 2 * ndof)), tmat; |
Mt->give_elemnodes(eid, nodes); |
Mt->give_node_coord3d(x, y, z, eid); |
eldispl(lcid, eid, r.a); // element nodal displacements 24x |
// transformation of displacement-rotation vector into local coordinate system |
long transf = Mt->locsystems(nodes); |
if (transf > 0) { |
reallocv(RSTCKVEC(ndofe, aux)); |
reallocm(RSTCKMAT(ndofe, ndofe, tmat)); |
transf_matrix(nodes, tmat); |
lgvectortransf(aux, r, tmat); |
copyv(aux, r); |
} |
// volumetric strain |
dum = tetVol(x[0], y[0], z[0], x[1], y[1], z[1], x[2], y[2], z[2], x[3], y[3], z[3]); // initial volume |
epsVol = tetVol(x[0] + r[0], y[0] + r[1], z[0] + r[2], |
x[1] + r[6], y[1] + r[7], z[1] + r[8], |
x[2] + r[12], y[2] + r[13], z[2] + r[14], |
x[3] + r[18], y[3] + r[19], z[3] + r[20]); // new volume |
epsVol = (epsVol - dum) / (dum * 3.0); // hydrostatic strain - in paper labeled as volumetric |
ipp = Mt->elements[eid].ipp[ri][ci]; |
geom_matrix(eid, gm); |
for (i = 0; i < tnip; i++) { |
n0 = nbf[i][0]; // first edge node |
n1 = nbf[i][1]; // second edge node |
aca = 0; |
a = gm.a + i * tncomp * gm.n; |
for (k = 0; k < tncomp; k++) { |
dum = 0.0; |
// first node |
b = r.a + n0 * ndof; |
for (l = 0; l < ndof; l++) { |
dum += a[aca] * b[l]; |
aca++; |
} |
// second node |
b = r.a + n1 * ndof; |
for (l = 0; l < ndof; l++) { |
dum += a[aca] * b[l]; |
aca++; |
} |
eps[k] = dum; |
} |
// update strain vector |
Mm->storestrain(lcid, ipp, eps); |
// update volumetric strain |
Mm->ip[ipp].other[14] = epsVol; |
ipp++; |
} |
} |
/** |
function computes strains in all integration points/facets of element |
@param lcid - load case id |
@param eid - element id |
@param ri - row index |
@param ci - column index |
JV 2.2021 |
*/ |
void tetralattice::ip_strains2(long lcid, long eid, long ri, long ci, intpoints *ip) { |
long i, k, l, n0, n1, aca, ipp; |
double dum, epsVol; |
double* a, * b; |
vector x(ASTCKVEC(nne)), y(ASTCKVEC(nne)), z(ASTCKVEC(nne)); // coordinates of nodes |
vector r(ASTCKVEC(ndofe)); // nodal displacements and rotations |
vector eps(ASTCKVEC(tncomp)); // facet strain vector |
ivector nodes(ASTCKIVEC(nne)); // element nodes IDs |
vector aux; |
matrix gm(ASTCKMAT(tncomp * tnip, 2 * ndof)), tmat; |
Mt->give_elemnodes(eid, nodes); |
Mt->give_node_coord3d(x, y, z, eid); |
eldispl(lcid, eid, r.a); // element nodal displacements 24x |
// transformation of displacement-rotation vector into local coordinate system |
long transf = Mt->locsystems(nodes); |
if (transf > 0) { |
reallocv(RSTCKVEC(ndofe, aux)); |
reallocm(RSTCKMAT(ndofe, ndofe, tmat)); |
transf_matrix(nodes, tmat); |
lgvectortransf(aux, r, tmat); |
copyv(aux, r); |
} |
// volumetric strain |
dum = tetVol(x[0], y[0], z[0], x[1], y[1], z[1], x[2], y[2], z[2], x[3], y[3], z[3]); // initial volume |
epsVol = tetVol(x[0] + r[0], y[0] + r[1], z[0] + r[2], |
x[1] + r[6], y[1] + r[7], z[1] + r[8], |
x[2] + r[12], y[2] + r[13], z[2] + r[14], |
x[3] + r[18], y[3] + r[19], z[3] + r[20]); // new volume |
epsVol = (epsVol - dum) / (dum * 3.0); // hydrostatic strain - in paper labeled as volumetric |
ipp = Mt->elements[eid].ipp[ri][ci]; |
geom_matrix(eid, gm); |
for (i = 0; i < tnip; i++) { |
n0 = nbf[i][0]; // first edge node |
n1 = nbf[i][1]; // second edge node |
aca = 0; |
a = gm.a + i * tncomp * gm.n; |
for (k = 0; k < tncomp; k++) { |
dum = 0.0; |
// first node |
b = r.a + n0 * ndof; |
for (l = 0; l < ndof; l++) { |
dum += a[aca] * b[l]; |
aca++; |
} |
// second node |
b = r.a + n1 * ndof; |
for (l = 0; l < ndof; l++) { |
dum += a[aca] * b[l]; |
aca++; |
} |
eps[k] = dum; |
} |
// update strain vector |
// toto ne |
//Mm->storestrain(lcid, ipp, eps); |
// |
// nejak takto |
for (k=0;k<tncomp;k++){ |
ip[i].strain[k]=eps[k]; |
} |
// update volumetric strain |
// toto ne |
//Mm->ip[ipp].other[14] = epsVol; |
// |
// nejak takto |
ip[i].other[14] = epsVol; |
ipp++; |
} |
} |
/** |
function assembles transformation %matrix |
@param nodes - nodes of element |
@param tmat - transformation %matrix |
JV 2.2021 |
*/ |
void tetralattice::transf_matrix(ivector& nodes, matrix& tmat) { |
long i, n, m; |
nullm(tmat); |
n = nodes.n; |
m = tmat.m; |
for (i = 0; i < m; i++) { |
tmat[i][i] = 1.0; |
} |
for (i = 0; i < n; i++) { |
if (Mt->nodes[nodes[i]].transf > 0) { |
tmat[i * 6 + 0][i * 6] = tmat[i * 6 + 3][i * 6 + 3] = Mt->nodes[nodes[i]].e1[0]; |
tmat[i * 6 + 1][i * 6] = tmat[i * 6 + 4][i * 6 + 3] = Mt->nodes[nodes[i]].e1[1]; |
tmat[i * 6 + 2][i * 6] = tmat[i * 6 + 5][i * 6 + 3] = Mt->nodes[nodes[i]].e1[2]; |
tmat[i * 6 + 0][i * 6 + 1] = tmat[i * 6 + 3][i * 6 + 4] = Mt->nodes[nodes[i]].e2[0]; |
tmat[i * 6 + 1][i * 6 + 1] = tmat[i * 6 + 4][i * 6 + 4] = Mt->nodes[nodes[i]].e2[1]; |
tmat[i * 6 + 2][i * 6 + 1] = tmat[i * 6 + 5][i * 6 + 4] = Mt->nodes[nodes[i]].e2[2]; |
tmat[i * 6 + 0][i * 6 + 2] = tmat[i * 6 + 3][i * 6 + 5] = Mt->nodes[nodes[i]].e3[0]; |
tmat[i * 6 + 1][i * 6 + 2] = tmat[i * 6 + 4][i * 6 + 5] = Mt->nodes[nodes[i]].e3[1]; |
tmat[i * 6 + 2][i * 6 + 2] = tmat[i * 6 + 5][i * 6 + 5] = Mt->nodes[nodes[i]].e3[2]; |
} |
} |
} |
/** |
function calculates the volume of tetrahedron |
@param x0,y0,z0 - coordinates of first node |
@param x1,y1,z1 - coordinates of second node |
@param x2,y2,z2 - coordinates of third node |
@param x3,y3,z3 - coordinates of fourth node |
@return The function returns volume of the tetrahedron defined by 4 nodes |
JV 3.2021 |
*/ |
inline double tetralattice::tetVol(double x0, double y0, double z0, double x1, double y1, double z1, double x2, double y2, double z2, double x3, double y3, double z3) const |
{ |
return ((x1 - x0) * (y2 - y0) * (z3 - z0) + (y1 - y0) * (z2 - z0) * (x3 - x0) + (z1 - z0) * (x2 - x0) * (y3 - y0) - |
(z1 - z0) * (y2 - y0) * (x3 - x0) - (x1 - x0) * (z2 - z0) * (y3 - y0) - (y1 - y0) * (x2 - x0) * (z3 - z0)) / 6.0; |
} |
void tetralattice::largest_eigenfrequency (long lcid, long eid) |
{ |
long i,k,ri=0,ci=0; |
vector d(ASTCKVEC(ndofe)),nv(ASTCKVEC(ndofe)); |
intpoints *ip; |
integratedquant iq; |
iq = locstress; |
ip = new intpoints [tnip]; |
// loop over all DOFs |
for (i=0;i<ndofe;i++){ |
// zde je treba vygenerovat spravny vektor uzlovych posunuti d |
// vypocet deformaci |
// tato funkce ma navic posledni argument |
// ten tam v potu tvare dodam, ale zaroven to budu |
// muset udelat na vsech prvcich, aby se to prelozilo |
ip_strains2 (lcid, eid, ri, ci, ip); |
// vypocet napeti |
// nova funkce |
for (k=0;k<tnip;k++) |
Mm->computenlstresses (k,ip[k]); |
// vypocet uzlovych sil |
elem_integration2 (iq,lcid,eid,ri,ci,nv,ip); |
// zde bude plneni matice tuhosti |
} |
// zde se sestavi matice hmotnosti |
// zde se zavola rutina na vypocet nejvetsi frekvence |
} |
#include "tetralattice.h" |
#include "global.h" |
#include "probdesc.h" |
#include "mechtop.h" |
#include "mechmat.h" |
#include "mechcrsec.h" |
#include "globmat.h" |
#include "genfile.h" |
#include "intpoints.h" |
#include "node.h" |
#include "element.h" |
#include "loadcase.h" |
#include "mathem.h" |
tetralattice::tetralattice(void) { |
long i; |
// number of DOFs per node |
ndof = 6; |
// number nodes on element |
nne = 4; |
// number of DOFs on element |
ndofe = nne * ndof; |
// number of strain/stress components |
tncomp = 3; |
// number of functions approximated |
napfun = 3; |
// order of numerical integration of mass matrix |
intordmm = 1; |
// number of edges on element |
ned = 6; |
// number of nodes on one edge |
nned = 2; |
// number of surfaces |
nsurf = 4; |
// number of nodes on one surface |
nnsurf = 3; |
// order of numerical integration on element edges (boundaries) |
intordb = 3; |
// strain/stress state |
ssst = spacestress; |
// number of blocks (parts of geometric matrix) |
nb = 1; |
// number of strain/stress components |
ncomp = new long[nb]; |
ncomp[0] = 3; |
// cumulative number of components approximated |
cncomp = new long[nb]; |
cncomp[0] = 0; |
// number of integration points = 12 (fixed) |
tnip = 12; |
nip = new long* [nb]; |
for (i = 0; i < nb; i++) { |
nip[i] = new long[nb]; |
} |
nip[0][0] = tnip; |
// nodes belonging to edge |
nbe[0][0] = 0; nbe[0][1] = 1; |
nbe[1][0] = 0; nbe[1][1] = 2; |
nbe[2][0] = 1; nbe[2][1] = 2; |
nbe[3][0] = 1; nbe[3][1] = 3; |
nbe[4][0] = 2; nbe[4][1] = 3; |
nbe[5][0] = 0; nbe[5][1] = 3; |
// edge belonging to facet |
ebf[0] = 0; |
ebf[1] = 0; |
ebf[2] = 1; |
ebf[3] = 1; |
ebf[4] = 2; |
ebf[5] = 2; |
ebf[6] = 3; |
ebf[7] = 3; |
ebf[8] = 4; |
ebf[9] = 4; |
ebf[10] = 5; |
ebf[11] = 5; |
// nodes beloging to surface - surfaces indexed according to the oposite node |
nbs[0][0] = 1; nbs[0][1] = 2; nbs[0][2] = 3; // surface oposite node 0 |
nbs[1][0] = 0; nbs[1][1] = 3; nbs[1][2] = 2; // surface oposite node 1 |
nbs[2][0] = 0; nbs[2][1] = 1; nbs[2][2] = 3; // surface oposite node 2 |
nbs[3][0] = 0; nbs[3][1] = 2; nbs[3][2] = 1; // surface oposite node 3 |
// edges beloging to surface (with accordance to nbe) |
ebs[0][0] = 2; ebs[0][1] = 4; ebs[0][2] = 3; |
ebs[1][0] = 5; ebs[1][1] = 4; ebs[1][2] = 1; |
ebs[2][0] = 0; ebs[2][1] = 3; ebs[2][2] = 5; |
ebs[3][0] = 1; ebs[3][1] = 2; ebs[3][2] = 0; |
// nodes oposite the edge-node (surfacewise) |
enbs[0][0] = 4; enbs[0][1] = 3; enbs[0][2] = 2; |
enbs[1][0] = 4; enbs[1][1] = 1; enbs[1][2] = 5; |
enbs[2][0] = 3; enbs[2][1] = 5; enbs[2][2] = 0; |
enbs[3][0] = 2; enbs[3][1] = 0; enbs[3][2] = 1; |
// surface belonging to facet |
sbf[0] = 2; |
sbf[1] = 3; |
sbf[2] = 1; |
sbf[3] = 3; |
sbf[4] = 0; |
sbf[5] = 3; |
sbf[6] = 0; |
sbf[7] = 2; |
sbf[8] = 0; |
sbf[9] = 1; |
sbf[10] = 1; |
sbf[11] = 2; |
/// nodes belonging to facet |
for (i = 0; i < tnip; i++) { |
nbf[i][0] = nbe[ebf[i]][0]; |
nbf[i][1] = nbe[ebf[i]][1]; |
} |
} |
tetralattice::~tetralattice(void) { |
long i; |
for (i = 0; i < nb; i++) { |
delete[] nip[i]; |
delete[] intordsm[i]; |
} |
delete[] nip; |
delete[] intordsm; |
delete[] cncomp; |
delete[] ncomp; |
} |
/** |
function creates facets in tetrahedral element used by lattice discrete particle model |
@param eid - element ID |
JV, 2.2021 |
*/ |
void tetralattice::create_facets(long eid, matrix& mm) { |
// lambda expresion for length |
auto length = [](double x0, double y0, double z0, double x1, double y1, double z1) -> double { |
return sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0) + (z1 - z0) * (z1 - z0)); |
}; |
// lambda expression for moments of inertia of tetrahedron to the first node |
auto moi = [](double x0, double y0, double z0, double x1, double y1, double z1, double x2, double y2, double z2, double x3, double y3, double z3, double mass, double& ixx, double& iyy, double& izz, double& iyz, double& ixz, double& ixy) { |
double dumx, dumy, dumz, cx, cy, cz, dx, dy, dz; |
dumx = x0 * x0 + x0 * x1 + x1 * x1 + x0 * x2 + x1 * x2 + x2 * x2 + x0 * x3 + x1 * x3 + x2 * x3 + x3 * x3; |
dumy = y0 * y0 + y0 * y1 + y1 * y1 + y0 * y2 + y1 * y2 + y2 * y2 + y0 * y3 + y1 * y3 + y2 * y3 + y3 * y3; |
dumz = z0 * z0 + z0 * z1 + z1 * z1 + z0 * z2 + z1 * z2 + z2 * z2 + z0 * z3 + z1 * z3 + z2 * z3 + z3 * z3; |
cx = 0.25 * (x0 + x1 + x2 + x3); |
cy = 0.25 * (y0 + y1 + y2 + y3); |
cz = 0.25 * (z0 + z1 + z2 + z3); |
dx = cx - x0; |
dy = cy - y0; |
dz = cz - z0; |
ixx = 0.1 * mass * (dumy + dumz) + mass * (dy * dy + dz * dz); |
iyy = 0.1 * mass * (dumx + dumz) + mass * (dx * dx + dz * dz); |
izz = 0.1 * mass * (dumx + dumy) + mass * (dx * dx + dy * dy); |
iyz = 0.05 * mass * (2.0 * y0 * z0 + y1 * z0 + y2 * z0 + y3 * z0 + y0 * z1 + 2.0 * y1 * z1 + y2 * z1 + y3 * z1 + |
y0 * z2 + y1 * z2 + 2.0 * y2 * z2 + y3 * z2 + y0 * z3 + y1 * z3 + y2 * z3 + 2.0 * y3 * z3) + |
mass * dy * dz; |
ixz = 0.05 * mass * (2.0 * x0 * z0 + x1 * z0 + x2 * z0 + x3 * z0 + x0 * z1 + 2.0 * x1 * z1 + x2 * z1 + x3 * z1 + |
x0 * z2 + x1 * z2 + 2.0 * x2 * z2 + x3 * z2 + x0 * z3 + x1 * z3 + x2 * z3 + 2.0 * x3 * z3) + |
mass * dx * dz; |
ixy = 0.05 * mass * (2.0 * x0 * y0 + x1 * y0 + x2 * y0 + x3 * y0 + x0 * y1 + 2.0 * x1 * y1 + x2 * y1 + x3 * y1 + |
x0 * y2 + x1 * y2 + 2.0 * x2 * y2 + x3 * y2 + x0 * y3 + x1 * y3 + x2 * y3 + 2.0 * x3 * y3) + |
mass * dx * dy; |
}; |
// according to: Lattice Discrete Particle Model (LDPM) for failure behavior of concrete. I: Theory, Gianluca Cusatis, Daniele Pelessone, Andrea Mencarelli |
long i, j, ipp, n0, n1, ne, ns, dumn; |
double dum1, dum2, dum3; |
double fnx, fny, fnz, flx, fly, flz, fmx, fmy, fmz; |
double vol, density, mass, ixx, iyy, izz, iyz, ixz, ixy; |
bool orderNCES; |
vector x(ASTCKVEC(nne)), y(ASTCKVEC(nne)), z(ASTCKVEC(nne)); // nodes coordinates |
vector r(ASTCKVEC(nne)), ele(ASTCKVEC(ned)); // node radius, element edge length |
// new nodes |
vector enx(ASTCKVEC(ned)), eny(ASTCKVEC(ned)), enz(ASTCKVEC(ned)); // edge nodes |
vector snx(ASTCKVEC(ned)), sny(ASTCKVEC(ned)), snz(ASTCKVEC(ned)); // surface nodes |
double tx, ty, tz; // element center node |
vector fx(ASTCKVEC(tnip)), fy(ASTCKVEC(tnip)), fz(ASTCKVEC(tnip)); // facet centroids |
vector fa(ASTCKVEC(tnip)); // projected facet area |
ivector nodes(ASTCKIVEC(nne)); // element nodes IDs |
vector dens(ASTCKVEC(nne)); // nodal densities |
//matrix mm(ASTCKMAT(ndofe, ndofe)); |
// cleaning of mass matrix |
nullm(mm); |
// node IDs |
Mt->give_elemnodes(eid, nodes); |
// nodal densities |
Mc->give_density(eid, nodes, dens); |
// node coordinates |
Mt->give_node_coord3d(x, y, z, eid); |
// all node densities are the same |
density = dens[0]; |
// particle (node) radii |
for (i = 0; i < nne; i++) { |
r[i] = Mt->node_radius[nodes[i]]; |
} |
// edge mid-nodes - E12, E13, E14, E23, E24, E34 |
for (i = 0; i < ned; i++) { |
n0 = nbe[i][0]; |
n1 = nbe[i][1]; |
// edge lengths |
ele[i] = length(x[n0], y[n0], z[n0], x[n1], y[n1], z[n1]); |
dum1 = ele[i] - r[n0] - r[n1]; // gap between particles |
if (dum1 < 0.0) { |
print_err("Wrong 3D tetrahedral lattice element number %ld, negative gap! gap = %e", __FILE__, __LINE__, __func__, eid + 1, dum1); |
abort(); |
} |
dum2 = (r[n0] + 0.5 * dum1) / ele[i]; |
enx[i] = x[n0] + dum2 * (x[n1] - x[n0]); |
eny[i] = y[n0] + dum2 * (y[n1] - y[n0]); |
enz[i] = z[n0] + dum2 * (z[n1] - z[n0]); |
} |
// element surface nodes - F1, F2, F3, F4 |
for (i = 0; i < nsurf; i++) { |
snx[i] = sny[i] = snz[i] = 0.0; |
for (j = 0; j < nnsurf; j++) { |
n0 = nbs[i][j]; |
n1 = enbs[i][j]; |
dum3 = length(x[n0], y[n0], z[n0], enx[n1], eny[n1], enz[n1]); |
dum1 = dum3 - r[n0]; // gap between particle and edge |
if (dum1 < 0.0) { |
print_err("Wrong 3D tetrahedral lattice element number %ld, negative gap! gap = %e", __FILE__, __LINE__, __func__, eid + 1, dum1); |
abort(); |
} |
dum2 = (r[n0] + 0.5 * dum1) / dum3; |
snx[i] += x[n0] + dum2 * (enx[n1] - x[n0]); |
sny[i] += y[n0] + dum2 * (eny[n1] - y[n0]); |
snz[i] += z[n0] + dum2 * (enz[n1] - z[n0]); |
} |
snx[i] /= nnsurf; |
sny[i] /= nnsurf; |
snz[i] /= nnsurf; |
} |
// element centroid - t |
tx = ty = tz = 0.0; |
for (i = 0; i < nsurf; i++) { |
// surfaces indexed according to the oposite node |
n0 = n1 = i; |
dum3 = length(x[n0], y[n0], z[n0], snx[n1], sny[n1], snz[n1]); |
dum1 = dum3 - r[n0]; // gap between particle and edge |
if (dum1 < 0.0) { |
print_err("Wrong 3D tetrahedral lattice element number %ld, negative gap! gap = %e", __FILE__, __LINE__, __func__, eid + 1, dum1); |
abort(); |
} |
dum2 = (r[n0] + 0.5 * dum1) / dum3; |
tx += x[n0] + dum2 * (snx[n1] - x[n0]); |
ty += y[n0] + dum2 * (sny[n1] - y[n0]); |
tz += z[n0] + dum2 * (snz[n1] - z[n0]); |
} |
tx /= nsurf; |
ty /= nsurf; |
tz /= nsurf; |
// facets - centroid + area - 12x |
nullm(mm); |
ipp = Mt->elements[eid].ipp[0][0]; |
for (i = 0; i < tnip; i++) { |
ne = ebf[i]; // edge node |
ns = sbf[i]; // surface node |
n0 = nbf[i][0]; // first edge node |
n1 = nbf[i][1]; // second edge node |
// local coordinate system of the projected facet - alligned with the edge, order of axes N-L-M |
fnx = (x[n1] - x[n0]) / ele[ne]; |
fny = (y[n1] - y[n0]) / ele[ne]; |
fnz = (z[n1] - z[n0]) / ele[ne]; |
// facet centroid |
fx[i] = (enx[ne] + snx[ns] + tx) / 3.; |
fy[i] = (eny[ne] + sny[ns] + ty) / 3.; |
fz[i] = (enz[ne] + snz[ns] + tz) / 3.; |
// fl,fm - vectors in the facet plane |
flx = enx[ne] - tx; |
fly = eny[ne] - ty; |
flz = enz[ne] - tz; |
fmx = snx[ns] - tx; |
fmy = sny[ns] - ty; |
fmz = snz[ns] - tz; |
// cross product - fl x fm, vector length = twice the facet area |
dum1 = fly * fmz - flz * fmy; |
dum2 = flz * fmx - flx * fmz; |
dum3 = flx * fmy - fly * fmx; |
// projected facet area into the direction of perpedincular to the edge |
// scalar product of the facet area vector and edge unit vector |
fa[i] = fabs(0.5 * (dum1 * fnx + dum2 * fny + dum3 * fnz)); |
// local coordinate system of the projected facet - remaining axis, order of axes N-L-M |
// fl - vector perpedincular to fn by means of already defined vector fm (we could use any random vector instead of fm) |
flx = fmy * fnz - fmz * fny; |
fly = fmz * fnx - fmx * fnz; |
flz = fmx * fny - fmy * fnx; |
dum1 = sqrt(flx * flx + fly * fly + flz * flz); |
flx /= dum1; |
fly /= dum1; |
flz /= dum1; |
// remaining axis m => fm vector perpedincular to fn and fl vectors |
fmx = fny * flz - fnz * fly; |
fmy = fnz * flx - fnx * flz; |
fmz = fnx * fly - fny * flx; |
// volume and moments of inertia |
// tetrahedron nodeOfOriginalElement-centroid(t)-edgeNode(en)-surfaceNode(sn) |
for (j = 0; j < 2; j++) { |
dumn = n0; |
if (j == 1) dumn = n1; |
vol = tetVol(x[dumn], y[dumn], z[dumn], tx, ty, tz, enx[ne], eny[ne], enz[ne], snx[ns], sny[ns], snz[ns]); |
orderNCES = true; |
if (vol < 0.0) { |
// tetrahedron nodeOfOriginalElement-edgeNode(en)-centroid(t)-surfaceNode(sn) |
vol = tetVol(x[dumn], y[dumn], z[dumn], enx[ne], eny[ne], enz[ne], tx, ty, tz, snx[ns], sny[ns], snz[ns]); |
orderNCES = false; |
} |
if (vol <= Mp->zero) { |
print_err("Wrong 3D tetrahedral lattice element number %ld, zero volume! vol = %e", __FILE__, __LINE__, __func__, eid + 1, vol); |
abort(); |
} |
// @todo get density |
mass = vol * density; |
if (orderNCES) { |
moi(x[dumn], y[dumn], z[dumn], tx, ty, tz, enx[ne], eny[ne], enz[ne], snx[ns], sny[ns], snz[ns], mass, ixx, iyy, izz, iyz, ixz, ixy); |
} else { |
moi(x[dumn], y[dumn], z[dumn], enx[ne], eny[ne], enz[ne], tx, ty, tz, snx[ns], sny[ns], snz[ns], mass, ixx, iyy, izz, iyz, ixz, ixy); |
} |
// mass |
mm[dumn * 6 + 0][dumn * 6 + 0] += mass; |
mm[dumn * 6 + 1][dumn * 6 + 1] += mass; |
mm[dumn * 6 + 2][dumn * 6 + 2] += mass; |
// inertia |
mm[dumn * 6 + 3][dumn * 6 + 3] += ixx; |
mm[dumn * 6 + 4][dumn * 6 + 4] += iyy; |
mm[dumn * 6 + 5][dumn * 6 + 5] += izz; |
mm[dumn * 6 + 3][dumn * 6 + 4] -= ixy; |
mm[dumn * 6 + 3][dumn * 6 + 5] -= ixz; |
mm[dumn * 6 + 4][dumn * 6 + 5] -= iyz; |
mm[dumn * 6 + 4][dumn * 6 + 3] -= ixy; |
mm[dumn * 6 + 5][dumn * 6 + 3] -= ixz; |
mm[dumn * 6 + 5][dumn * 6 + 4] -= iyz; |
// additonal momentum |
// tetrahedron centroid |
dum1 = 0.25 * (x[dumn] + tx + enx[ne] + snx[ns]); |
dum2 = 0.25 * (y[dumn] + ty + eny[ne] + sny[ns]); |
dum3 = 0.25 * (z[dumn] + tz + enz[ne] + snz[ns]); |
mm[dumn * 6 + 0][dumn * 6 + 4] += mass * (z[dumn] - dum3); |
mm[dumn * 6 + 0][dumn * 6 + 5] -= mass * (y[dumn] - dum2); |
mm[dumn * 6 + 1][dumn * 6 + 3] -= mass * (z[dumn] - dum3); |
mm[dumn * 6 + 1][dumn * 6 + 5] += mass * (x[dumn] - dum1); |
mm[dumn * 6 + 2][dumn * 6 + 3] += mass * (y[dumn] - dum2); |
mm[dumn * 6 + 2][dumn * 6 + 4] -= mass * (x[dumn] - dum1); |
mm[dumn * 6 + 4][dumn * 6 + 0] += mass * (z[dumn] - dum3); |
mm[dumn * 6 + 5][dumn * 6 + 0] -= mass * (y[dumn] - dum2); |
mm[dumn * 6 + 3][dumn * 6 + 1] -= mass * (z[dumn] - dum3); |
mm[dumn * 6 + 5][dumn * 6 + 1] += mass * (x[dumn] - dum1); |
mm[dumn * 6 + 3][dumn * 6 + 2] += mass * (y[dumn] - dum2); |
mm[dumn * 6 + 4][dumn * 6 + 2] -= mass * (x[dumn] - dum1); |
} |
/*---------- DATA SAVING ----------*/ |
// save values on IP |
Mm->ip[ipp].other[0] = fx[i]; |
Mm->ip[ipp].other[1] = fy[i]; |
Mm->ip[ipp].other[2] = fz[i]; |
// local coordinates |
Mm->ip[ipp].other[3] = fnx; |
Mm->ip[ipp].other[4] = fny; |
Mm->ip[ipp].other[5] = fnz; |
Mm->ip[ipp].other[6] = flx; |
Mm->ip[ipp].other[7] = fly; |
Mm->ip[ipp].other[8] = flz; |
Mm->ip[ipp].other[9] = fmx; |
Mm->ip[ipp].other[10] = fmy; |
Mm->ip[ipp].other[11] = fmz; |
// facet area |
Mm->ip[ipp].other[12] = fa[i]; |
// edge length |
Mm->ip[ipp].other[13] = ele[ebf[i]]; |
// volumetric strain |
Mm->ip[ipp].other[14] = 0.0; |
ipp++; |
} |
// diagonalization of the mass matrix |
// @todo |
//diagonalization (mm); |
} |
/** |
function assembles strain-displacement (geometric) %matrix for all facets in tetrahedral element |
vector of strains has following ordering eps=(e_N, e_L, e_M) |
geometric %matrix size is (tncomp*tnip, 2*ndof) |
@param eid - element ID |
@param gm - geometric %matrix |
JV, 2.2021 |
*/ |
void tetralattice::geom_matrix(long eid, matrix& gm) { |
long i, ri, ipp, n0, n1; |
double dum1; |
double* a; |
double fx, fy, fz; |
double fnx, fny, fnz, flx, fly, flz, fmx, fmy, fmz; |
double A04_0, A05_0, A15_0, A04_1, A05_1, A15_1; |
vector x(ASTCKVEC(nne)), y(ASTCKVEC(nne)), z(ASTCKVEC(nne)); // nodes coordinates |
// node coordinates |
Mt->give_node_coord3d(x, y, z, eid); |
nullm(gm); |
ipp = Mt->elements[eid].ipp[0][0]; |
ri = 0; |
for (i = 0; i < tnip; i++) { |
n0 = nbf[i][0]; // first edge node |
n1 = nbf[i][1]; // second edge node |
dum1 = 1. / Mm->ip[ipp].other[13]; // 1. / edge length |
fx = Mm->ip[ipp].other[0]; |
fy = Mm->ip[ipp].other[1]; |
fz = Mm->ip[ipp].other[2]; |
fnx = Mm->ip[ipp].other[3] * dum1; |
fny = Mm->ip[ipp].other[4] * dum1; |
fnz = Mm->ip[ipp].other[5] * dum1; |
flx = Mm->ip[ipp].other[6] * dum1; |
fly = Mm->ip[ipp].other[7] * dum1; |
flz = Mm->ip[ipp].other[8] * dum1; |
fmx = Mm->ip[ipp].other[9] * dum1; |
fmy = Mm->ip[ipp].other[10] * dum1; |
fmz = Mm->ip[ipp].other[11] * dum1; |
A04_0 = (fz - z[n0]); |
A05_0 = (y[n0] - fy); |
A15_0 = (fx - x[n0]); |
A04_1 = (fz - z[n1]); |
A05_1 = (y[n1] - fy); |
A15_1 = (fx - x[n1]); |
// eps_N |
a = gm[ri++]; |
a[0] = -fnx; |
a[1] = -fny; |
a[2] = -fnz; |
a[3] = fny * A04_0 + fnz * A05_0; |
a[4] = -fnx * A04_0 + fnz * A15_0; |
a[5] = -fnx * A05_0 - fny * A15_0; |
a[6] = fnx; |
a[7] = fny; |
a[8] = fnz; |
a[9] = -fny * A04_1 - fnz * A05_1; |
a[10] = fnx * A04_1 - fnz * A15_1; |
a[11] = fnx * A05_1 + fny * A15_1; |
// eps_L |
a = gm[ri++]; |
a[0] = -flx; |
a[1] = -fly; |
a[2] = -flz; |
a[3] = fly * A04_0 + flz * A05_0; |
a[4] = -flx * A04_0 + flz * A15_0; |
a[5] = -flx * A05_0 - fly * A15_0; |
a[6] = flx; |
a[7] = fly; |
a[8] = flz; |
a[9] = -fly * A04_1 - flz * A05_1; |
a[10] = flx * A04_1 - flz * A15_1; |
a[11] = flx * A05_1 + fly * A15_1; |
// eps_M |
a = gm[ri++]; |
a[0] = -fmx; |
a[1] = -fmy; |
a[2] = -fmz; |
a[3] = fmy * A04_0 + fmz * A05_0; |
a[4] = -fmx * A04_0 + fmz * A15_0; |
a[5] = -fmx * A05_0 - fmy * A15_0; |
a[6] = fmx; |
a[7] = fmy; |
a[8] = fmz; |
a[9] = -fmy * A04_1 - fmz * A05_1; |
a[10] = fmx * A04_1 - fmz * A15_1; |
a[11] = fmx * A05_1 + fmy * A15_1; |
ipp++; |
} |
} |
/** |
function computes internal forces |
@param lcid - load case id |
@param eid - element id |
@param ri,ci - row and column indices |
@param ifor - vector of internal forces |
JV 2.2021 |
*/ |
void tetralattice::internal_forces(long lcid, long eid, long ri, long ci, vector& ifor) { |
integratedquant iq; |
iq = locstress; |
// computation of stresses |
compute_nlstress(lcid, eid, ri, ci); // stresses on facets |
// integration of stresses over the element |
elem_integration(iq, lcid, eid, ri, ci, ifor); |
} |
/** |
The function integrates selected stress type quantity over the finite element, i.e. |
it performs \int_{\Omega} \mbf{B}^T \mbf{\sigma} d\Omega. It results in nodal values. |
@param iq - type of integrated quantity (see alias.h) |
@param lcid - number of load case |
@param eid - element id |
@param ri,ci - row and column indices |
@param nv - nodal values (output) |
@return The function returns nodal values calculated in the %vector nv |
JV 2.2021 |
*/ |
void tetralattice::elem_integration(integratedquant iq, long lcid, long eid, long /*ri*/, long /*ci*/, vector& nv) { |
long i, ii, k, l, n0, n1, ipp; |
double vol, ipv0, ipv1, ipv2; |
double* a0, * a1, * a2, * b; |
matrix gm(ASTCKMAT(tncomp * tnip, 2 * ndof)); // geoetric matrix |
vector ipv(ASTCKVEC(tncomp)); // itegration point values |
nullv(nv); |
ipp = Mt->elements[eid].ipp[0][0]; |
geom_matrix(eid, gm); |
ii = 0; |
for (i = 0; i < tnip; i++) { |
n0 = nbf[i][0]; // first edge node |
n1 = nbf[i][1]; // second edge node |
vol = Mm->ip[ipp].other[12] * Mm->ip[ipp].other[13]; // facet area * edge length |
Mm->givequantity(iq, lcid, ipp, cncomp[0], ipv); // function assembles required quantity at integration point |
ipv0 = ipv[0]; |
ipv1 = ipv[1]; |
ipv2 = ipv[2]; |
a0 = gm[ii++]; // first row of corresponding B matrix |
a1 = gm[ii++]; // second row of corresponding B matrix |
a2 = gm[ii++]; // third row of corresponding B matrix |
// first node |
b = nv.a + n0 * ndof; |
for (k = 0; k < ndof; k++) { |
b[k] += vol * (ipv0 * a0[k] + ipv1 * a1[k] + ipv2 * a2[k]); |
} |
// second node |
b = nv.a + n1 * ndof; |
for (k = ndof, l = 0; l < ndof; k++, l++) { |
b[l] += vol * (ipv0 * a0[k] + ipv1 * a1[k] + ipv2 * a2[k]); |
} |
ipp++; |
} |
} |
/** |
The function integrates selected stress type quantity over the finite element, i.e. |
it performs \int_{\Omega} \mbf{B}^T \mbf{\sigma} d\Omega. It results in nodal values. |
@param iq - type of integrated quantity (see alias.h) |
@param lcid - number of load case |
@param eid - element id |
@param ri,ci - row and column indices |
@param nv - nodal values (output) |
@return The function returns nodal values calculated in the %vector nv |
JV 2.2021 |
*/ |
void tetralattice::elem_integration2(integratedquant /*iq*/, long /*lcid*/, long eid, long /*ri*/, long /*ci*/, vector& nv, intpoints *ip) { |
long i, ii, k, l, n0, n1, ipp; |
double vol, ipv0, ipv1, ipv2; |
double* a0, * a1, * a2, * b; |
matrix gm(ASTCKMAT(tncomp * tnip, 2 * ndof)); // geoetric matrix |
vector ipv(ASTCKVEC(tncomp)); // itegration point values |
nullv(nv); |
ipp = Mt->elements[eid].ipp[0][0]; |
geom_matrix(eid, gm); |
ii = 0; |
for (i = 0; i < tnip; i++) { |
n0 = nbf[i][0]; // first edge node |
n1 = nbf[i][1]; // second edge node |
// toto ne |
//vol = Mm->ip[ipp].other[12] * Mm->ip[ipp].other[13]; // facet area * edge length |
// neco takoveho |
vol = ip[i].other[12] * ip[i].other[13]; // facet area * edge length |
// toto ne |
//Mm->givequantity(iq, lcid, ipp, cncomp[0], ipv); // function assembles required quantity at integration point |
//ipv0 = ipv[0]; |
//ipv1 = ipv[1]; |
//ipv2 = ipv[2]; |
ipv0 = ip[i].stress[0]; |
ipv1 = ip[i].stress[1]; |
ipv2 = ip[i].stress[2]; |
a0 = gm[ii++]; // first row of corresponding B matrix |
a1 = gm[ii++]; // second row of corresponding B matrix |
a2 = gm[ii++]; // third row of corresponding B matrix |
// first node |
b = nv.a + n0 * ndof; |
for (k = 0; k < ndof; k++) { |
b[k] += vol * (ipv0 * a0[k] + ipv1 * a1[k] + ipv2 * a2[k]); |
} |
// second node |
b = nv.a + n1 * ndof; |
for (k = ndof, l = 0; l < ndof; k++, l++) { |
b[l] += vol * (ipv0 * a0[k] + ipv1 * a1[k] + ipv2 * a2[k]); |
} |
ipp++; |
} |
} |
/** |
function computes correct stresses at integration points on element |
@param lcid - number of load case |
@param eid - element id |
@param ri,ci - row and column indices |
JV 2.2021 |
*/ |
void tetralattice::compute_nlstress(long /*lcid*/, long eid, long ri, long ci) { |
long i, ipp; |
// computation of correct stresses |
ipp = Mt->elements[eid].ipp[ri][ci]; |
if (Mp->strcomp == 1) { |
for (i = 0; i < tnip; i++) { |
Mm->computenlstresses(ipp,Mm->ip[ipp]); |
ipp++; |
} |
} |
} |
/** |
function for strain calculation |
@param lcid - load case id |
@param eid - element id |
@param ri - row index |
@param ci - column index |
JV 2.2021 |
*/ |
void tetralattice::strains(long lcid, long eid, long ri, long ci) { |
//double** stra = NULL; |
vector coord, eps; |
if (Mp->strainaver == 0) { |
fprintf(stderr, "\n\n unknown strain averaging is required in function tetralattice::strains (%s, line %d).\n", __FILE__, __LINE__); |
} |
switch (Mm->stra.tape[eid]) { |
case nowhere: { |
break; |
} |
case intpts: { |
// strains are computed at integration points/facets |
ip_strains(lcid, eid, ri, ci); |
break; |
} |
default: { |
fprintf(stderr, "\n\n unknown strain point is required in function tetralattice::strains (%s, line %d).\n", __FILE__, __LINE__); |
} |
} |
if (Mp->strainaver == 0) { |
// deletion of cretaed vectors |
} |
} |
/** |
function computes strains in all integration points/facets of element |
@param lcid - load case id |
@param eid - element id |
@param ri - row index |
@param ci - column index |
JV 2.2021 |
*/ |
void tetralattice::ip_strains(long lcid, long eid, long ri, long ci) { |
long i, k, l, n0, n1, aca, ipp; |
double dum, epsVol; |
double* a, * b; |
vector x(ASTCKVEC(nne)), y(ASTCKVEC(nne)), z(ASTCKVEC(nne)); // coordinates of nodes |
vector r(ASTCKVEC(ndofe)); // nodal displacements and rotations |
vector eps(ASTCKVEC(tncomp)); // facet strain vector |
ivector nodes(ASTCKIVEC(nne)); // element nodes IDs |
vector aux; |
matrix gm(ASTCKMAT(tncomp * tnip, 2 * ndof)), tmat; |
Mt->give_elemnodes(eid, nodes); |
Mt->give_node_coord3d(x, y, z, eid); |
eldispl(lcid, eid, r.a); // element nodal displacements 24x |
// transformation of displacement-rotation vector into local coordinate system |
long transf = Mt->locsystems(nodes); |
if (transf > 0) { |
reallocv(RSTCKVEC(ndofe, aux)); |
reallocm(RSTCKMAT(ndofe, ndofe, tmat)); |
transf_matrix(nodes, tmat); |
lgvectortransf(aux, r, tmat); |
copyv(aux, r); |
} |
// volumetric strain |
dum = tetVol(x[0], y[0], z[0], x[1], y[1], z[1], x[2], y[2], z[2], x[3], y[3], z[3]); // initial volume |
epsVol = tetVol(x[0] + r[0], y[0] + r[1], z[0] + r[2], |
x[1] + r[6], y[1] + r[7], z[1] + r[8], |
x[2] + r[12], y[2] + r[13], z[2] + r[14], |
x[3] + r[18], y[3] + r[19], z[3] + r[20]); // new volume |
epsVol = (epsVol - dum) / (dum * 3.0); // hydrostatic strain - in paper labeled as volumetric |
ipp = Mt->elements[eid].ipp[ri][ci]; |
geom_matrix(eid, gm); |
for (i = 0; i < tnip; i++) { |
n0 = nbf[i][0]; // first edge node |
n1 = nbf[i][1]; // second edge node |
aca = 0; |
a = gm.a + i * tncomp * gm.n; |
for (k = 0; k < tncomp; k++) { |
dum = 0.0; |
// first node |
b = r.a + n0 * ndof; |
for (l = 0; l < ndof; l++) { |
dum += a[aca] * b[l]; |
aca++; |
} |
// second node |
b = r.a + n1 * ndof; |
for (l = 0; l < ndof; l++) { |
dum += a[aca] * b[l]; |
aca++; |
} |
eps[k] = dum; |
} |
// update strain vector |
Mm->storestrain(lcid, ipp, eps); |
// update volumetric strain |
Mm->ip[ipp].other[14] = epsVol; |
ipp++; |
} |
} |
/** |
function computes strains in all integration points/facets of element |
@param lcid - load case id |
@param eid - element id |
@param ri - row index |
@param ci - column index |
JV 2.2021 |
*/ |
void tetralattice::ip_strains2(long lcid, long eid, long ri, long ci, intpoints *ip) { |
long i, k, l, n0, n1, aca, ipp; |
double dum, epsVol; |
double* a, * b; |
vector x(ASTCKVEC(nne)), y(ASTCKVEC(nne)), z(ASTCKVEC(nne)); // coordinates of nodes |
vector r(ASTCKVEC(ndofe)); // nodal displacements and rotations |
vector eps(ASTCKVEC(tncomp)); // facet strain vector |
ivector nodes(ASTCKIVEC(nne)); // element nodes IDs |
vector aux; |
matrix gm(ASTCKMAT(tncomp * tnip, 2 * ndof)), tmat; |
Mt->give_elemnodes(eid, nodes); |
Mt->give_node_coord3d(x, y, z, eid); |
eldispl(lcid, eid, r.a); // element nodal displacements 24x |
// transformation of displacement-rotation vector into local coordinate system |
long transf = Mt->locsystems(nodes); |
if (transf > 0) { |
reallocv(RSTCKVEC(ndofe, aux)); |
reallocm(RSTCKMAT(ndofe, ndofe, tmat)); |
transf_matrix(nodes, tmat); |
lgvectortransf(aux, r, tmat); |
copyv(aux, r); |
} |
// volumetric strain |
dum = tetVol(x[0], y[0], z[0], x[1], y[1], z[1], x[2], y[2], z[2], x[3], y[3], z[3]); // initial volume |
epsVol = tetVol(x[0] + r[0], y[0] + r[1], z[0] + r[2], |
x[1] + r[6], y[1] + r[7], z[1] + r[8], |
x[2] + r[12], y[2] + r[13], z[2] + r[14], |
x[3] + r[18], y[3] + r[19], z[3] + r[20]); // new volume |
epsVol = (epsVol - dum) / (dum * 3.0); // hydrostatic strain - in paper labeled as volumetric |
ipp = Mt->elements[eid].ipp[ri][ci]; |
geom_matrix(eid, gm); |
for (i = 0; i < tnip; i++) { |
n0 = nbf[i][0]; // first edge node |
n1 = nbf[i][1]; // second edge node |
aca = 0; |
a = gm.a + i * tncomp * gm.n; |
for (k = 0; k < tncomp; k++) { |
dum = 0.0; |
// first node |
b = r.a + n0 * ndof; |
for (l = 0; l < ndof; l++) { |
dum += a[aca] * b[l]; |
aca++; |
} |
// second node |
b = r.a + n1 * ndof; |
for (l = 0; l < ndof; l++) { |
dum += a[aca] * b[l]; |
aca++; |
} |
eps[k] = dum; |
} |
// update strain vector |
// toto ne |
//Mm->storestrain(lcid, ipp, eps); |
// |
// nejak takto |
for (k=0;k<tncomp;k++){ |
ip[i].strain[k]=eps[k]; |
} |
// update volumetric strain |
// toto ne |
//Mm->ip[ipp].other[14] = epsVol; |
// |
// nejak takto |
ip[i].other[14] = epsVol; |
ipp++; |
} |
} |
/** |
function assembles transformation %matrix |
@param nodes - nodes of element |
@param tmat - transformation %matrix |
JV 2.2021 |
*/ |
void tetralattice::transf_matrix(ivector& nodes, matrix& tmat) { |
long i, n, m; |
nullm(tmat); |
n = nodes.n; |
m = tmat.m; |
for (i = 0; i < m; i++) { |
tmat[i][i] = 1.0; |
} |
for (i = 0; i < n; i++) { |
if (Mt->nodes[nodes[i]].transf > 0) { |
tmat[i * 6 + 0][i * 6] = tmat[i * 6 + 3][i * 6 + 3] = Mt->nodes[nodes[i]].e1[0]; |
tmat[i * 6 + 1][i * 6] = tmat[i * 6 + 4][i * 6 + 3] = Mt->nodes[nodes[i]].e1[1]; |
tmat[i * 6 + 2][i * 6] = tmat[i * 6 + 5][i * 6 + 3] = Mt->nodes[nodes[i]].e1[2]; |
tmat[i * 6 + 0][i * 6 + 1] = tmat[i * 6 + 3][i * 6 + 4] = Mt->nodes[nodes[i]].e2[0]; |
tmat[i * 6 + 1][i * 6 + 1] = tmat[i * 6 + 4][i * 6 + 4] = Mt->nodes[nodes[i]].e2[1]; |
tmat[i * 6 + 2][i * 6 + 1] = tmat[i * 6 + 5][i * 6 + 4] = Mt->nodes[nodes[i]].e2[2]; |
tmat[i * 6 + 0][i * 6 + 2] = tmat[i * 6 + 3][i * 6 + 5] = Mt->nodes[nodes[i]].e3[0]; |
tmat[i * 6 + 1][i * 6 + 2] = tmat[i * 6 + 4][i * 6 + 5] = Mt->nodes[nodes[i]].e3[1]; |
tmat[i * 6 + 2][i * 6 + 2] = tmat[i * 6 + 5][i * 6 + 5] = Mt->nodes[nodes[i]].e3[2]; |
} |
} |
} |
/** |
function calculates the volume of tetrahedron |
@param x0,y0,z0 - coordinates of first node |
@param x1,y1,z1 - coordinates of second node |
@param x2,y2,z2 - coordinates of third node |
@param x3,y3,z3 - coordinates of fourth node |
@return The function returns volume of the tetrahedron defined by 4 nodes |
JV 3.2021 |
*/ |
inline double tetralattice::tetVol(double x0, double y0, double z0, double x1, double y1, double z1, double x2, double y2, double z2, double x3, double y3, double z3) const |
{ |
return ((x1 - x0) * (y2 - y0) * (z3 - z0) + (y1 - y0) * (z2 - z0) * (x3 - x0) + (z1 - z0) * (x2 - x0) * (y3 - y0) - |
(z1 - z0) * (y2 - y0) * (x3 - x0) - (x1 - x0) * (z2 - z0) * (y3 - y0) - (y1 - y0) * (x2 - x0) * (z3 - z0)) / 6.0; |
} |
void tetralattice::largest_eigenfrequency (long lcid, long eid) |
{ |
long i,k,ri=0,ci=0; |
vector d(ASTCKVEC(ndofe)),nv(ASTCKVEC(ndofe)); |
intpoints *ip; |
integratedquant iq; |
iq = locstress; |
ip = new intpoints [tnip]; |
// loop over all DOFs |
for (i=0;i<ndofe;i++){ |
// zde je treba vygenerovat spravny vektor uzlovych posunuti d |
// vypocet deformaci |
// tato funkce ma navic posledni argument |
// ten tam v potu tvare dodam, ale zaroven to budu |
// muset udelat na vsech prvcich, aby se to prelozilo |
ip_strains2 (lcid, eid, ri, ci, ip); |
// vypocet napeti |
// nova funkce |
for (k=0;k<tnip;k++) |
Mm->computenlstresses (k,ip[k]); |
// vypocet uzlovych sil |
elem_integration2 (iq,lcid,eid,ri,ci,nv,ip); |
// zde bude plneni matice tuhosti |
} |
// zde se sestavi matice hmotnosti |
// zde se zavola rutina na vypocet nejvetsi frekvence |
} |
/trunk/SIFEL/MEFEL/SRC/tetralattice.h |
---|
1,92 → 1,92 |
#ifndef TETRADISCR_H |
#define TETRADISCR_H |
#include "alias.h" |
#include "intpoints.h" |
struct matrix; |
struct vector; |
struct ivector; |
/** |
class tetradiscr defines tetrahedral elements for lattice discrete models |
8. 2. 2021, JK |
*/ |
class tetralattice |
{ |
public: |
tetralattice(void); |
~tetralattice(void); |
/// number of DOFs per node |
long ndof; |
/// number of DOFs on the element |
long ndofe; |
/// number of nodes on one element |
long nne; |
/// total number of components of the strain and stress tensors |
long tncomp; |
/// total number of integration points on element |
long tnip; |
/// number of approximated functions on the element |
long napfun; |
/// number of edges on one element |
long ned; |
/// number of nodes on one edge |
long nned; |
/// number of surfaces |
long nsurf; |
/// number of nodes on one surface |
long nnsurf; |
/// array of orders of integration of stiffness matrix |
long** intordsm; |
/// order of integration of mass matrix |
long intordmm; |
/// order of numerical interation on surfaces |
long intordb; |
/// array of numbers of integration points in sets |
long** nip; |
/// number of blocks |
long nb; |
/// array of numbers of components of blocks |
long* ncomp; |
/// cumulative array of numbers of components of blocks |
long* cncomp; |
/// stress/strain state |
strastrestate ssst; |
/// nodes belonging to edge - matrix [ned][2] |
long nbe[6][2]; |
/// edge belonging to facet - vector [tnip] |
long ebf[12]; |
/// nodes belonging to surface of the element - matrix [nsurf][nnsurf] |
long nbs[4][3]; |
/// lines belonging to surface of the element (with accordance to nbe) - matrix [nsurf][nnsurf] |
long ebs[4][3]; |
/// edge-nodes belonging to surface of the element - matrix [nsurf][nnsurf] (corresponding to the oposite node in nbs matrix) |
long enbs[4][3]; |
/// surface belonging to facet - vector [tnip] |
long sbf[12]; |
/// nodes belonging to facet - matrix [tnip][2] |
long nbf[12][2]; |
void create_facets(long eid, matrix& mm); |
void geom_matrix(long eid, matrix& B); |
void internal_forces(long lcid, long eid, long ri, long ci, vector& ifor); |
void elem_integration(integratedquant iq, long lcid, long eid, long ri, long ci, vector& nv); |
void elem_integration2(integratedquant iq, long lcid, long eid, long ri, long ci, vector& nv, intpoints *ip); |
void compute_nlstress(long lcid, long eid, long ri, long ci); |
void strains(long lcid, long eid, long ri, long ci); |
void ip_strains(long lcid, long eid, long ri, long ci); |
void ip_strains2(long lcid, long eid, long ri, long ci, intpoints *ip); |
void transf_matrix(ivector& nodes, matrix& tmat); |
void largest_eigenfrequency (long lcid, long eid); |
private: |
inline double tetVol(double x0, double y0, double z0, double x1, double y1, double z1, double x2, double y2, double z2, double x3, double y3, double z3) const; |
}; |
#endif |
#ifndef TETRADISCR_H |
#define TETRADISCR_H |
#include "alias.h" |
#include "intpoints.h" |
struct matrix; |
struct vector; |
struct ivector; |
/** |
class tetradiscr defines tetrahedral elements for lattice discrete models |
8. 2. 2021, JK |
*/ |
class tetralattice |
{ |
public: |
tetralattice(void); |
~tetralattice(void); |
/// number of DOFs per node |
long ndof; |
/// number of DOFs on the element |
long ndofe; |
/// number of nodes on one element |
long nne; |
/// total number of components of the strain and stress tensors |
long tncomp; |
/// total number of integration points on element |
long tnip; |
/// number of approximated functions on the element |
long napfun; |
/// number of edges on one element |
long ned; |
/// number of nodes on one edge |
long nned; |
/// number of surfaces |
long nsurf; |
/// number of nodes on one surface |
long nnsurf; |
/// array of orders of integration of stiffness matrix |
long** intordsm; |
/// order of integration of mass matrix |
long intordmm; |
/// order of numerical interation on surfaces |
long intordb; |
/// array of numbers of integration points in sets |
long** nip; |
/// number of blocks |
long nb; |
/// array of numbers of components of blocks |
long* ncomp; |
/// cumulative array of numbers of components of blocks |
long* cncomp; |
/// stress/strain state |
strastrestate ssst; |
/// nodes belonging to edge - matrix [ned][2] |
long nbe[6][2]; |
/// edge belonging to facet - vector [tnip] |
long ebf[12]; |
/// nodes belonging to surface of the element - matrix [nsurf][nnsurf] |
long nbs[4][3]; |
/// lines belonging to surface of the element (with accordance to nbe) - matrix [nsurf][nnsurf] |
long ebs[4][3]; |
/// edge-nodes belonging to surface of the element - matrix [nsurf][nnsurf] (corresponding to the oposite node in nbs matrix) |
long enbs[4][3]; |
/// surface belonging to facet - vector [tnip] |
long sbf[12]; |
/// nodes belonging to facet - matrix [tnip][2] |
long nbf[12][2]; |
void create_facets(long eid, matrix& mm); |
void geom_matrix(long eid, matrix& B); |
void internal_forces(long lcid, long eid, long ri, long ci, vector& ifor); |
void elem_integration(integratedquant iq, long lcid, long eid, long ri, long ci, vector& nv); |
void elem_integration2(integratedquant iq, long lcid, long eid, long ri, long ci, vector& nv, intpoints *ip); |
void compute_nlstress(long lcid, long eid, long ri, long ci); |
void strains(long lcid, long eid, long ri, long ci); |
void ip_strains(long lcid, long eid, long ri, long ci); |
void ip_strains2(long lcid, long eid, long ri, long ci, intpoints *ip); |
void transf_matrix(ivector& nodes, matrix& tmat); |
void largest_eigenfrequency (long lcid, long eid); |
private: |
inline double tetVol(double x0, double y0, double z0, double x1, double y1, double z1, double x2, double y2, double z2, double x3, double y3, double z3) const; |
}; |
#endif |
/trunk/SIFEL/MEFEL/SRC/vectorcnamem.cpp |
---|
0,0 → 1,179 |
#include "vectorcnamem.h" |
#include "iotools.h" |
#include <stdlib.h> |
// names of a general %vector component indices for particular states |
const char*vector_cnamem::vect_indices_bar[] = {"x", "y", "z"}; |
const char*vector_cnamem::vect_indices_plbeam[] = {"x", "z", "ry"}; |
const char*vector_cnamem::vect_indices_spbeam[] = {"x", "y", "z", "rx", "ry", "ry"}; |
const char*vector_cnamem::vect_indices_plane[] = {"x", "y"}; |
const char*vector_cnamem::vect_indices_plate[] = {"z", "rx", "ry"};; |
const char*vector_cnamem::vect_indices_shell[] = {"x", "y", "z", "rx", "ry", "ry"}; |
const char*vector_cnamem::vect_indices_space[] = {"x", "y", "z"}; |
// names of a displacement %vector indices for particular states |
const char*vector_cnamem::displvec_comp_names_bar[] = {"u", "v", "w"}; |
const char*vector_cnamem::displvec_comp_names_plbeam[] = {"u", "w", "phi_y"}; |
const char*vector_cnamem::displvec_comp_names_spbeam[] = {"u", "v", "w", "phi_x", "phi_y", "phi_z"}; |
const char*vector_cnamem::displvec_comp_names_plane[] = {"u", "v"}; |
const char*vector_cnamem::displvec_comp_names_plate[] = {"w", "phi_x", "phi_y"}; |
const char*vector_cnamem::displvec_comp_names_shell[] = {"u", "v", "w", "phi_x", "phi_y", "phi_z"}; |
const char*vector_cnamem::displvec_comp_names_space[] = {"u", "v", "w"}; |
// names of a load %vector indices for particular states |
const char*vector_cnamem::reactvec_comp_names_bar[] = {"R_x", "R_y", "R_z"}; |
const char*vector_cnamem::reactvec_comp_names_plbeam[] = {"R_x", "R_z", "Mr_y"}; |
const char*vector_cnamem::reactvec_comp_names_spbeam[] = {"R_x", "R_y", "R_z", "Mr_x", "Mr_y", "Mr_z"}; |
const char*vector_cnamem::reactvec_comp_names_plane[] = {"R_x", "R_y"}; |
const char*vector_cnamem::reactvec_comp_names_plate[] = {"R_z", "Mr_x", "Mr_y"}; |
const char*vector_cnamem::reactvec_comp_names_shell[] = {"R_x", "R_y", "R_z", "Mr_x", "Mr_y", "Mr_z"}; |
const char*vector_cnamem::reactvec_comp_names_space[] = {"R_x", "R_y", "R_z"}; |
/** |
The function returns pointer to string with indices for the given vector component. |
@param[in] ssst - tensor stress/strain state |
@param[in] compid - required %vector component |
@return The function returns pointer to string representation of the required %vector component |
Created by Tomas Koudelka, 10.2023 |
*/ |
const char*vector_cnamem::vect_indstr(strastrestate ssst, long compid) |
{ |
const char *ret = NULL; |
switch (ssst){ |
case bar: |
ret = vect_indices_bar[compid]; |
break; |
case plbeam: |
ret = vect_indices_plbeam[compid]; |
break; |
case spacebeam: |
ret = vect_indices_spbeam[compid]; |
break; |
case planestress: |
case planestrain: |
case axisymm: |
case planecontact: |
ret = vect_indices_plane[compid]; |
break; |
case platek: |
case plates: |
ret = vect_indices_plate[compid]; |
break; |
case shell: |
ret = vect_indices_shell[compid]; |
break; |
case spacestress: |
ret = vect_indices_space[compid]; |
break; |
default: |
print_err("unknown stress/strain state %d is required", __FILE__, __LINE__, __func__, int(ssst)); |
abort(); |
} |
return ret; |
} |
/** |
The function returns pointer to string with label for the given displacement vector component. |
@param[in] ssst - tensor stress state |
@param[in] compid - required displacement %vector component |
@return The function returns pointer to string representation of the required displacement %vector component. |
Created by Tomas Koudelka, 10.2023 |
*/ |
const char*vector_cnamem::displ_cmpstr(strastrestate ssst, long compid) |
{ |
const char *ret = NULL; |
switch (ssst){ |
case bar: |
ret = displvec_comp_names_bar[compid]; |
break; |
case plbeam: |
ret = displvec_comp_names_plbeam[compid]; |
break; |
case spacebeam: |
ret = displvec_comp_names_spbeam[compid]; |
break; |
case planestress: |
case planestrain: |
case planecontact: |
case axisymm: |
ret = displvec_comp_names_plane[compid]; |
break; |
case plates: |
case platek: |
ret = displvec_comp_names_plate[compid]; |
break; |
case shell: |
ret = displvec_comp_names_shell[compid]; |
break; |
case spacestress: |
ret = displvec_comp_names_space[compid]; |
break; |
default: |
print_err("unknown stress state %d is required", __FILE__, __LINE__, __func__, int(ssst)); |
abort(); |
} |
return ret; |
} |
/** |
The function returns pointer to string with label for the given stress tensor component in Voigt notation. |
@param[in] ssst - tensor stress state |
@param[in] compid - required tensor component, tensor storage in Voigt notation is considered |
@return The function returns pointer to string representation of the required tensor component |
Created by Tomas Koudelka, 10.2023 |
*/ |
const char*vector_cnamem::react_cmpstr(strastrestate ssst, long compid) |
{ |
const char *ret = NULL; |
switch (ssst){ |
case bar: |
ret = reactvec_comp_names_bar[compid]; |
break; |
case plbeam: |
ret = reactvec_comp_names_plbeam[compid]; |
break; |
case spacebeam: |
ret = reactvec_comp_names_spbeam[compid]; |
break; |
case planestress: |
case planestrain: |
case planecontact: |
case axisymm: |
ret = reactvec_comp_names_plane[compid]; |
break; |
case platek: |
case plates: |
ret = reactvec_comp_names_plate[compid]; |
break; |
case shell: |
ret = reactvec_comp_names_shell[compid]; |
break; |
case spacestress: |
ret = reactvec_comp_names_space[compid]; |
break; |
default: |
print_err("unknown strain state %d is required", __FILE__, __LINE__, __func__, int(ssst)); |
abort(); |
} |
return ret; |
} |
/trunk/SIFEL/MEFEL/SRC/vectorcnamem.h |
---|
0,0 → 1,80 |
#ifndef VECTORCNAMEM |
#define VECTORCNAMEM |
#include "alias.h" |
/** |
Class that defines nodal %vector component names for mechanical problems. |
It involves index names of a general %vectors and particular component names for |
the displacement and reaction vectors that are defined with respect to the given |
stress/strain state. |
Created by Tomas Koudelka, 10.2023 |
*/ |
class vector_cnamem |
{ |
public: |
// |
// General %vector indices for particular states |
// |
/// vector indices for uniaxial stress/strain state |
static const char*vect_indices_bar[]; |
/// vector indices for arrays on 2D beam |
static const char*vect_indices_plbeam[]; |
/// vector indices for arrays on 3D beam |
static const char*vect_indices_spbeam[]; |
/// vector indices for plane stress/strain, plane contact and axisymmetric states |
static const char*vect_indices_plane[]; |
/// vector indices for stress/strain state in Kirchoff's and Mindlin plates |
static const char*vect_indices_plate[]; |
/// vector indices for shell state |
static const char*vect_indices_shell[]; |
/// vector indices for fully 3D state |
static const char*vect_indices_space[]; |
// |
// names of displacement %vector components for particular states |
// |
/// names of displacement %vector component for uniaxial stress/strain state |
static const char*displvec_comp_names_bar[]; |
/// names of displacement %vector components for arrays on 2D beam |
static const char*displvec_comp_names_plbeam[]; |
/// names of displacement %vector components for arrays on 3D beam |
static const char*displvec_comp_names_spbeam[]; |
/// names of displacement %vector components for plane stress/strain, plane contact and axisymmetric states |
static const char*displvec_comp_names_plane[]; |
/// names of displacement %vector components for stress/strain state in Kirchoff's and Mindlin plates |
static const char*displvec_comp_names_plate[]; |
/// names of displacement %vector components for shell state |
static const char*displvec_comp_names_shell[]; |
/// names of displacement %vector components for fully 3D state |
static const char*displvec_comp_names_space[]; |
// |
// names of reaction %vector components for particular states |
// |
/// names of reaction %vector components for uniaxial stress/strain state |
static const char*reactvec_comp_names_bar[]; |
/// names of reaction %vector components for arrays on 2D beam |
static const char*reactvec_comp_names_plbeam[]; |
/// names of reaction %vector components for arrays on 3D beam |
static const char*reactvec_comp_names_spbeam[]; |
/// names of reaction %vector components for plane stress/strain, plane contact and axisymmetric states |
static const char*reactvec_comp_names_plane[]; |
/// names of reaction %vector components for stress/strain state in Kirchoff's and Mindlin plates |
static const char*reactvec_comp_names_plate[]; |
/// names of reaction %vector components for shell state |
static const char*reactvec_comp_names_shell[]; |
/// names of reaction %vector components for fully 3D state |
static const char*reactvec_comp_names_space[]; |
/// returns pointer to string with indices for the given second order tensor component |
static const char*vect_indstr(strastrestate ssst, long compid); |
/// returns pointer to string with labels for the given displacement %vector component |
static const char*displ_cmpstr(strastrestate ssst, long compid); |
/// returns pointer to string with labels for the given load/reaction %vector component |
static const char*react_cmpstr(strastrestate ssst, long compid); |
}; |
#endif |
/trunk/SIFEL/MEFEL/SRC/vecttens.cpp |
---|
7,6 → 7,7 |
#include <stdlib.h> |
/** |
Function creates tensor components from %vector components. |
645,6 → 646,58 |
/** |
The function returns full-length stress/strain %vector (6 components) from the reduced |
stress/strain %vector (ncompstr components). |
. |
@param[out] fv - full length %vector (6 components) |
@param[in] rv - array of reduced %vector (ncompstr components) |
@param ssst - stress/strain state indicator |
@return The function returns full-length %vector components in the argument rv |
Created by Tomas Koudelka 11.2.2014 |
*/ |
void give_full_vector(vector &fv, double *rv, strastrestate ssst) |
{ |
switch (ssst){ |
case bar:{ |
fv[0]=rv[0]; |
break; |
} |
case plbeam:{ |
break; |
} |
case planecontact:{ |
fv[0] = rv[0]; |
fv[1] = rv[1]; |
break; |
} |
case planestress:{ |
fv[0]=rv[0]; fv[1]=rv[1]; fv[5]=rv[2]; fv[2]=rv[3]; |
break; |
} |
case planestrain:{ |
fv[0]=rv[0]; fv[1]=rv[1]; fv[5]=rv[2]; fv[2]=rv[3]; |
break; |
} |
case axisymm:{ |
fv[0]=rv[0]; fv[1]=rv[1]; fv[2]=rv[2]; fv[5]=rv[3]; |
break; |
} |
case spacestress:{ |
fv[0]=rv[0]; fv[1]=rv[1]; fv[2]=rv[2]; |
fv[3]=rv[3]; fv[4]=rv[4]; fv[5]=rv[5]; |
break; |
} |
default: |
print_err("unknown strain state is required", __FILE__, __LINE__, __func__); |
} |
} |
/** |
Function creates auxiliary %matrix m |
(useful for thermal strains, pore pressure, etc.) |
1011,7 → 1064,7 |
@retval spacestress for ncomp=6 |
@retval -1 for any other ncomp value |
Created by Tomas Koudelka, koudelka@cml.fsv.cvut.cz, 4.10.2007 |
Created by Tomas Koudelka, tomas.koudelka@fsv.cvut.cz, 4.10.2007 |
*/ |
strastrestate guess_ssst(long ncomp) |
{ |
1034,6 → 1087,45 |
/** |
The function returns number of stress/strain array components depending on the stress/strain state indicator. |
@param[in] ssst - required stress/strain state indicator |
@return The function returns number of stress/strain array components for the given stress strain indicator. |
*/ |
long give_ncompstr(strastrestate ssst) |
{ |
switch (ssst){ |
case bar: |
return 1; |
case plbeam: |
return 3; |
case spacebeam: |
return 6; |
case planestress: |
case planestrain: |
return 4; |
case planecontact: |
return 2; |
case platek: |
case plates: |
return 3; |
case axisymm: |
return 4; |
case shell: |
return 6; |
case spacestress: |
return 6; |
default: |
print_err("unknown strain state is required", __FILE__, __LINE__, __func__); |
abort(); |
} |
return 0; |
} |
/** |
The function transforms the second order stress/strain tensor l given in the local coordinate system to |
tensor g in global coordinate system. Both tensors l and g are defined in the %vector engineering |
notation but transformation %matrix T(3,3) must be given in the form x_g = T x_l where x_l(3) and x_g(3) |
1319,14 → 1411,14 |
is defined in the %vector engineering notation but transformation %matrix T(3,3) must be given in |
the form x_g = T x_l where x_l(3) and x_g(3) are local and global vectors respectively. |
@param g - 2-nd order stress/strain tensor in the %vector engineering notation defined in |
the global coordinate system (input) |
@param l - i-th component 2-nd order stress/strain tensor in the %vector engineering notation defined in |
the local coordinate system (output) |
@param i - index of required stress/strain component in the egineering notation |
@param tmat - transformation %matrix T(3,3) |
@param ssst - stress/strain state indicator - defines the number of g and l components |
@param stra - stress/strain indicator - defines whether g and l represents stresses or strains |
@param[in] g - 2-nd order stress/strain tensor in the %vector engineering notation defined in |
the global coordinate system |
@param[out] l - i-th component 2-nd order stress/strain tensor in the %vector engineering notation defined in |
the local coordinate system (output) |
@param[in] i - index of required stress/strain component in the egineering notation |
@param[in] tmat - transformation %matrix T(3,3) |
@param[in] ssst - stress/strain state indicator - defines the number of g and l components |
@param[in] stra - stress/strain indicator - defines whether g and l represents stresses or strains |
*/ |
void gl_comp_engvectortransf (const vector &g, double &l, long i, const matrix &tmat, strastrestate ssst, strastre stra) |
{ |
1540,12 → 1632,12 |
engineering notation (G(6,6), L(6,6) but transformation %matrix T(3,3) must be given in the form |
x_g = T x_l where x_l(3) and x_g(3) are local and global vectors respectively. |
@param g[in] - 4-th order stiffness tensor in the %matrix engineering notation g(6,6) defined in |
the global coordinate system |
@param l[out] - 4-th order stiffness tensor in the %matrix engineering notation l(6,6) defined in |
the local coordinate system (input) |
@param tmat - transformation %matrix T(3,3) |
@param ssst - stress/strain state indicator - defines the number of g and l components |
@param[in] g - 4-th order stiffness tensor in the %matrix engineering notation g(6,6) defined in |
the global coordinate system |
@param[out] l - 4-th order stiffness tensor in the %matrix engineering notation l(6,6) defined in |
the local coordinate system (input) |
@param[in] tmat - transformation %matrix T(3,3) |
@param[in] ssst - stress/strain state indicator - defines the number of g and l components |
*/ |
void gl_tens4transf (const matrix &g, matrix &l, const matrix &tmat, strastrestate /*ssst*/) |
{ |
1629,9 → 1721,9 |
lv(4) = tau_zx |
lv(5) = tau_xy |
@param lv - long %vector |
@param sv - short %vector (output) |
@param ssst - strain/stress state |
@param[in] lv - long %vector |
@param[out] sv - short %vector (output) |
@param[in] ssst - strain/stress state |
@return The function returns required short %vector in the parameter sv. |
1701,7 → 1793,7 |
lv(4) = tau_zx |
lv(5) = tau_xy |
@param lv - %vector of components |
@param[in] lv - %vector of stress components |
17. 4. 2015, JK |
*/ |
1715,6 → 1807,27 |
return j2; |
} |
/** |
The function computes second invariant of a deviator of a strain tensor. |
The input %vector contains engineering components of the strain tensor. |
Components of the strain deviator are not needed on input. |
Ordering of components is shown on the example of strains |
lv(0) = eps_x |
lv(1) = eps_y |
lv(2) = eps_z |
lv(3) = gamma_yz |
lv(4) = gamma_zx |
lv(5) = gamma_xy |
@param[in] lv - %vector of strain components in Voigt's notation |
@return The function returns the resulting deviator in the argument dev. |
17. 4. 2015, JK |
*/ |
double j2_strain_invar (vector &lv) |
{ |
double j2; |
1726,16 → 1839,17 |
} |
/** |
function computes deviatoric part of the tensor |
The function computes deviatoric part of the given tensor in Voigt's notation. |
@param tens - engineering components of the tensor |
@param dev - engineering components of the deviator of the tensor |
@param[in] tens - engineering components of the tensor, i.e. tensor in Voigt's notation |
@param[out] dev - engineering components of the deviator of the tensor, i.e. deviator in Voigt's notation |
both vectors contain 6 components |
this function cannot know the actual number of components |
the actual components have to be determined outside of this function |
Both vectors must contain 6 components, because this function cannot know the actual number of components, |
the actual components have to be determined outside of this function. |
28.10.2001, modified 21. 4. 2015 |
@return The function returns the resulting deviator in the argument dev. |
28.10.2001, modified 21. 4. 2015 |
*/ |
void deviator (vector &tens,vector &dev) |
{ |
1752,20 → 1866,24 |
dev(5) = tens(5); |
} |
/** |
function computes first invariant of a tensor |
input is a %vector with 6 engineering components of the tensor |
The function computes first invariant of a tensor. |
Input is a %vector with 6 engineering components of the tensor, i.e. tensor in Voigt's notation. |
@param tens - engineering components of the tensor |
@param[in] tens - engineering components of the tensor |
tens(0) = tens_11 |
tens(1) = tens_22 |
tens(2) = tens_33 |
tens(3) = tens_23 |
tens(4) = tens_32 |
tens(5) = tens_13 |
tens(0) = tens_11 |
tens(1) = tens_22 |
tens(2) = tens_33 |
tens(3) = tens_23 |
tens(4) = tens_32 |
tens(5) = tens_13 |
4.1.2002 |
@return The function returns a value of the first invariant of the given tensor tens. |
4.1.2002 |
*/ |
double first_invar (vector &tens) |
{ |
1774,12 → 1892,17 |
return inv; |
} |
/** |
function computes second invariant of a stress tensor |
The function computes second invariant of a stress tensor. |
Input is a %vector with six engineering components of the tensor, i.e. tensor in Voigt's notation. |
@param tens - engineering components of the stress tensor |
@param[in] tens - engineering components of the stress tensor |
4.1.2002 |
@return The function returns a value of the first invariant of the given tensor tens. |
4.1.2002 |
*/ |
double second_stress_invar (vector &tens) |
{ |
1790,12 → 1913,17 |
return inv; |
} |
/** |
function computes third invariant of a stress tensor |
The function computes third invariant of a stress tensor. |
Input is a %vector with six engineering components of the tensor, i.e. tensor in Voigt's notation. |
@param tens - engineering components of stress tensor |
@param[in] tens - engineering components of stress tensor |
4.1.2002 |
@return The function returns a value of the first invariant of the given tensor tens. |
4.1.2002 |
*/ |
double third_stress_invar (vector &tens) |
{ |
1812,10 → 1940,12 |
return inv; |
} |
/** |
function computes second invariant of a strain tensor |
@param tens - engineering components of the strain tensor |
@param[in] tens - engineering components of the strain tensor |
4.1.2002 |
*/ |
1831,7 → 1961,7 |
/** |
function computes third invariant of a strain tensor |
@param tens - engineering components of strain tensor |
@param[in] tens - engineering components of strain tensor |
4.1.2002 |
*/ |
1854,7 → 1984,7 |
/** |
The function returns norm of stress tensor given in Voigt notation. |
@param sig - stress components in Voigt notation |
@param[in] sig - stress components in Voigt notation |
@return The function returns norm of stress tensor. |
1960,3 → 2090,53 |
return; |
} |
/** |
The function computes the first invariant of the second order tensor. |
@param[in] tens - tensor components stored as a %matrix 3x3 |
@return The function returns the first invariant value. |
*/ |
double first_invar (matrix &t) |
{ |
double inv = t(0,0) + t(1,1) + t(2,2); |
return inv; |
} |
/** |
The function computes the second invariant of the second order tensor t, which |
is defined as T11*T22 + T11*T33 + T22*T33 - T12^2 - T13^2 - T23^2. |
@param[in] tens - tensor components stored as a %matrix 3x3 |
@return The function returns the second invariant value. |
*/ |
double second_invar (matrix &t) |
{ |
double inv = t(0,0)*t(1,1) + t(0,0)*t(2,2) + t(1,1)*t(2,2); |
inv -= t(0,1)*t(0,1) + t(0,2)*t(0,2) + t(1,2)*t(1,2); |
return inv; |
} |
/** |
The function computes the third invariant of the second order tensor, which is |
defined as det|T|. |
@param[in] tens - tensor components stored as a %matrix 3x3 |
@return The function returns the third invariant value. |
*/ |
double third_invar (matrix &t) |
{ |
double inv = t(0,0)*t(1,1)*t(2,2) + t(0,1)*t(1,2)*t(2,0) + t(0,2)*t(1,0)*t(2,1); |
inv -= t(0,2)*t(1,1)*t(2,0) + t(0,0)*t(1,2)*t(2,1) + t(0,1)*t(1,0)*t(2,2); |
return inv; |
} |
/trunk/SIFEL/MEFEL/SRC/vecttens.h |
---|
35,6 → 35,9 |
/// returns guess of stress/strain state depending on the number of components |
strastrestate guess_ssst(long ncomp); |
/// returns number of stress/strain array components depending on the stress/strain indicator |
long give_ncompstr(strastrestate ssst); |
// converts long %vector to reduced %vector |
//void longvect_shortvect (double *lv,double *sv,strastrestate ssst); |
59,6 → 62,9 |
/// converts reduced stress/strain %vector to full-length %vector |
void give_full_vector(double *fv, double *rv, strastrestate ssst); |
/// converts reduced stress/strain %vector to full-length %vector |
void give_full_vector(vector &fv, double *rv, strastrestate ssst); |
/// transforms stress/strain %vector l given in the local coordinate system to stress/strain %vector g in global coordinate system (g = T . l) |
void lg_engvectortransf (vector &g, const vector &l, const matrix &tmat, strastrestate ssst, strastre str); |
90,4 → 96,8 |
void normed_stress_tensor(vector &t, vector &nt); |
void normed_strain_tensor(vector &eps, vector &neps); |
double first_invar (matrix &t); |
double second_invar (matrix &t); |
double third_invar (matrix &t); |
#endif |
/trunk/SIFEL/Makefile.in |
---|
60,7 → 60,7 |
# compiler flags which suppress some annoying repeated warnings |
# these options are not printed during compilation process by default |
COMPATFLAGS = -Wno-write-strings -Wno-unused-but-set-variable -Wno-unused-result -MMD |
COMPATFLAGS = -std=c++11 -Wno-write-strings -Wno-unused-but-set-variable -Wno-unused-result -MMD |
# setup for tracing line coverage with the help of gcov |
#COMPATFLAGS = -Wno-write-strings -Wno-unused-but-set-variable -Wno-unused-result --coverage -fprofile-arcs -ftest-coverage -pg |
130,7 → 130,7 |
# add default system libraries needed by all targets |
# (-lm = math library; -rdynamic = enforce including all symbol tables; -ldl = default shared libary support) |
SYS_LIBS = -L/usr/local/lib/../lib64 -lm -rdynamic -ldl |
SYS_LIBS = -lm -rdynamic -ldl |
# setup for the tracing of line coverage with the help of gcov |
# SYS_LIBS = -lm -rdynamic -ldl -lgcov --coverage |
/trunk/SIFEL/zipsif |
---|
8,6 → 8,6 |
echo Creating backup file prg$FNAME.zip with following files $FILETYPES |
zip -R prg$FNAME $FILETYPES -x 691/\* EXAM/\* GEFEL/PETSC/\* ARCHIVES/\* EXAMPLES/\* WORK/\* |
zip -R prg$FNAME $FILETYPES -x 691/\* EXAM/\* GEFEL/PETSC/\* GEFEL/CHOLMOD/\* ARCHIVES/\* EXAMPLES/\* WORK/\* |
echo Backup file prg$FNAME.zip was created |