Subversion Repositories sifel

Compare Revisions

Ignore whitespace Rev 784 → Rev 785

/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", &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", &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