Subversion Repositories sifel

Compare Revisions

Ignore whitespace Rev 777 → Rev 778

/trunk/SIFEL/GEFEL/matrix.cpp
3382,9 → 3382,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];
}
}
/trunk/SIFEL/MEFEL/SRC/Makefile
37,7 → 37,7
SRCS += cebfip78.cpp cebfipcontactmat.cpp chen.cpp consol.cpp contactmat.cpp cpsolver.cpp creep.cpp creep_b3.cpp creep_dpl.cpp
SRCS += creepb.cpp creepdam.cpp creep_effym.cpp creep_rspec.cpp crsec2dbar.cpp crsec2dbeam.cpp
SRCS += crsec3d.cpp crsec3dbeam.cpp crseclayer.cpp crsecnod.cpp crsecplstr.cpp cusatismaterial.cpp damplast.cpp damplastifacemat.cpp dkq.cpp dkt.cpp dloadcase.cpp
SRCS += dloadn.cpp dloadel.cpp dloadpd.cpp drprag.cpp doubdp.cpp drprag2.cpp dst.cpp edgem.cpp edsolver.cpp effstress.cpp eigvalsol.cpp elastgmat2d.cpp elastgmat3d.cpp
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
/trunk/SIFEL/MEFEL/SRC/alias.h
150,7 → 150,7
// aliases for material models
enum mattype {elisomat=1,elgmat3d=2,elortomat=3,elgmat2d=4, homomatm=9,
simplas1d=10,jflow=11,mohrcoulparab=22,mohrcoul=24,
boermaterial=25,druckerprager=26,doubledrprager=27,druckerprager2=28,modcamclaymat=30, modcamclaycoupmat=31,bbmcoupmat=33,
boermaterial=25,druckerprager=26,doubledrprager=27,druckerprager2=28,modcamclaymat=30, modcamclaycoupmat=31,bbmcoupmat=33,doublestructuremat=34,
shefpl=40,chenplast=42, hissplasmat=45,
microplaneM4=50,microsimp=51,microfibro=52,
simvisplas=70,simvisc=71,isovisc=72,lemaitr=75,
170,7 → 170,7
const enumstr mattypestr[] = {{"elisomat",1}, {"elgmat3d",2}, {"elortomat",3}, {"elgmat2d",4},{"homomatm",9},{"simplas1d",10},
{"jflow",11}, {"mohrcoulparab",22},
{"mohrcoul",24}, {"boermaterial",25}, {"druckerprager",26}, {"doubledrprager",27}, {"druckerprager2",28},
{"modcamclaymat",30}, {"modcamclaycoupmat",31}, {"bbmcoupmat",33}, {"shefpl",40}, {"chenplast",42}, {"hissplasmat",45},
{"modcamclaymat",30}, {"modcamclaycoupmat",31}, {"bbmcoupmat",33}, {"doublestructuremat",34}, {"shefpl",40}, {"chenplast",42}, {"hissplasmat",45},
{"microplaneM4",50}, {"microsimp",51}, {"microfibro",52},
{"simvisc",71}, {"isovisc",72}, {"lemaitr",75},
{"layerplate",80},
/trunk/SIFEL/MEFEL/SRC/bbm.cpp
1,6 → 1,7
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
 
#include "bbm.h"
#include "global.h"
#include "probdesc.h"
7,12 → 8,14
#include "mechmat.h"
#include "vecttens.h"
#include "intpoints.h"
#include "matrix.h"
#include "vector.h"
#include "tensor.h"
#include "elastisomat.h"
#include "mathem.h"
#include "nonlinman.h"
 
 
 
/**
This constructor inializes attributes to zero values.
*/
24,6 → 27,15
c1_tilde = 0.0;
c2 = 0.0;
ks = 0.0;
 
//pr_suc_f = no;
//pr_tempr_f = no;
 
kappa_s0 = 0.0;
aks1 = 0.0;
aks2 = 0.0;
a0 = 0.0;
a2 = 0.0;
}
 
 
49,6 → 61,21
{
xfscanf (in, "%k%lf%k%lf%k%lf", "m", &m, "lambda", &lambda, "kappa", &kappa);
xfscanf (in, "%k%lf%k%lf%k%lf", "c1_tilde", &c1_tilde, "c2", &c2, "ks", &ks);
 
//preparation for the total stresses (net stress) concept and the temperature effect:
 
//xfscanf (in, "%k%lf", "kappa_s0", &kappa_s0);
//xfscanf (in, "%k%lf%k%lf", "aks1", &aks1, "aks2", &aks2);
//xfscanf (in, "%k%lf%k%lf", "a0", &a0, "a2", &a2);
 
//xfscanf(in, "%k%m", "presc_suction", &answertype_kwdset, &pr_suc_f);
//if (pr_suc_fl == yes)
//suc_fn.read(in);
 
//xfscanf(in, "%k%m", "presc_tempr", &answertype_kwdset, &pr_tempr_f);
//if (pr_tempr_fl == yes)
//tempr_fn.read(in);
 
sra.read (in);
}
 
57,63 → 84,121
with respect of consistency parameter gamma.
 
@param ipp - integration point number
@param im - index of material type for given ip
@param ido - index of internal variables for given material in the ipp other array
 
12/06/2012 TKo
*/
void bbmmat::initval(long ipp, long ido)
void bbmmat::initval(long ipp, long im, long ido)
{
double v_ini, i1s, v_pc0, v_lambda1;
double v_kappa1, p1, pc_0;
double v_ini, v_pc0, v_lambda1;
double i1s, j2s, s;
double v_kappa1, p1, bar_pc_0, pc_0;
long i, ncompstr = Mm->ip[ipp].ncompstr;
vector epse(ASTCKVEC(ncompstr)), sig(ASTCKVEC(ncompstr)),sigt(ASTCKVEC(6));
matrix d(ASTCKMAT(ncompstr, ncompstr));
vector sig(ASTCKVEC(ncompstr)),sigt(ASTCKVEC(6)), q(ASTCKVEC(2));
double err=sra.give_err ();
// variables used for the calculation of initial value of preconsolidation pressure for the fully saturated state
double a, b, fs, ksi, sr, qq, p_atm = 101325.0;
 
if (Mm->ip[ipp].eqother[ido+ncompstr+1] == 0.0) // actual value of p_c was not set
{
// initial value of specific volume under small pressure p_1
v_kappa1 = Mm->ic[ipp][0];
// initial value of specific volume under small pressure p_1 on the normal consolidation line (v_lambda1 = 1+N)
v_lambda1 = Mm->ic[ipp][0];
// initial reference presure
p1 = Mm->ic[ipp][1];
// initial effective preconsolidation pressure
pc_0 = Mm->ic[ipp][2];
p1 = Mm->ic[ipp][1];
// initial effective preconsolidation pressure \bar{p}_{c0}}
bar_pc_0 = Mm->ic[ipp][2];
 
// initial value of elastic strain
for (i=0; i<ncompstr; i++)
epse[i] = Mm->ip[ipp].strain[i] = Mm->ic[ipp][3+i];
// initial effective stresses
if ((Mp->eigstrains == 4) || (Mp->eigstrains == 5)){
for (i=0; i<ncompstr; i++)
sig(i) = Mm->ip[ipp].stress[i] = Mm->eigstresses[ipp][i];
}
else{
print_err("initial effective stresses (eigentsresses) are not defined on element %ld, ip=%ld,\n"
" cannot determine specific volume for initial stress state", __FILE__, __LINE__, __func__, Mm->elip[ipp]+1, ipp+1);
abort();
}
 
// elastic stiffness matrix
Mm->elmatstiff(d, ipp, ido);
// initial value of stress
mxv(d, epse, sig);
//add initial value of effective stresses
for (i=0; i<ncompstr; i++)
Mm->ip[ipp].stress[i] += sig[i];
 
//vector_tensor (sig,sigt,Mm->ip[ipp].ssst,stress);
give_full_vector (sigt, sig, Mm->ip[ipp].ssst);
// initial value of mean stress
i1s = first_invar(sigt)/3.0;
q(0) = bar_pc_0;
s = Mm->givenonmechq(suction, ipp); // suction pressure s
sr = Mm->givenonmechq(saturation_degree, ipp); // degree of saturation S_r
//limitation of positive suction
if(s >=0.0)
s=0.0;
s = fabs(s);
q(1) = ks*s;
// test if the initial state is elastic, if not calculate new value of inital effective preconsolidation pressure pc_0 so the OCR=1
if (yieldfunction(sigt, q) > err){
j2s = j2_stress_invar (sigt);
bar_pc_0 = j2s/(m*m*(i1s-q(1))) + i1s;
}
 
// specific volume for initial effective preconsolidation pressure
v_pc0 = v_kappa1 - kappa*log(pc_0/p1);
//
// Calculation of inital value of preconsolidation pressure for the fully saturated state pc_0
//
// suction function:
//
// s / p_{atm}
// f(s) = 1 + -----------------------
// 10.7 + 2.4(s / p_{atm})
//
fs = 1.0 + (s/p_atm) / (10.7 + 2.4*(s/p_atm));
if (fs < 1.0)
fs = 1.0;
// bonding variable:
//
// \ksi = f(s) (1 - S_r)
//
ksi = (1-sr)*fs;
 
// according to Gallipoli
qq = 1.0 - c1_tilde*(1.0 - exp(c2*ksi)); // e/e_s
a = (qq - 1.0)/(lambda*qq - kappa)*(v_lambda1 - 1.0);
b = (lambda - kappa)/(lambda*qq - kappa);
pc_0 = -pow(-bar_pc_0 /exp(a), 1.0/b);
 
// compute initial value of specific volume
v_pc0 = v_lambda1 - lambda*log(pc_0/p1);
 
// actual value of p_c = initial effective preconsolidtaion pressure
Mm->ip[ipp].other[ido+ncompstr+1] = Mm->ip[ipp].eqother[ido+ncompstr+1] = pc_0;
// original specific volume before any loading
Mm->ip[ipp].other[ido+ncompstr+3] = Mm->ip[ipp].eqother[ido+ncompstr+3] = v_lambda1 = v_pc0 + lambda*log(pc_0/p1);
Mm->ip[ipp].other[ido+ncompstr+1] = Mm->ip[ipp].eqother[ido+ncompstr+1] = bar_pc_0;
Mm->ip[ipp].other[ido+ncompstr+2] = Mm->ip[ipp].eqother[ido+ncompstr+2] = q(1);
// initial value of specific volume under small pressure p_1 on the swelling line (v_{\kappa l}) at the fully saturated state
Mm->ip[ipp].other[ido+ncompstr+3] = Mm->ip[ipp].eqother[ido+ncompstr+3] = v_kappa1 = v_pc0 + kappa*log(pc_0/p1);
// specific volume for intial stress state
Mm->ip[ipp].other[ido+ncompstr+4] = Mm->ip[ipp].eqother[ido+ncompstr+4] = v_ini = v_pc0 + kappa*log(pc_0/i1s);
// intial mean stress
Mm->ip[ipp].other[ido+ncompstr+5] = Mm->ip[ipp].eqother[ido+ncompstr+5] = i1s;
// saturation degree
Mm->ip[ipp].other[ido+ncompstr+9] = Mm->ip[ipp].eqother[ido+ncompstr+9] = Mm->givenonmechq(saturation_degree, ipp); // degree of saturation S_r
// initial depsv_dt
Mm->ip[ipp].other[ido+ncompstr+10] = Mm->ip[ipp].eqother[ido+ncompstr+10] = 0.0;
// porosity n for intial stress state
Mm->ip[ipp].other[ido+ncompstr+11] = Mm->ip[ipp].eqother[ido+ncompstr+11] = (v_ini-1.0)/v_ini; // v_ini = 1.0 + e_ini
// suction for intial stress state
Mm->ip[ipp].other[ido+ncompstr+12] = Mm->ip[ipp].eqother[ido+ncompstr+12] = Mm->givenonmechq(suction, ipp); // suction pressure s
// suction
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);
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
Mm->ip[ipp].other[ido+ncompstr+14] = Mm->ip[ipp].eqother[ido+ncompstr+14] = 1.0;
// set inital stiffness matrix
matrix d;
makerefm(d, Mm->ip[ipp].other+ido+ncompstr+15, ncompstr, ncompstr);
Mm->elmatstiff(d, ipp, ido);
copym(d, Mm->ip[ipp].eqother+ido+ncompstr+15);
check_math_errel(Mm->elip[ipp]);
 
check_math_errel(0);
 
return;
}
 
121,7 → 206,7
/**
This function computes the value of yield functions.
 
@param sig - stress tensor in Voigt notation
@param sig - full stress tensor in Voigt notation (6 components)
@param q - %vector of hardening parameter
 
@retval The function returns value of yield function for the given stress tensor
146,9 → 231,9
This function computes derivatives of as-th yield function
with respect of vector sigma.
 
@param sig - stress tensor in Voigt notation
@param sig - stress tensor in Voigt notation (6 components)
@param q - %vector of the hardening parameter
@param dfds - %matrix where the resulting derivatives are stored
@param dfds - %vector where the resulting derivatives are stored (6 components)
 
 
4.1.2002
189,9 → 274,10
ddfds[0][0] = ddfds[1][1] = ddfds[2][2] = 2.0/(3.0*m*m) + 2.0/9.0;
ddfds[0][1] = ddfds[0][2] = ddfds[1][0] = ddfds[1][2] = -1.0/(3.0*m*m) + 2.0/9.0;
ddfds[2][0] = ddfds[2][1] = ddfds[0][1];
ddfds[3][3] = 1.0/(m*m);
ddfds[4][4] = 1.0/(m*m);
ddfds[5][5] = 1.0/(m*m);
// doubled shear components due to tensor-> vector transformation
ddfds[3][3] = 2.0/(m*m);
ddfds[4][4] = 2.0/(m*m);
ddfds[5][5] = 2.0/(m*m);
}
 
 
202,11 → 288,11
 
@param sig - stress tensor
@param q - %vector of the hardening parameters
@param dgds - %matrix where the resulting derivatives are stored
@param ddgds - %matrix where the resulting derivatives are stored
*/
void bbmmat::derpotsigma (vector &sig, vector &q, vector &dgds)
void bbmmat::derpotsigma (vector &sig, vector &q, vector &ddgds)
{
deryieldfsigma (sig, q, dgds);
deryieldfsigma (sig, q, ddgds);
}
 
 
242,17 → 328,17
The function computes the second derivatives of yield function
with respect to hradening parameters.
 
@param dfds - %matrix, where the resulting derivatives are stored
@param ddfdq - %matrix, where the resulting derivatives are stored
 
 
Created by Tomas Koudelka, 09.2012
*/
void bbmmat::deryieldfdqdq(matrix &dfq)
void bbmmat::deryieldfdqdq(matrix &ddfdq)
{
dfq[0][0] = 0.0;
dfq[0][1] = 1.0;
dfq[1][0] = 1.0;
dfq[1][1] = 0.0;
ddfdq[0][0] = 0.0;
ddfdq[0][1] = 1.0;
ddfdq[1][0] = 1.0;
ddfdq[1][1] = 0.0;
 
return;
}
284,31 → 370,51
 
@param ipp - integration point number
@param ido - index of internal variables for given material in the ipp other array
@param sig - stress tensor
@param sig - full stress tensor
@param qtr - %vector of hardening variables
@param epsp - %vector of attained plastic strains
@param dqdg - %vector where the resulting derivatives are stored in Voigt notation
 
 
Created by Tomas Koudelka, 09.2012
*/
void bbmmat::der_q_gamma(long ipp, long ido, vector &sig, vector &qtr, vector &dqdg)
void bbmmat::der_q_gamma(long ipp, long ido, vector &sig, vector &qtr, vector &epsp, vector &dqdg)
{
double v_ini, v_lambda1, i1s;
double p_atm = 101.3250;
double v_ini, v_lambda1, v_kappa1, p1, i1s, epsvp;
double p_atm = 101325.0;
double s, sr, fs, b, c, c1, ksi;
long ncompstr = Mm->ip[ipp].ncompstr;
strastrestate ssst = Mm->ip[ipp].ssst;
vector epst(ASTCKVEC(6));
// mean stress
i1s = first_invar (sig)/3.0;
// original specific volume before any loading
v_lambda1 = Mm->ip[ipp].eqother[ido+ncompstr+3];
// initial value of specific volume under small pressure p_1 for the normal consolidation line (v_{\lambda 1} = N)
v_lambda1 = Mm->ic[ipp][0];
// initial reference presure
p1 = Mm->ic[ipp][1];
// initial value of specific volume under small pressure p_1 for the swelling line (v_{\kappa 1})
v_kappa1 = Mm->ip[ipp].eqother[ido+ncompstr+3];
// specific volume for intial stress state
v_ini = Mm->ip[ipp].eqother[ido+ncompstr+4];
 
s = Mm->givenonmechq(suction, ipp); // suction pressure s
//limitation of positive suction
if(s >=0.0)
s=0.0;
s = fabs(s);
sr = Mm->givenonmechq(saturation_degree, ipp); // degree of saturation S_r
 
// actual value of preconsolidation pressure for the fully saturated state
give_full_vector (epst, epsp, ssst);
epsvp = first_invar(epst);
//double pc_new = p1 * exp((v_kappa1 - v_lambda1 + v_ini*epsvp)/(kappa-lambda));
// specific volume for the actual preconsolidation pressure:
//
// v_{pc} = v_{\lambda1} - \lambda \ln(p_c/p_1)
// double v_pc = v_lambda1 - lambda * log(pc_new/p1);
 
// suction function:
//
// s / p_{atm}
316,6 → 422,8
// 10.7 + 2.4(s / p_{atm})
//
fs = 1.0 + (s/p_atm) / (10.7 + 2.4*(s/p_atm));
if (fs < 1.0)
fs = 1.0;
 
// bonding variable:
//
327,10 → 435,12
// c_1 = --------------------
// 1
// -------------- + 1
// v_{\lambda1}-1
c1 = c1_tilde/(1.0/(v_lambda1-1.0)+1.0);
// v_{pc}-1
 
// c1 = c1_tilde/(1.0/(v_pc-1.0)+1.0); // according to Borja
c1 = c1_tilde; // according to Gallipoli
 
 
//
// c(\ksi) = 1 - c_1 [1-\exp(c_2 \ksi)]
//
346,25 → 456,27
 
// q[0] = \bar{p}_c = -\exp[a(\ksi)] (-p_c)^{b(\ksi)}
//
// p_c = p_1 exp[(v_{\kappa} - v_{\lambda_1})/(\kappa - \lambda)]
// p_c = p_1 exp[(v_{\kappa_1} - v_{\lambda_1} + eps_{vp} v_{ini})/(\kappa - \lambda)]
//
// v_{\kappa} = v_{ini} (1+\eps_v) + \kappa \ln(p/p_1) => depends on p => depends on gamma
// p_1 = const
// p_{c0} = const
// \sigma_{m0} = const
// v_{\kappa_1} = const
// v_{p_{c0}} = v_{\kappa_1} - \kappa \ln(p_{c0}/p_1) = const
// v_{ini} = v_{p_{c0}} + \kappa \ln(p_{c0}/\sigma_{m0}) = const
// v_{\lambda_1} = v_{p_{c0}} - \lambda \ln(p_{c0}/p_1) = const
//
// v_{ini} = v_{p_{c0}} + \kappa \ln(p_{c0}/p_{ini}) = const
// v_{\lambda_1} = v_{p_{c0}} + \lambda \ln(p_{c0}/p_1) = const
// v_{p_{c0}} = v_{\kappa_1} - \kappa \ln(p_{c0}/p_1) = const
//
// d \bar{p}_c d p_c
// ----------- = \exp[a(\ksi)] b(\ksi)(-p_c)^{b(\ksi)-1} ----------,
// d \gamma d \gamma
// d \bar{p}_c d p_c (-p_c)^{b(\ksi)} d p_c
// ----------- = -\exp[a(\ksi)] b(\ksi)(-p_c)^{b(\ksi)-1} ---------- = -\exp[a(\ksi)] b(\ksi) ---------------- ---------- ,
// d \gamma d \gamma p_c d \gamma
//
// d p_c v_ini
// ---------- = p_c ----------------- (2p - \bar{p}_c - p_s),
// d \gamma \kappa - \lambda
//
// d \bar{p}_c b(\ksi) v_ini
// ----------- = -\bar{p}_c ---------------- (2p - \bar{p}_c - p_s)
// d \gamma \kappa - \lambda
// d \bar{p}_c b(\ksi) v_ini
// ----------- = -\bar{p}_c ---------------- (2p - \bar{p}_c - p_s)
// d \gamma \kappa - \lambda
//
//
dqdg[0] = -qtr[0] * (b*v_ini)/(kappa-lambda) * (2.0*i1s-qtr[0]-qtr[1]);
384,6 → 496,273
 
 
/**
The function computes derivatives of hardening paramters
with respect of consistency parameter gamma.
 
@param ipp - integration point number
@param ido - index of internal variables for given material in the ipp other array
@param sig - full stress tensor
@param qtr - %vector of hardening variables
@param epsp - %vector of attained plastic strains
@param dqdgds - %matrix where the resulting derivatives are stored in Voigt notation,
its dimensions must be qtr.n x 6
 
 
Created by Tomas Koudelka, 05.2022
*/
void bbmmat::dqpardgammadsigma(long ipp, long ido, vector &sig, vector &qtr, vector &epsp, matrix &dqdgds)
{
double v_ini, v_lambda1, v_kappa1, p1, i1s, epsvp;
double p_atm = 101325.0;
double s, sr, fs, b, c, c1, ksi;
long ncompstr = Mm->ip[ipp].ncompstr;
strastrestate ssst = Mm->ip[ipp].ssst;
vector epst(ASTCKVEC(6));
// mean stress
i1s = first_invar (sig)/3.0;
// initial value of specific volume under small pressure p_1 for the normal consolidation line (v_{\lambda 1} = N)
v_lambda1 = Mm->ic[ipp][0];
// initial reference presure
p1 = Mm->ic[ipp][1];
// initial value of specific volume under small pressure p_1 for the swelling line (v_{\kappa 1})
v_kappa1 = Mm->ip[ipp].eqother[ido+ncompstr+3];
// specific volume for intial stress state
v_ini = Mm->ip[ipp].eqother[ido+ncompstr+4];
 
s = Mm->givenonmechq(suction, ipp); // suction pressure s
//limitation of positive suction
if(s >=0.0)
s=0.0;
s = fabs(s);
sr = Mm->givenonmechq(saturation_degree, ipp); // degree of saturation S_r
 
// actual value of preconsolidation pressure for the fully saturated state
give_full_vector (epst, epsp, ssst);
epsvp = first_invar(epst);
//double pc_new = p1 * exp((v_kappa1 - v_lambda1 + v_ini*epsvp)/(kappa-lambda));
// specific volume for the actual preconsolidation pressure:
//
// v_{pc} = v_{\lambda1} - \lambda \ln(p_c/p_1)
//double v_pc = v_lambda1 - lambda * log(pc_new/p1);
 
// suction function:
//
// s / p_{atm}
// f(s) = 1 + -----------------------
// 10.7 + 2.4(s / p_{atm})
//
fs = 1.0 + (s/p_atm) / (10.7 + 2.4*(s/p_atm));
if (fs < 1.0)
fs = 1.0;
 
// bonding variable:
//
// \ksi = f(s) (1 - S_r)
//
ksi = (1-sr)*fs;
 
// \tilde{c}_1
// c_1 = --------------------
// 1
// -------------- + 1
// v_{pc}-1
 
// c1 = c1_tilde/(1.0/(v_pc-1.0)+1.0); // according to Borja
c1 = c1_tilde; // according to Gallipoli
 
 
//
// c(\ksi) = 1 - c_1 [1-\exp(c_2 \ksi)]
//
c = 1.0 - c1*(1.0-exp(c2*ksi));
 
//
// \lambda - \kappa
// b(\ksi) = --------------------------
// \lambda c(\ksi) - \kappa
//
b = (lambda - kappa)/(lambda*c - kappa);
 
 
// q[0] = \bar{p}_c = -\exp[a(\ksi)] (-p_c)^{b(\ksi)}
//
// p_c = p_1 exp[(v_{\kappa_1} - v_{\lambda_1} + eps_{vp} v_{ini})/(\kappa - \lambda)]
//
// p_1 = const
// p_{c0} = const
// \sigma_{m0} = const
// v_{\kappa_1} = const
// v_{p_{c0}} = v_{\kappa_1} - \kappa \ln(p_{c0}/p_1) = const
// v_{ini} = v_{p_{c0}} + \kappa \ln(p_{c0}/\sigma_{m0}) = const
// v_{\lambda_1} = v_{p_{c0}} - \lambda \ln(p_{c0}/p_1) = const
//
// d \bar{p}_c d p_c (-p_c)^{b(\ksi)} d p_c
// ----------- = -\exp[a(\ksi)] b(\ksi)(-p_c)^{b(\ksi)-1} ---------- = -\exp[a(\ksi)] b(\ksi) ---------------- ---------- ,
// d \gamma d \gamma p_c d \gamma
//
// d p_c v_ini
// ---------- = p_c ----------------- (2p - \bar{p}_c - p_s),
// d \gamma \kappa - \lambda
//
// d \bar{p}_c b(\ksi) v_ini
// ----------- = -\bar{p}_c ---------------- (2p - \bar{p}_c - p_s)
// d \gamma \kappa - \lambda
//
//
// dqdg(0) = -qtr[0] * (b*v_ini)/(kappa-lambda) * (2.0*i1s-qtr[0]-qtr[1]);
dqdgds(0,0) = dqdgds(0,1) = dqdgds(0,2) = -qtr[0] * (b*v_ini)/(kappa-lambda) * 2.0/3.0;
 
 
// q[1] = p_s = k*s
//
// d p_s
// ----------- = 0.0 because p_s is constant for the given strain level
// d \gamma
//
dqdgds(1,0) = dqdgds(1,1) = dqdgds(1,2) = dqdgds(1,3) = dqdgds(1,4) = dqdgds(1,5) = 0.0;
 
return;
}
 
 
 
/**
The function computes derivatives of hardening paramters
with respect of consistency parameter gamma.
 
@param ipp - integration point number
@param ido - index of internal variables for given material in the ipp other array
@param sig - full stress tensor
@param qtr - %vector of hardening variables
@param epsp - %vector of attained plastic strains
@param dqdgds - %matrix where the resulting derivatives are stored, its dimensions must be qtr.n x qtr.n
 
 
Created by Tomas Koudelka, 05.2022
*/
void bbmmat::dqpardgammadqpar(long ipp, long ido, vector &sig, vector &qtr, vector &epsp, matrix &dqdgdq)
{
double v_ini, v_lambda1, v_kappa1, p1, i1s, epsvp;
double p_atm = 101325.0;
double s, sr, fs, b, c, c1, ksi;
long ncompstr = Mm->ip[ipp].ncompstr;
strastrestate ssst = Mm->ip[ipp].ssst;
vector epst(ASTCKVEC(6));
// mean stress
i1s = first_invar (sig)/3.0;
// initial value of specific volume under small pressure p_1 for the normal consolidation line (v_{\lambda 1} = N)
v_lambda1 = Mm->ic[ipp][0];
// initial reference presure
p1 = Mm->ic[ipp][1];
// initial value of specific volume under small pressure p_1 for the swelling line (v_{\kappa 1})
v_kappa1 = Mm->ip[ipp].eqother[ido+ncompstr+3];
// specific volume for intial stress state
v_ini = Mm->ip[ipp].eqother[ido+ncompstr+4];
 
s = Mm->givenonmechq(suction, ipp); // suction pressure s
//limitation of positive suction
if(s >=0.0)
s=0.0;
s = fabs(s);
sr = Mm->givenonmechq(saturation_degree, ipp); // degree of saturation S_r
 
// actual value of preconsolidation pressure for the fully saturated state
give_full_vector (epst, epsp, ssst);
epsvp = first_invar(epst);
//double pc_new = p1 * exp((v_kappa1 - v_lambda1 + v_ini*epsvp)/(kappa-lambda));
// specific volume for the actual preconsolidation pressure:
//
// v_{pc} = v_{\lambda1} - \lambda \ln(p_c/p_1)
//double v_pc = v_lambda1 - lambda * log(pc_new/p1);
 
// suction function:
//
// s / p_{atm}
// f(s) = 1 + -----------------------
// 10.7 + 2.4(s / p_{atm})
//
fs = 1.0 + (s/p_atm) / (10.7 + 2.4*(s/p_atm));
if (fs < 1.0)
fs = 1.0;
 
// bonding variable:
//
// \ksi = f(s) (1 - S_r)
//
ksi = (1-sr)*fs;
 
// \tilde{c}_1
// c_1 = --------------------
// 1
// -------------- + 1
// v_{pc}-1
 
// c1 = c1_tilde/(1.0/(v_pc-1.0)+1.0); // according to Borja
c1 = c1_tilde; // according to Gallipoli
 
 
//
// c(\ksi) = 1 - c_1 [1-\exp(c_2 \ksi)]
//
c = 1.0 - c1*(1.0-exp(c2*ksi));
 
//
// \lambda - \kappa
// b(\ksi) = --------------------------
// \lambda c(\ksi) - \kappa
//
b = (lambda - kappa)/(lambda*c - kappa);
 
 
// q[0] = \bar{p}_c = -\exp[a(\ksi)] (-p_c)^{b(\ksi)}
//
// p_c = p_1 exp[(v_{\kappa_1} - v_{\lambda_1} + eps_{vp} v_{ini})/(\kappa - \lambda)]
//
// p_1 = const
// p_{c0} = const
// \sigma_{m0} = const
// v_{\kappa_1} = const
// v_{p_{c0}} = v_{\kappa_1} - \kappa \ln(p_{c0}/p_1) = const
// v_{ini} = v_{p_{c0}} + \kappa \ln(p_{c0}/\sigma_{m0}) = const
// v_{\lambda_1} = v_{p_{c0}} - \lambda \ln(p_{c0}/p_1) = const
//
// d \bar{p}_c d p_c (-p_c)^{b(\ksi)} d p_c
// ----------- = -\exp[a(\ksi)] b(\ksi)(-p_c)^{b(\ksi)-1} ---------- = -\exp[a(\ksi)] b(\ksi) ---------------- ---------- ,
// d \gamma d \gamma p_c d \gamma
//
// d p_c v_ini
// ---------- = p_c ----------------- (2p - \bar{p}_c - p_s),
// d \gamma \kappa - \lambda
//
// d \bar{p}_c b(\ksi) v_ini
// ----------- = -\bar{p}_c ---------------- (2p - \bar{p}_c - p_s)
// d \gamma \kappa - \lambda
//
//
// dqdg(0) = -qtr[0] * (b*v_ini)/(kappa-lambda) * (2.0*i1s-qtr[0]-qtr[1]);
// wrong //dqdgdq(0,0) = 2.0*qtr[0] * (b*v_ini)/(kappa-lambda);
dqdgdq(0,0) = -(b*v_ini)/(kappa-lambda) * (2.0*i1s-2.0*qtr[0]-qtr[1]);
dqdgdq(0,1) = qtr[0] * (b*v_ini)/(kappa-lambda);
 
 
// q[1] = p_s = k*s
//
// d p_s
// ----------- = 0.0 because p_s is constant for the given strain level
// d \gamma
//
dqdgdq(1,0) = dqdgdq(1,1) = 0.0;
 
return;
}
 
 
 
/**
This function computes plastic modulus.
 
@param ipp - integration point number
390,12 → 769,13
@param ido - index of internal variables for given material in the ipp other array
@param sig - stress tensor in Voigt notation
@param qtr - %vector of hardening parameters
@param epsp - %vector of attained plastic strains
 
@retval The function returns value of the plastic modulus.
 
Created by Tomas Koudelka, 09.2012
*/
double bbmmat::plasmodscalar(long ipp, long ido, vector &sig, vector &qtr)
double bbmmat::plasmodscalar(long ipp, long ido, vector &sig, vector &qtr, vector &epsp)
{
double ret;
vector dfq(ASTCKVEC(2));
402,7 → 782,7
vector dqg(ASTCKVEC(2));
 
deryieldfq(sig, qtr, dfq);
der_q_gamma(ipp, ido, sig, qtr, dqg);
der_q_gamma(ipp, ido, sig, qtr, epsp, dqg);
scprd(dfq, dqg, ret);
 
return -ret;
428,18 → 808,18
vector epst(ASTCKVEC(6));
vector depsp(epsp.n);
double v_kappa1, v_lambda1, p1, depsvp, v_ini, pc_new;
double v_pc, p_atm = 101.3250;
double v_pc, p_atm = 101325.0;
double s, sr, fs, a, b, c, c1, ksi;
strastrestate ssst = Mm->ip[ipp].ssst;
long ncompstr = Mm->ip[ipp].ncompstr;
long i;
// initial value of specific volume under small pressure p_1
v_kappa1 = Mm->ic[ipp][0];
// initial value of specific volume under small pressure p_1 for the normal consolidation line (v_lambda1 = 1+N)
v_lambda1 = Mm->ic[ipp][0];
// initial reference presure
p1 = Mm->ic[ipp][1];
// original specific volume before any loading
v_lambda1 = Mm->ip[ipp].eqother[ido+ncompstr+3];
v_kappa1 = Mm->ip[ipp].eqother[ido+ncompstr+3];
// specific volume for intial stress state
v_ini = Mm->ip[ipp].eqother[ido+ncompstr+4];
 
452,9 → 832,11
// vk = v_ini*(1+epsv)+kappa*log(i1s/p1);
 
for (i=0; i<ncompstr; i++)
depsp[i] = epsp[i] + Mm->ic[ipp][3+i];
depsp[i] = epsp[i];// + Mm->ic[ipp][3+i];
 
give_full_vector(epst, depsp, ssst);
depsvp = first_invar(epst);
 
pc_new = p1 * exp((v_kappa1 - v_lambda1 + v_ini*depsvp)/(kappa-lambda));
 
// For the partially saturated soil,
471,6 → 853,9
v_pc = v_lambda1 - lambda * log(pc_new/p1);
 
s = Mm->givenonmechq(suction, ipp); // suction pressure s
//limitation of positive suction
if(s >=0.0)
s=0.0;
s = fabs(s);
sr = Mm->givenonmechq(saturation_degree, ipp); // degree of saturation S_r
 
481,6 → 866,8
// 10.7 + 2.4(s / p_{atm})
//
fs = 1.0 + (s/p_atm) / (10.7 + 2.4*(s/p_atm));
if (fs < 1.0)
fs = 1.0;
 
// bonding variable:
//
492,8 → 879,9
// c_1 = --------------------
// 1
// -------------- + 1
// v_{\lambda1}-1
c1 = c1_tilde/(1.0/(v_lambda1-1.0)+1.0);
// v_{pc}-1
// c1 = c1_tilde/(1.0/(v_pc-1.0)+1.0); // according to Borja
c1 = c1_tilde; // according to Gallipoli
 
 
//
502,9 → 890,9
c = 1.0 - c1*(1.0-exp(c2*ksi));
 
//
// a(\ksi) = v_ini v_{lambda_1} [c(\ksi)-1]/[\lambda c(\ksi) - \kappa)
// a(\ksi) = v_{lambda_1} [c(\ksi)-1]/[\lambda c(\ksi) - \kappa)
//
a = v_ini*v_lambda1*(c - 1.0)/(lambda*c - kappa);
a = (v_lambda1 - 1.0)*(c - 1.0)/(lambda*c - kappa);
 
//
// \lambda - \kappa
554,7 → 942,149
case secant_stiff:
case incr_tangent_stiff:
case ijth_tangent_stiff:{
// consistent tangent stiffness matrix
long n = Mm->ip[ipp].ncompstr;
if (sra.give_tsra() == cp){
// algorithmic consistent stiffness matrix for the cutting plane algorithm is computed in the course of stress return
if (d.m != n){ // material stiffness matrix used for element in the case of plane stress/strain states
for(long i=0; i<d.m; i++) // copy just the first d.n(=3) components at all matrix rows
memcpy(&d(i,0), Mm->ip[ipp].other+ido+n+15+n*i, d.n*sizeof(*Mm->ip[ipp].other));
}
else{ // dimensions of material stiffness matrix matches the ones for element material stiffness matrix
matrix auxm;
makerefm(auxm, Mm->ip[ipp].other+ido+n+15, n, n);
copym(auxm, d);
}
}
else{
// compute algorithmic stiffness matrix for closest point projection stress return algorithm
matrix de(ASTCKMAT(6, 6)), ddfdst(ASTCKMAT(6,6));
matrix e(ASTCKMAT(6, 6)), auxd(ASTCKMAT(6,6)), tmp(ASTCKMAT(6, 6));
double gamma = Mm->ip[ipp].other[ido+n];
identm(e);
Mm->elmatstiff(de, ipp, spacestress);
dderyieldfsigma(ddfdst);
cmulm(gamma, de, auxd);
mxm(auxd, ddfdst, tmp);
addm(e, tmp, auxd);
invm(auxd, tmp, zero);
mxm(tmp, de, auxd);
// matrix representation of the fourth order tensor
tensor4_ematrix(d, auxd, Mm->ip[ipp].ssst);
}
break;
}
}
}
 
 
 
/**
This function computes elasto-plastic material stiffnes matrix.
 
@param d - allocated matrix structure for material stiffness %matrix in the reduced format
@param ipp - integration point number
@param ido - index of internal variables for given material in the ipp other array
 
Created by Tomas Koudelka, 09.2012
*/
void bbmmat::depmatstiff (matrix &d, long ipp, long ido)
{
switch (Mp->nlman->stmat){
case initial_stiff:
// initial elastic matrix
Mm->elmatstiff(d, ipp, ido);
break;
case tangent_stiff:
case secant_stiff:
case incr_tangent_stiff:
case ijth_tangent_stiff:{
// consitent tangent stiffness matrix
long n = Mm->ip[ipp].ncompstr;
long ncompq = 2;
matrix de(ASTCKMAT(n, n)), auxm;
vector sig(ASTCKVEC(n)), q(ASTCKVEC(ncompq)), epsp(ASTCKVEC(n));
vector dfds(ASTCKVEC(n)), dgds(ASTCKVEC(n));
vector sigt(ASTCKVEC(6)), dfdst(ASTCKVEC(6)), dgdst(ASTCKVEC(6));
vector dedgds(ASTCKVEC(n)), dedfds(ASTCKVEC(n));
strastrestate ssst = Mm->ip[ipp].ssst;
double denomh, denomd, denom, gamma, f, err=sra.give_err();
 
// prepare actual values of needed quantities
copyv(Mm->ip[ipp].stress, sig); // stresses
copyv(Mm->ip[ipp].other+ido, epsp); // plastic strains
gamma = Mm->ip[ipp].other[ido+n+0]; // cumulated plastic multiplier
q(0) = Mm->ip[ipp].other[ido+n+1]; // hardening parameter \bar{p}_c
q(1) = Mm->ip[ipp].other[ido+n+2]; // hardening parameter k_s
give_full_vector(sigt, sig, ssst); // 6 component vector of stresses
 
// check actual stress state: f <= 0.0
f = yieldfunction(sigt, q);
if ((f < -err) || (gamma == 0.0 && (f < err))){
// stress state is in the elastic domain,
// i.e. material has been subjected by elastic loading/unloading ->
// -> return actual elastic stiffness matrix
Mm->elmatstiff(d, ipp, ssst);
return;
}
 
// stress state is on/close to the yield surface
// material has been subjected by plastic loading ->
 
// compute elasto-plastic matrix
 
// D_e \frac{dg}{d\sigma} (\frac{df}{d\sigma})^T D_e
// D_{ep} = D_e - ---------------------------------------------------
// (\frac{df}{d\sigma})^T D_e \frac{dg}{d\sigma} + H
//
// H = -\frac{df}{dq} \frac{dq}{d\lambda}
Mm->elmatstiff(de, ipp, ssst);
deryieldfsigma(sigt, q, dfdst);
derpotsigma(sigt, q, dgdst);
// conversion of full tensor notation to vector notation
give_red_vector(dfdst, dfds, ssst);
// conversion of full tensor notation to vector notation
give_red_vector(dgdst, dgds, ssst);
mxv(de,dgds,dedgds);
mxv(de,dfds,dedfds);
denomh = plasmodscalar(ipp, ido, sig, q, epsp);
scprd(dfds, dedgds, denomd);
// preserve minimum stiffness for perfect plastic material, i.e. if the hardening modulus is 'close' to zero (H->0)
// if (fabs(denomh/denomd) < 1.0e-3)
// denomh = sgn(denomh)*1.0e-3*denomd;
denom = denomd+denomh;
 
if (n == d.m){
// material stiffness matrix has identical dimensions with the ones of stiffness matrix used in
// assembling of element stiffness matrix on finite element -> auxm will be reference on matrix d
makerefm(auxm, d.a, d.m, d.n);
nullm(auxm);
}
else{
// material stiffness matrix has different dimensions than the stiffness matrix used in
// assembling of element stiffness matrix on finite element -> auxm will be reference on matrix d
reallocm(RSTCKMAT(n, n, auxm));
}
// calculate matrix in the nominator
vxv(dedgds, dedfds, auxm);
// scaling by the denominator
cmulm(1.0/denom, auxm);
// resulting material stiffness matrix
subm(de, auxm, auxm);
 
// resulting material stiffness matrix with dimensions adjusted for finite element computation
if (n != d.m){
// resulting material stiffness matrix dimensions must be adjusted for finite element computation
extractblock(auxm, d, 0, 0);
}
else{
// nothing is needed, matrix auxm is direct reference to the matrix in argument d
// hence d contains resulting material stiffness matrix with appropriate dimensions for
// the stiffness matrix on the finite element
}
/*
double zero=1.0e-20;
matrix de(ASTCKMAT(6, 6)), ddfdst(ASTCKMAT(6,6));
matrix e(ASTCKMAT(6, 6)), auxd(ASTCKMAT(6,6)), tmp(ASTCKMAT(6, 6));
long n = Mm->ip[ipp].ncompstr;
568,15 → 1098,129
invm(auxd, tmp, zero);
mxm(tmp, de, auxd);
// matrix representation of the fourth order tensor
tensor4_ematrix(d, auxd, Mm->ip[ipp].ssst);
tensor4_ematrix(d, auxd, Mm->ip[ipp].ssst);*/
break;
}
}
}
 
/**
The function computes stress increments due to suction and temperature changes 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 krejci, 02/2023
*/
void bbmmat::nlstressesincr (long ipp, long im, long ido)
//
{
double n,v,depss=0.0,depst=0.0,ds,s,kappa_s,lambda_s,p_atm = 101325.0,p,pc_ref;
// double temp=0.0,temp0=0.0,dtemp=0.0;
long i,ncomp;
// stress/strain state
strastrestate ss = Mm->ip[ipp].ssst;
ncomp=Mm->ip[ipp].ncompstr;
matrix d(ASTCKMAT(ncomp,ncomp));
vector depsv(ASTCKVEC(ncomp)),dsigma(ASTCKVEC(ncomp));
if (Mm->ip[ipp].tm[im-1] == effective_stress){
// In case of effective stresses concept, stress increments due to suction changes are included in eff_stress material
for (i=0;i<ncomp;i++)
Mm->ip[ipp].eqother[ido+ncomp+15+ncomp*ncomp+i] = 0.0;
}
else{
//stress increments are computed in case of total stresses concept (net stress) - not completed!!!
// suction change
//if (pr_suc_f == no){
// actual porosity n
n = Mm->ip[ipp].other[ido+ncomp+11];
// specific volume
v = 1/(1-n);
// suction increment
ds = Mm->givenonmechq(suction, ipp) - Mm->ip[ipp].eqother[ido+ncomp+12];
s = Mm->givenonmechq(suction, ipp);
//positive notation of suction
s = fabs(s);
// volume strain caused by a suction change
// 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
if(ds >= 0.0){//swelling
p = Mm->ip[ipp].eqother[ido+ncomp+5];//effective mean stress
pc_ref = Mm->ip[ipp].eqother[ido+ncomp+1]; //effective preconsolidation pressure
kappa_s = kappa_s0*(1+aks1*log(p/pc_ref))*exp(aks2*s);
depss = -kappa_s*ds/(3*v*(s+p_atm));//swelling
}
else{//shrinkage - not finished!!??
lambda_s = kappa_s0;//provisionally
depss = -lambda_s*ds/(3*v*(s+p_atm));//shrinkage
}
//}
// temperature change - not completed
//if (pr_tempr_f == no){
//temp = ???
//temp0 = ???
//dtemp = ???
//depst = (a0 + a2*(temp - temp0))*dtemp/3.0;
//}
//only uniaxial
if(ss==bar){
depsv[0]=depss+depst;
}
else{
depsv[0]=depss+depst;
depsv[1]=depss+depst;
}
if(ss==planestrain) depsv[3]=depss+depst;
if(ss==planestress) depsv[3]=depss+depst;
if(ss==axisymm) depsv[2]=depss+depst;
if(ss==spacestress) depsv[2]=depss+depst;
fillm(0.0,d);
matstiff (d, ipp, ido);
mxv (d,depsv,dsigma);
for (i=0;i<ncomp;i++)
Mm->ip[ipp].eqother[ido+ncomp+15+ncomp*ncomp+i] = dsigma(i);
}
}
 
 
/**
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 Krejci, 02/2023
*/
void bbmmat::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; j<sig.n; i++, j++)
sig(j) = Mm->ip[ipp].eqother[ido+ncomp+15+ncomp*ncomp+i];
}
 
 
 
/**
This function computes stresses at given integration point ipp,
depending on the reached strains.
The cutting plane algorithm is used. The stress and the other attribute of
583,6 → 1227,7
given integration point is actualized.
 
@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
 
Created by Tomas Koudelka, 09.2012
591,19 → 1236,19
//
{
int errr;
long i,ni,ncomp=Mm->ip[ipp].ncompstr;
double gamma,err;
long i,ni,ncomp=Mm->ip[ipp].ncompstr, matcomp=0, ret;
double gamma, err, pnewdt = 1.0;
vector epsn(ASTCKVEC(ncomp)), epsp(ASTCKVEC(ncomp)), q(ASTCKVEC(2));
vector epsa(ASTCKVEC(ncomp)), sig(ASTCKVEC(ncomp)), dfds(ASTCKVEC(ncomp)), dgds(ASTCKVEC(ncomp));
matrix d(ASTCKMAT(ncomp,ncomp));
matrix d;
vector dfdst(ASTCKVEC(6)), dgdst(ASTCKVEC(6));
vector epst(ASTCKVEC(6)), epsnt(ASTCKVEC(6)), epspt(ASTCKVEC(6)), sigt(ASTCKVEC(6));
//vector dev(ASTCKVEC(6));
double i1s, j2s, epsv, epsvp;
double dtime = Mp->timecon.actualforwtimeincr();
// double p_atm = 101.3250,s,ds;
vector epss(ASTCKVEC(ncomp));
matrix epsvs(ASTCKMAT(3,3));
// stress/strain state
//strastrestate ssst = Mm->ip[ipp].ssst;
//double nu;
 
// initial values
for (i=0; i<ncomp; i++)
610,30 → 1255,11
{
epsn[i] = Mm->ip[ipp].strain[i];
epsp[i] = Mm->ip[ipp].eqother[ido+i];
// epsp[i] += Mm->ic[ipp][3+i];
// It is necessary to substract initial strains in order to invoke initial nonzero stress
// state for zero displacements (i.e. zero strains)
// sig = E*(eps - eps_p), sig_0 = E*eps_0. For eps = 0: sig = sig_0 => eps_p = -eps_0
epsp[i] -= Mm->ic[ipp][3+i];
// epsp[i] -= Mm->ic[ipp][3+i];
}
 
//zde vlozeno??!!
//elastic swelling strains:
///////////////////////////////////////////////////
//s = Mm->givenonmechq(suction, ipp); // suction pressure s
//ds = s - Mm->ip[ipp].eqother[ido+ncomp+12];
//for (i=0;i<3;i++)
//epsvs[i][i] = -0.022/(1+0.6)*ds/(s+p_atm);
// convert total stress tensor back to vector form - epss
//tensor_vector(epss, epsvs, Mm->ip[ipp].ssst,stress);
 
//for (i=0; i<ncomp; i++)
//Mm->ip[ipp].strain[i] += epss[i];
///////////////////////////////////////////////////
 
 
gamma=Mm->ip[ipp].eqother[ido+ncomp];
q[0] = Mm->ip[ipp].eqother[ido+ncomp+1]; // effective preconsolidation pressure \bar{p}_c
q[1] = Mm->ip[ipp].eqother[ido+ncomp+2]; // apparent adhesion p_s = k * s
640,11 → 1266,18
 
// stress return algorithm
switch(sra.give_tsra ())
{
{
case cp:
ni=sra.give_ni ();
err=sra.give_err ();
Mm->cutting_plane (ipp, im, ido, gamma, epsn, epsp, q, ni, err);
matcomp = actualize_stiffmat(*Mp->nlman, Mp->istep, Mp->jstep);
if (Mp->istep >= 265){
matcomp = 0;
}
if (matcomp) reallocm(RSTCKMAT(ncomp, ncomp, d));
ret = Mm->cutting_plane (ipp, im, ido, gamma, epsn, epsp, q, ni, err, matcomp, d);
if (ret)
pnewdt = 0.5;
break;
case gsra:
ni=sra.give_ni ();
654,15 → 1287,43
default:
print_err("wrong type of stress return algorithm is required", __FILE__, __LINE__, __func__);
abort ();
}
/*
////////////////////////////////
// elastic material for debug!!??
// initial values
for (i=0;i<ncomp;i++){
epsn[i]=epsp[i]=Mm->ip[ipp].strain[i];
}
reallocm(RSTCKMAT(ncomp, ncomp, d));
Mm->elmatstiff (d,ipp,ssst);
nu = 0.3;
mxv (d,epsn,sig);
if (Mm->ip[ipp].ssst == planestress)
Mm->ip[ipp].strain[3] = -nu / (1.0 - nu) * (epsn[0]+epsn[1]);
if ((Mp->eigstrains == 4) || (Mp->eigstrains == 5))
{
for (i=0;i<ncomp;i++)
sig(i) += Mm->eigstresses[ipp][i];
}
for (i=0;i<ncomp;i++){
Mm->ip[ipp].stress[i]=sig(i);
}
////////////////////////////////
*/
 
 
// new data storage
for (i=0; i<ncomp; i++){
epsp[i] += Mm->ic[ipp][3+i];
//epsp[i] += Mm->ic[ipp][3+i];
Mm->ip[ipp].other[ido+i]=epsp[i];
}
Mm->ip[ipp].other[ido+ncomp]=gamma;
Mm->ip[ipp].other[ido+ncomp+1]=q[0]; // the first hardening parameter \bar{p}_c
Mm->ip[ipp].other[ido+ncomp+2]=q[1]; // the second hardening parameter p_s
// other[ido+ncomp+3] = v_lambda1; it is the initial value and therefore it does not require actualization
// other[ido+ncomp+4] = v_ini; it is the initial value and therefore it does not require actualization
 
Mm->givestress(0, ipp, sig);
 
670,14 → 1331,13
give_full_vector(epsnt,epsn,Mm->ip[ipp].ssst);
give_full_vector(epspt,epsp,Mm->ip[ipp].ssst);
 
//vector_tensor (sig,sigt,Mm->ip[ipp].ssst,strain);
//vector_tensor (epsn,epst,Mm->ip[ipp].ssst,strain);//tady??!!
//vector_tensor (epsp,epspt,Mm->ip[ipp].ssst,strain);
//deviator (sigt,dev);
i1s = first_invar (sigt)/3.0;
// the second invariant of deviator
// it is expressed with the help of the stress components
// components of the deviator are not needed
j2s = sqrt(j2_stress_invar (sigt));
 
epsv = first_invar (epsnt);//tady??!!
epsv = first_invar (epsnt);
epsvp = first_invar (epspt);
Mm->ip[ipp].other[ido+ncomp+5] = i1s;
Mm->ip[ipp].other[ido+ncomp+6] = j2s;
684,11 → 1344,15
Mm->ip[ipp].other[ido+ncomp+7] = epsv;
Mm->ip[ipp].other[ido+ncomp+8] = epsvp;
Mm->ip[ipp].other[ido+ncomp+9] = Mm->givenonmechq(saturation_degree, ipp);
Mm->ip[ipp].other[ido+ncomp+10] = (epsv - Mm->ip[ipp].eqother[ido+ncomp+7])/dtime;
// volumetric strain rate
//Mm->ip[ipp].other[ido+ncomp+10] = (epsv - Mm->ip[ipp].eqother[ido+ncomp+7])/dtime;
// the volumetric strain rate is computed via generalized trapesoidal rule
Mm->ip[ipp].other[ido+ncomp+10] = 0.5*((epsv - Mm->ip[ipp].eqother[ido+ncomp+7])/dtime + Mm->ip[ipp].eqother[ido+ncomp+10]);
 
// reference presure = p1
double p1 = Mm->ic[ipp][1];
// specific volume at the reference pressure p_1 = v_lambda1
double v_lambda1 = Mm->ip[ipp].eqother[ido+ncomp+3];
double v_lambda1 = Mm->ic[ipp][0];
// specific volume for the actual preconsolidation pressure = v_pc
double v_pc = v_lambda1 - lambda * log(q[0]/p1);
// specific volume for the actual pressure p
699,25 → 1363,79
v = v_pc + kappa*log(-q[0]);
// actual porosity n
Mm->ip[ipp].other[ido+ncomp+11] = (v-1.0)/v;
// suction
Mm->ip[ipp].other[ido+ncomp+12] = Mm->givenonmechq(suction, ipp);
// Young modulus
Mm->ip[ipp].other[ido+ncomp+13] = give_actual_ym(ipp, im, ido);
// time step scaling factor
Mm->ip[ipp].other[ido+ncomp+14] = pnewdt;
 
if (matcomp)
copym(d, Mm->ip[ipp].other+ido+ncomp+15);
 
errr = check_math_errel(Mm->elip[ipp]);
}
 
 
 
 
/**
Function returns flag whether actualize the stiffness matrix according to the setup of the nonlinear solver and
attained number of steps.
 
@param[in] smt - type of the stiffness matrix modification in NR method
@param[in] istep - number of load increment step in NR method
@param[in] jstep - number of inner iteration step in NR method
 
@retval 0 - in the case that actualization of the stiffness matrix is NOT required
@retval 1 - in the case that actualization of the stiffness matrix is required
*/
long bbmmat::actualize_stiffmat(const nonlinman &nlman, long istep, long jstep)
{
long ret = 0;
switch (nlman.stmat){
case initial_stiff:
break;
case tangent_stiff:
ret = 1;
break;
case secant_stiff:
case incr_tangent_stiff:{
if (jstep <= 0)
ret = 1;
break;
}
case ijth_tangent_stiff:{
if (((jstep <= 0) && (istep % nlman.ithstiffchange == 0)) ||
((jstep+1) % nlman.jthstiffchange == 0))
ret = 1;
break;
}
default:{
print_err("unknown type of stiffness matrix is required",__FILE__,__LINE__,__func__);
}
}
return ret;
}
 
 
 
/**
This 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
 
Created by Tomas Koudelka, 09.2012
*/
void bbmmat::updateval (long ipp,long ido)
void bbmmat::updateval (long ipp, long im, long ido)
{
long i,n = Mm->ip[ipp].ncompstr;
 
double e = comp_actual_ym(ipp, im, ido);
for (i=0;i<n;i++){
Mm->ip[ipp].eqother[ido+i]=Mm->ip[ipp].other[ido+i];
}
736,18 → 1454,174
Mm->ip[ipp].eqother[ido+n+7] = Mm->ip[ipp].other[ido+n+7]; // epsv;
Mm->ip[ipp].eqother[ido+n+8] = Mm->ip[ipp].other[ido+n+8]; // epsvp;
// saturation degree
Mm->ip[ipp].eqother[ido+n+9] = Mm->ip[ipp].other[ido+n+9]; // Sr
Mm->ip[ipp].eqother[ido+n+9] = Mm->ip[ipp].other[ido+n+9]; // Sr
// volumteric strain rate
Mm->ip[ipp].eqother[ido+n+10] = Mm->ip[ipp].other[ido+n+10]; // depsv/dt
Mm->ip[ipp].eqother[ido+n+10] = Mm->ip[ipp].other[ido+n+10]; // depsv/dt
// actual porosity n
Mm->ip[ipp].eqother[ido+n+11] = Mm->ip[ipp].other[ido+n+11];
// actual suction
Mm->ip[ipp].eqother[ido+n+12] = Mm->ip[ipp].other[ido+n+12];
// suction
Mm->ip[ipp].eqother[ido+n+12] = Mm->ip[ipp].other[ido+n+12]; //s
// Young modulus
Mm->ip[ipp].eqother[ido+n+13] = Mm->ip[ipp].other[ido+n+13] = e;
// time step scaling factor
Mm->ip[ipp].eqother[ido+n+14] = Mm->ip[ipp].other[ido+n+14];
// stiffness matrix
for (i=0;i<n*n;i++){
Mm->ip[ipp].eqother[ido+n+15+i] = Mm->ip[ipp].other[ido+n+15+i];
}
// stress increments - it is not needed
//for (i=0;i<n;i++){
//Mm->ip[ipp].eqother[ido+n+15+n*n+i]=Mm->ip[ipp].other[ido+n+15+n*n+i];
//}
}
 
 
 
/**
The function returns actual Young modulus value.
 
@param ipp - integration point number
@param im - index of material type for given ip
@param ido - index of internal variables for given material in the ipp other array
 
*/
double bbmmat::give_actual_ym(long ipp, long im, long ido)
{
long ncomp=Mm->ip[ipp].ncompstr;
double e = Mm->ip[ipp].other[ido+ncomp+13];
 
return e;
}
 
 
 
/**
The function computes actual Young modulus value.
 
@param ipp - integration point number
@param im - index of material type for given ip
@param ido - index of internal variables for given material in the ipp other array
 
*/
double bbmmat::comp_actual_ym(long ipp, long im, long ido)
{
long idem = Mm->ip[ipp].gemid();
long ncompo = Mm->givencompeqother(ipp, im);
double e;
 
// initial Young modulus
double e_ini = Mm->give_initial_ym(ipp, idem, ido+ncompo);
// actual Poisson's ratio
double nu = give_actual_nu(ipp, im, ido);
 
// actual values of strains
long ncomp=Mm->ip[ipp].ncompstr;
strastrestate ssst = Mm->ip[ipp].ssst;
//vector epsp(ASTCKVEC(ncomp));
vector epst(ASTCKVEC(6));
vector eps(ASTCKVEC(ncomp));
vector epsp(ASTCKVEC(ncomp));
vector sig(ASTCKVEC(ncomp));
vector q(ASTCKVEC(1));
 
// actual total volumetric strain
Mm->givestrain(0, ipp, eps);
give_full_vector(epst, eps, ssst);
double epsv = first_invar(epst);
// actual plastic volumteric strain
//Mm->giveother(ipp, ido, ncomp, epsp);
// total volumetric strain from the last converged step
double epsvo = Mm->ip[ipp].eqother[ido+ncomp+7];
// total volumetric plastic strain from the last converged step
double epsvpo = Mm->ip[ipp].eqother[ido+ncomp+8];
 
// actual plastic strain
for(long i=0; i<ncomp; i++)
epsp(i) = Mm->ip[ipp].other[ido];
give_full_vector(epst, epsp, ssst);
double epsvp = first_invar(epst);
 
// actual value of p_c
//updateq(ipp, ido, eps, epsp, sig, q);
//double pc = q(0);
double pc = Mm->ip[ipp].other[ido+ncomp+1];
 
/*
// initial value of elastic strain
for (long i=0; i<ncomp; i++)
eps(i) = Mm->ic[ipp][3+i];
give_full_vector(auxt, eps, ssst);
double epsv_ini = first_invar(auxt);
if (epsv >= epsv_ini)
return e_ini;*/
// actual value of of specific volume
double v_ini = Mm->ip[ipp].eqother[ido+ncomp+4];
//double v = v_ini*(1.0+epsv);
 
//double p = pc/exp((v-v_pc)/kappa);
double po = Mm->ip[ipp].eqother[ido+ncomp+5];
if ((po == 0.0) || (epsv == 0.0))
return e_ini;
if (po > pc){
// for the unloading: \Delta eps^{el}_V = \Delta eps_V
// actual p according actual swelling line
double epsve = (epsv-epsvo) - (epsvp - epsvpo);
double p = po*exp(-(epsve)*v_ini/kappa);
if (epsve == 0.0)
e = 3.0*(1.0-2.0*nu)*v_ini*(-p)/kappa;
else
e = 3.0*(1.0-2.0*nu)*(p-po)/(epsve);
}
else{
e = e_ini;
}
 
//e = 3.0*(1.0-2.0*nu)*v*(-p)/kappa;
 
return e;
}
 
 
 
/**
The function returns actual Poisson's ratio.
 
@param ipp - integration point number
@param im - index of material type for given ip
@param ido - index of internal variables for given material in the ipp other array
 
*/
double bbmmat::give_actual_nu(long ipp, long im, long ido)
{
long idem = Mm->ip[ipp].gemid();
long ncompo = Mm->givencompeqother(ipp, im);
double nu = Mm->give_initial_nu(ipp, idem, ido+ncompo);
 
return nu;
}
 
 
/**
The function returns time step scaling factor required by the 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 scaling factor provided by the bbmmat model
 
Created by Tomas Koudelka, 5.2022
*/
double bbmmat::dstep_red(long ipp, long im, long ido)
{
long ncomp = Mm->ip[ipp].ncompstr;
return (Mm->ip[ipp].other[ido+ncomp+14]);
}
 
 
 
/**
Function returns irreversible plastic strains.
 
@param ipp - integration point number in the mechmat ip array.
939,8 → 1813,12
*/
void bbmmat::give_reqnmq(long *anmq)
{
//if (pr_suc_f == no){
anmq[saturation_degree-1] = 1;
anmq[suction-1] = 1;
//}
//if (pr_tempr_f == no)
//anmq[temperature-1] = 1;
}
 
 
/trunk/SIFEL/MEFEL/SRC/bbm.h
1,12 → 1,17
#ifndef BBMMAT_H
#define BBMMAT_H
 
#include "iotools.h"
#include "galias.h"
#include "gfunct.h"
#include "xfile.h"
#include "alias.h"
#include "strretalg.h"
#include "matrix.h"
#include "vector.h"
struct matrix;
struct vector;
struct atsel;
class nonlinman;
 
 
/**
This class defines modified cam-clay material model
for coupling with moisture transfer. The material is defined by
17,7 → 22,7
 
Additionally, there are three parameters which controls
evolution of hardening with respect to degree of saturation and suction
c1_tilde, c2 - controls the ration of specific volumes v/v_sat (partially sturated/fully saturated)
c1_tilde, c2 - controls the ratio of specific volumes v/v_sat (partially saturated/fully saturated)
ks - controls apparent adhesion (intersection of yield surface with p axis)
In addition to these material constants, several initial values
26,11 → 31,11
unloading from initial consolidation pressure p_c0 (v_kappa0)
p1 - reference pressure (p_1), it must be negative
p_c0 - initial consolidation pressure, it must be negative
iepsp_1 -
sig0_1 -
. \
. \ components of initial plastic strains
. \ components of eigenstresses
. /
iepsp_ncomp -
sig0_ncomp -
Order of the eqother array components
id | description
59,7 → 64,7
bbmmat (void);
~bbmmat (void);
void read (XFILE *in);
void initval(long ipp, long ido);
void initval(long ipp, long im, long ido);
double cohesion(vector &qtr);
double yieldfunction (vector &sig, vector &q);
void deryieldfsigma (vector &sig, vector &q, vector &dfds);
66,15 → 71,25
void dderyieldfsigma (matrix &ddfds);
void derpotsigma (vector &sig, vector &q, vector &dgds);
void deryieldfq(vector &sig, vector &q, vector &dq);
void deryieldfdqdq(matrix &dfq);
void deryieldfdqdq(matrix &ddfdq);
void deryieldfdsdq(matrix &dfdsdqt);
void der_q_gamma(long ipp, long ido, vector &sig, vector &qtr, vector &dqdg);
double plasmodscalar(long ipp, long ido, vector &sig, vector &qtr);
void der_q_gamma(long ipp, long ido, vector &sig, vector &qtr, vector &epsp, vector &dqdg);
void dqpardgammadsigma(long ipp, long ido, vector &sig, vector &qtr, vector &epsp, matrix &dqdgds);
void dqpardgammadqpar(long ipp, long ido, vector &sig, vector &qtr, vector &epsp, matrix &dqdgdq);
double plasmodscalar(long ipp, long ido, vector &sig, vector &qtr, vector &epsp);
void updateq(long ipp, long ido, vector &eps, vector &epsp, vector &sig, vector &q);
// void updateq(vector &epsp, strastrestate ssst, vector &q);
void matstiff (matrix &d, long ipp,long ido);
void depmatstiff (matrix &d, long ipp, long ido);
void nlstressesincr (long ipp,long im,long ido);
void givestressincr (long lcid, long ipp, long im, long ido, long fi, vector &sig);
void nlstresses (long ipp,long im,long ido);
void updateval (long ipp,long ido);
long actualize_stiffmat(const nonlinman &nlman, long istep, long jstep);
void updateval (long ipp, long im, long ido);
double comp_actual_ym(long ipp, long im, long ido);
double give_actual_ym(long ipp, long im, long ido);
double give_actual_nu(long ipp, long im, long ido);
double dstep_red(long ipp, long im, long ido);
void giveirrstrains (long ipp, long ido, vector &epsp);
double give_consparam (long ipp, long ido);
double give_preconspress(long ipp, long ido);
104,6 → 119,23
/// coefficent of apparent adhesion due to suction pressure
double ks;
 
/// soil swelling index reference value
double kappa_s0;
 
/// parameters for the strain rate caculation caused by the suction change
double aks1,aks2;
/// parameters for the thermal strain rate caculation
double a0,a2;
 
/// flag for suction definition (yes=suction evolution is prescribed by suc_fn, no=suction is taken from TRFEL)
//answertype pr_suc_f;
/// function of prescribed suction evolution
//gfunct suc_fn;
/// flag for temperature definition (yes=temperature is prescribed by tempr_fn, no=temperature is taken from TRFEL)
//answertype pr_tempr_f;
/// function of prescribed temperature evolution
//gfunct tempr_fn;
 
/// stress return algorithm
strretalg sra;
};
/trunk/SIFEL/MEFEL/SRC/creep.cpp
27,6 → 27,7
*/
void creep_matstiff (matrix &d, long ipp, long im, long ido)
{
long i,j;
double q;
q = 1.0;
// asymptotic elastic stiffness matrix
36,6 → 37,17
 
// actual stiffness matrix
cmulm(q, d);
 
 
// this printing below is only for debug:
//fprintf(Out,"\n q = %lf\n",q);
//fprintf(Out,"\n\n vysledna matice pro creep D^M\n");
//for (i=0;i<6;i++){
//for (j=0;j<6;j++)
// fprintf(Out,"%e \n",d[i][j]);
//fprintf(Out,"\n");
//}
//fflush(Out);
}
 
 
/trunk/SIFEL/MEFEL/SRC/creep_b3.cpp
445,9 → 445,9
 
 
/**
function stores E_mu stifnesses of Kelvin chain units into eqother
function stores E_mu stiffnesses of Kelvin chain units into eqother
 
@param e_mu - %vector of stifnesses
@param e_mu - %vector of stiffnesses
@param n_ret_times - number of ret. times
@param ipp - number of integration point
@param ido - index of internal variables for given material in the ipp other array
473,9 → 473,9
 
 
/**
function returns E_mu stifnesses of Kelvin chains
function returns E_mu stiffnesses of Kelvin chains
 
@param e_mu - %vector of stifnesses
@param e_mu - %vector of stiffnesses
@param n_ret_times - number of ret. times
@param ipp - number of integration point
@param ido - index of internal variables for given material in the ipp other array
/trunk/SIFEL/MEFEL/SRC/creep_dpl.cpp
286,9 → 286,9
 
 
/**
function stores E_mu stifnesses of Kelvin chain units into eqother
function stores E_mu stiffnesses of Kelvin chain units into eqother
 
@param e_mu - %vector of stifnesses
@param e_mu - %vector of stiffnesses
@param n_ret_times - number of ret. times
@param ipp - number of integration point
@param ido - index of internal variables for given material in the ipp other array
314,9 → 314,9
 
 
/**
function returns E_mu stifnesses of Kelvin chains
function returns E_mu stiffnesses of Kelvin chains
 
@param e_mu - %vector of stifnesses
@param e_mu - %vector of stiffnesses
@param n_ret_times - number of ret. times
@param ipp - number of integration point
@param ido - index of internal variables for given material in the ipp other array
/trunk/SIFEL/MEFEL/SRC/creep_rspec.cpp
746,7 → 746,7
/**
function stores E_mu stiffnesses of Kelvin chain units into eqother
 
@param e_mu - %vector of stifnesses
@param e_mu - %vector of stiffnesses
@param n_ret_times - number of ret. times
@param ipp - number of integration point
@param ido - index of internal variables for given material in the ipp other array
772,9 → 772,9
 
 
/**
function returns E_mu stifnesses of Kelvin chains
function returns E_mu stiffnesses of Kelvin chains
 
@param e_mu - %vector of stifnesses
@param e_mu - %vector of stiffnesses
@param n_ret_times - number of ret. times
@param ipp - number of integration point
@param ido - index of internal variables for given material in the ipp other array
/trunk/SIFEL/MEFEL/SRC/dloadcase.cpp
764,7 → 764,8
@return The function returns prescribed displacement.
Created by Tomas Koudelka, 14.11.2007
Modified by Tomas Koudelka, 07.2016
Modified by Tomas Koudelka, 07.2016,
Corrected by TKr, 20/04/2023
*/
double dloadcase::get_pd(double time, long dof)
{
789,7 → 790,8
}
case timedepload:{
if (npd)
ret = pd[0-dof-1].getval(Mp->time);
//ret = pd[0-dof-1].getval(Mp->time);
ret = pd[0-dof-1].getval(time); // corrcted for values for the given time
if (tnpid && (-dof > max_npd)) // initial prescribed displacements at gradual construction problem have been defined
ret = pid[-(dof+max_npd+1)]; // dof number of prescribed initial displacement is negative and it is less than all dof numbers
// for prescribed displacements defined in particular subloadcases
/trunk/SIFEL/MEFEL/SRC/dsm.cpp
0,0 → 1,1855
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
 
#include "dsm.h"
#include "global.h"
#include "probdesc.h"
#include "mechmat.h"
#include "vecttens.h"
#include "intpoints.h"
#include "matrix.h"
#include "vector.h"
#include "tensor.h"
#include "elastisomat.h"
#include "mathem.h"
#include "nonlinman.h"
 
 
/**
This constructor inializes attributes to zero values.
*/
dsmmat::dsmmat (void)
{
m = 0.0;
lambda = 0.0;
kappa = 0.0;
c1_tilde = 0.0;
c2 = 0.0;
ks = 0.0;
 
//pr_suc_f = no;
//pr_tempr_f = no;
 
kappa_s0 = 0.0;
aks1 = 0.0;
aks2 = 0.0;
a0 = 0.0;
a2 = 0.0;
}
 
 
 
/**
This destructor is only for the formal purposes.
*/
dsmmat::~dsmmat (void)
{
 
}
 
 
 
/**
This function reads material parameters from the opened text file given
by the parameter in.
 
@param in - pointer to the opned text file
 
*/
void dsmmat::read (XFILE *in)
{
xfscanf (in, "%k%lf%k%lf%k%lf", "m", &m, "lambda", &lambda, "kappa", &kappa);
xfscanf (in, "%k%lf%k%lf%k%lf", "c1_tilde", &c1_tilde, "c2", &c2, "ks", &ks);
 
sra.read (in);
}
 
/**
This function initializes material model data
with respect of consistency parameter gamma.
 
@param ipp - integration point number
@param im - index of material type for given ip
@param ido - index of internal variables for given material in the ipp other array
 
12/06/2012 TKo
*/
void dsmmat::initval(long ipp, long im, long ido)
{
double v_ini, v_pc0, v_lambda1;
double i1s, j2s, s;
double v_kappa1, p1, bar_pc_0, pc_0;
long i, ncompstr = Mm->ip[ipp].ncompstr;
vector sig(ASTCKVEC(ncompstr)),sigt(ASTCKVEC(6)), q(ASTCKVEC(2));
double err=sra.give_err ();
// variables used for the calculation of initial value of preconsolidation pressure for the fully saturated state
double a, b, fs, ksi, sr, qq, p_atm = 101325.0;
 
if (Mm->ip[ipp].eqother[ido+ncompstr+1] == 0.0) // actual value of p_c was not set
{
// initial value of specific volume under small pressure p_1 on the normal consolidation line (v_lambda1 = 1+N)
v_lambda1 = Mm->ic[ipp][0];
// initial reference presure
p1 = Mm->ic[ipp][1];
// initial effective preconsolidation pressure \bar{p}_{c0}}
bar_pc_0 = Mm->ic[ipp][2];
 
// initial effective stresses
if ((Mp->eigstrains == 4) || (Mp->eigstrains == 5)){
for (i=0; i<ncompstr; i++)
sig(i) = Mm->ip[ipp].stress[i] = Mm->eigstresses[ipp][i];
}
else{
print_err("initial effective stresses (eigentsresses) are not defined on element %ld, ip=%ld,\n"
" cannot determine specific volume for initial stress state", __FILE__, __LINE__, __func__, Mm->elip[ipp]+1, ipp+1);
abort();
}
 
//vector_tensor (sig,sigt,Mm->ip[ipp].ssst,stress);
give_full_vector (sigt, sig, Mm->ip[ipp].ssst);
// initial value of mean stress
i1s = first_invar(sigt)/3.0;
q(0) = bar_pc_0;
s = Mm->givenonmechq(suction, ipp); // suction pressure s
sr = Mm->givenonmechq(saturation_degree, ipp); // degree of saturation S_r
//limitation of positive suction
if(s >=0.0)
s=0.0;
s = fabs(s);
q(1) = ks*s;
// test if the initial state is elastic, if not calculate new value of inital effective preconsolidation pressure pc_0 so the OCR=1
if (yieldfunction(sigt, q) > err){
j2s = j2_stress_invar (sigt);
bar_pc_0 = j2s/(m*m*(i1s-q(1))) + i1s;
}
 
//
// Calculation of inital value of preconsolidation pressure for the fully saturated state pc_0
//
// suction function:
//
// s / p_{atm}
// f(s) = 1 + -----------------------
// 10.7 + 2.4(s / p_{atm})
//
fs = 1.0 + (s/p_atm) / (10.7 + 2.4*(s/p_atm));
if (fs < 1.0)
fs = 1.0;
// bonding variable:
//
// \ksi = f(s) (1 - S_r)
//
ksi = (1-sr)*fs;
 
// according to Gallipoli
qq = 1.0 - c1_tilde*(1.0 - exp(c2*ksi)); // e/e_s
a = (qq - 1.0)/(lambda*qq - kappa)*(v_lambda1 - 1.0);
b = (lambda - kappa)/(lambda*qq - kappa);
pc_0 = -pow(-bar_pc_0 /exp(a), 1.0/b);
 
// compute initial value of specific volume
v_pc0 = v_lambda1 - lambda*log(pc_0/p1);
 
// actual value of p_c = initial effective preconsolidtaion pressure
Mm->ip[ipp].other[ido+ncompstr+1] = Mm->ip[ipp].eqother[ido+ncompstr+1] = bar_pc_0;
Mm->ip[ipp].other[ido+ncompstr+2] = Mm->ip[ipp].eqother[ido+ncompstr+2] = q(1);
// initial value of specific volume under small pressure p_1 on the swelling line (v_{\kappa l}) at the fully saturated state
Mm->ip[ipp].other[ido+ncompstr+3] = Mm->ip[ipp].eqother[ido+ncompstr+3] = v_kappa1 = v_pc0 + kappa*log(pc_0/p1);
// specific volume for intial stress state
Mm->ip[ipp].other[ido+ncompstr+4] = Mm->ip[ipp].eqother[ido+ncompstr+4] = v_ini = v_pc0 + kappa*log(pc_0/i1s);
// intial mean stress
Mm->ip[ipp].other[ido+ncompstr+5] = Mm->ip[ipp].eqother[ido+ncompstr+5] = i1s;
// saturation degree
Mm->ip[ipp].other[ido+ncompstr+9] = Mm->ip[ipp].eqother[ido+ncompstr+9] = Mm->givenonmechq(saturation_degree, ipp); // degree of saturation S_r
// initial depsv_dt
Mm->ip[ipp].other[ido+ncompstr+10] = Mm->ip[ipp].eqother[ido+ncompstr+10] = 0.0;
// porosity n for intial stress state
Mm->ip[ipp].other[ido+ncompstr+11] = Mm->ip[ipp].eqother[ido+ncompstr+11] = (v_ini-1.0)/v_ini; // v_ini = 1.0 + e_ini
// suction
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);
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
Mm->ip[ipp].other[ido+ncompstr+14] = Mm->ip[ipp].eqother[ido+ncompstr+14] = 1.0;
// set inital stiffness matrix
matrix d;
makerefm(d, Mm->ip[ipp].other+ido+ncompstr+15, ncompstr, ncompstr);
Mm->elmatstiff(d, ipp, ido);
copym(d, Mm->ip[ipp].eqother+ido+ncompstr+15);
check_math_errel(Mm->elip[ipp]);
 
//set of effective mean stress of previous time step
Mm->ip[ipp].other[ido+ncompstr+15+ncompstr*ncompstr] = Mm->ip[ipp].eqother[ido+ncompstr+15+ncompstr*ncompstr] = i1s;
 
return;
}
 
 
/**
This function computes the value of yield functions.
 
@param sig - full stress tensor in Voigt notation (6 components)
@param q - %vector of hardening parameter
 
@retval The function returns value of yield function for the given stress tensor
 
25.3.2002
*/
double dsmmat::yieldfunction (vector &sig, vector &q)
{
double i1s,j2s,f;
i1s = first_invar (sig)/3.0;
j2s = j2_stress_invar (sig);
 
f = j2s/(m*m) + (i1s - q[1]) * (i1s - q[0]);
return f;
}
 
 
 
/**
This function computes derivatives of as-th yield function
with respect of vector sigma.
 
@param sig - stress tensor in Voigt notation (6 components)
@param q - %vector of the hardening parameter
@param dfds - %vector where the resulting derivatives are stored (6 components)
 
 
4.1.2002
*/
void dsmmat::deryieldfsigma (vector &sig, vector &q, vector &dfds)
{
double volume,i1s;
i1s = first_invar (sig)/3.0;
deviator (sig,dfds);
 
// q[0] = \bar{p}_c
// q[1] = p_s = k * s
cmulv(1.0/(m*m), dfds);
volume=1.0/3.0*(2.0*i1s - q[0] - q[1]);
dfds(0) += volume;
dfds(1) += volume;
dfds(2) += volume;
dfds(3) *= 2.0;
dfds(4) *= 2.0;
dfds(5) *= 2.0;
}
 
 
 
/**
The function computes the second derivatives of yield function
with respect of stress tensor sigma.
 
@param ddfds - tensor of the 4-th order where the are derivatives stored
 
19.12.2002
*/
void dsmmat::dderyieldfsigma (matrix &ddfds)
{
fillm(0.0, ddfds);
ddfds[0][0] = ddfds[1][1] = ddfds[2][2] = 2.0/(3.0*m*m) + 2.0/9.0;
ddfds[0][1] = ddfds[0][2] = ddfds[1][0] = ddfds[1][2] = -1.0/(3.0*m*m) + 2.0/9.0;
ddfds[2][0] = ddfds[2][1] = ddfds[0][1];
// doubled shear components due to tensor-> vector transformation
ddfds[3][3] = 2.0/(m*m);
ddfds[4][4] = 2.0/(m*m);
ddfds[5][5] = 2.0/(m*m);
}
 
 
 
/**
The function computes derivatives of plastic potential function
with respect of vector sigma.
 
@param sig - stress tensor
@param q - %vector of the hardening parameters
@param ddgds - %matrix where the resulting derivatives are stored
*/
void dsmmat::derpotsigma (vector &sig, vector &q, vector &ddgds)
{
deryieldfsigma (sig, q, ddgds);
}
 
 
 
/**
This function computes derivatives of as-th yield function
with respect of vector of hradening parameters.
 
@param sig - stress tensor
@param q - %vector of the hardening parameters
@param dfds - %vector where the resulting derivatives are stored
 
 
4.1.2002
*/
void dsmmat::deryieldfq(vector &sig, vector &q, vector &dfq)
{
// df
// ---------- = dfq[0]
// d\bar{p}_c
dfq[0] = -first_invar (sig)/3.0 + q[1];
// df
// --- = dfq[1]
// p_s
dfq[1] = -first_invar (sig)/3.0 + q[0];
 
return;
}
 
 
 
/**
The function computes the second derivatives of yield function
with respect to hradening parameters.
 
@param ddfdq - %matrix, where the resulting derivatives are stored
 
 
Created by Tomas Koudelka, 09.2012
*/
void dsmmat::deryieldfdqdq(matrix &ddfdq)
{
ddfdq[0][0] = 0.0;
ddfdq[0][1] = 1.0;
ddfdq[1][0] = 1.0;
ddfdq[1][1] = 0.0;
 
return;
}
 
 
 
/**
The function computes the second derivatives of yield function
with respect to stresses.
 
@param dfds - tensor, where the resulting derivatives are stored.
size of dfds = (6,number_of_hardening_param)
 
 
Created by Tomas Koudelka, 09.2012
*/
void dsmmat::deryieldfdsdq(matrix &dfdsdqt)
{
dfdsdqt[0][0] = dfdsdqt[1][0] = dfdsdqt[2][0] = -1.0/3.0;
dfdsdqt[0][1] = dfdsdqt[1][1] = dfdsdqt[2][1] = -1.0/3.0;
return;
}
 
 
 
/**
The function computes derivatives of hardening paramters
with respect of consistency parameter gamma.
 
@param ipp - integration point number
@param ido - index of internal variables for given material in the ipp other array
@param sig - full stress tensor
@param qtr - %vector of hardening variables
@param epsp - %vector of attained plastic strains
@param dqdg - %vector where the resulting derivatives are stored in Voigt notation
 
 
Created by Tomas Koudelka, 09.2012
*/
void dsmmat::der_q_gamma(long ipp, long ido, vector &sig, vector &qtr, vector &epsp, vector &dqdg)
{
double v_ini, v_lambda1, v_kappa1, p1, i1s, epsvp;
double p_atm = 101325.0;
double s, sr, fs, b, c, c1, ksi;
long ncompstr = Mm->ip[ipp].ncompstr;
strastrestate ssst = Mm->ip[ipp].ssst;
vector epst(ASTCKVEC(6));
// mean stress
i1s = first_invar (sig)/3.0;
// initial value of specific volume under small pressure p_1 for the normal consolidation line (v_{\lambda 1} = N)
v_lambda1 = Mm->ic[ipp][0];
// initial reference presure
p1 = Mm->ic[ipp][1];
// initial value of specific volume under small pressure p_1 for the swelling line (v_{\kappa 1})
v_kappa1 = Mm->ip[ipp].eqother[ido+ncompstr+3];
// specific volume for intial stress state
v_ini = Mm->ip[ipp].eqother[ido+ncompstr+4];
 
s = Mm->givenonmechq(suction, ipp); // suction pressure s
//limitation of positive suction
if(s >=0.0)
s=0.0;
s = fabs(s);
sr = Mm->givenonmechq(saturation_degree, ipp); // degree of saturation S_r
 
// actual value of preconsolidation pressure for the fully saturated state
give_full_vector (epst, epsp, ssst);
epsvp = first_invar(epst);
//double pc_new = p1 * exp((v_kappa1 - v_lambda1 + v_ini*epsvp)/(kappa-lambda));
// specific volume for the actual preconsolidation pressure:
//
// v_{pc} = v_{\lambda1} - \lambda \ln(p_c/p_1)
// double v_pc = v_lambda1 - lambda * log(pc_new/p1);
 
// suction function:
//
// s / p_{atm}
// f(s) = 1 + -----------------------
// 10.7 + 2.4(s / p_{atm})
//
fs = 1.0 + (s/p_atm) / (10.7 + 2.4*(s/p_atm));
if (fs < 1.0)
fs = 1.0;
 
// bonding variable:
//
// \ksi = f(s) (1 - S_r)
//
ksi = (1-sr)*fs;
 
// \tilde{c}_1
// c_1 = --------------------
// 1
// -------------- + 1
// v_{pc}-1
 
// c1 = c1_tilde/(1.0/(v_pc-1.0)+1.0); // according to Borja
c1 = c1_tilde; // according to Gallipoli
 
 
//
// c(\ksi) = 1 - c_1 [1-\exp(c_2 \ksi)]
//
c = 1.0 - c1*(1.0-exp(c2*ksi));
 
//
// \lambda - \kappa
// b(\ksi) = --------------------------
// \lambda c(\ksi) - \kappa
//
b = (lambda - kappa)/(lambda*c - kappa);
 
 
// q[0] = \bar{p}_c = -\exp[a(\ksi)] (-p_c)^{b(\ksi)}
//
// p_c = p_1 exp[(v_{\kappa_1} - v_{\lambda_1} + eps_{vp} v_{ini})/(\kappa - \lambda)]
//
// p_1 = const
// p_{c0} = const
// \sigma_{m0} = const
// v_{\kappa_1} = const
// v_{p_{c0}} = v_{\kappa_1} - \kappa \ln(p_{c0}/p_1) = const
// v_{ini} = v_{p_{c0}} + \kappa \ln(p_{c0}/\sigma_{m0}) = const
// v_{\lambda_1} = v_{p_{c0}} - \lambda \ln(p_{c0}/p_1) = const
//
// d \bar{p}_c d p_c (-p_c)^{b(\ksi)} d p_c
// ----------- = -\exp[a(\ksi)] b(\ksi)(-p_c)^{b(\ksi)-1} ---------- = -\exp[a(\ksi)] b(\ksi) ---------------- ---------- ,
// d \gamma d \gamma p_c d \gamma
//
// d p_c v_ini
// ---------- = p_c ----------------- (2p - \bar{p}_c - p_s),
// d \gamma \kappa - \lambda
//
// d \bar{p}_c b(\ksi) v_ini
// ----------- = -\bar{p}_c ---------------- (2p - \bar{p}_c - p_s)
// d \gamma \kappa - \lambda
//
//
dqdg[0] = -qtr[0] * (b*v_ini)/(kappa-lambda) * (2.0*i1s-qtr[0]-qtr[1]);
 
 
// q[1] = p_s = k*s
//
// d p_s
// ----------- = 0.0 because p_s is constant for the given strain level
// d \gamma
//
dqdg[1] = 0.0;
 
return;
}
 
 
 
/**
The function computes derivatives of hardening paramters
with respect of consistency parameter gamma.
 
@param ipp - integration point number
@param ido - index of internal variables for given material in the ipp other array
@param sig - full stress tensor
@param qtr - %vector of hardening variables
@param epsp - %vector of attained plastic strains
@param dqdgds - %matrix where the resulting derivatives are stored in Voigt notation,
its dimensions must be qtr.n x 6
 
 
Created by Tomas Koudelka, 05.2022
*/
void dsmmat::dqpardgammadsigma(long ipp, long ido, vector &sig, vector &qtr, vector &epsp, matrix &dqdgds)
{
double v_ini, v_lambda1, v_kappa1, p1, i1s, epsvp;
double p_atm = 101325.0;
double s, sr, fs, b, c, c1, ksi;
long ncompstr = Mm->ip[ipp].ncompstr;
strastrestate ssst = Mm->ip[ipp].ssst;
vector epst(ASTCKVEC(6));
// mean stress
i1s = first_invar (sig)/3.0;
// initial value of specific volume under small pressure p_1 for the normal consolidation line (v_{\lambda 1} = N)
v_lambda1 = Mm->ic[ipp][0];
// initial reference presure
p1 = Mm->ic[ipp][1];
// initial value of specific volume under small pressure p_1 for the swelling line (v_{\kappa 1})
v_kappa1 = Mm->ip[ipp].eqother[ido+ncompstr+3];
// specific volume for intial stress state
v_ini = Mm->ip[ipp].eqother[ido+ncompstr+4];
 
s = Mm->givenonmechq(suction, ipp); // suction pressure s
//limitation of positive suction
if(s >=0.0)
s=0.0;
s = fabs(s);
sr = Mm->givenonmechq(saturation_degree, ipp); // degree of saturation S_r
 
// actual value of preconsolidation pressure for the fully saturated state
give_full_vector (epst, epsp, ssst);
epsvp = first_invar(epst);
//double pc_new = p1 * exp((v_kappa1 - v_lambda1 + v_ini*epsvp)/(kappa-lambda));
// specific volume for the actual preconsolidation pressure:
//
// v_{pc} = v_{\lambda1} - \lambda \ln(p_c/p_1)
//double v_pc = v_lambda1 - lambda * log(pc_new/p1);
 
// suction function:
//
// s / p_{atm}
// f(s) = 1 + -----------------------
// 10.7 + 2.4(s / p_{atm})
//
fs = 1.0 + (s/p_atm) / (10.7 + 2.4*(s/p_atm));
if (fs < 1.0)
fs = 1.0;
 
// bonding variable:
//
// \ksi = f(s) (1 - S_r)
//
ksi = (1-sr)*fs;
 
// \tilde{c}_1
// c_1 = --------------------
// 1
// -------------- + 1
// v_{pc}-1
 
// c1 = c1_tilde/(1.0/(v_pc-1.0)+1.0); // according to Borja
c1 = c1_tilde; // according to Gallipoli
 
 
//
// c(\ksi) = 1 - c_1 [1-\exp(c_2 \ksi)]
//
c = 1.0 - c1*(1.0-exp(c2*ksi));
 
//
// \lambda - \kappa
// b(\ksi) = --------------------------
// \lambda c(\ksi) - \kappa
//
b = (lambda - kappa)/(lambda*c - kappa);
 
 
// q[0] = \bar{p}_c = -\exp[a(\ksi)] (-p_c)^{b(\ksi)}
//
// p_c = p_1 exp[(v_{\kappa_1} - v_{\lambda_1} + eps_{vp} v_{ini})/(\kappa - \lambda)]
//
// p_1 = const
// p_{c0} = const
// \sigma_{m0} = const
// v_{\kappa_1} = const
// v_{p_{c0}} = v_{\kappa_1} - \kappa \ln(p_{c0}/p_1) = const
// v_{ini} = v_{p_{c0}} + \kappa \ln(p_{c0}/\sigma_{m0}) = const
// v_{\lambda_1} = v_{p_{c0}} - \lambda \ln(p_{c0}/p_1) = const
//
// d \bar{p}_c d p_c (-p_c)^{b(\ksi)} d p_c
// ----------- = -\exp[a(\ksi)] b(\ksi)(-p_c)^{b(\ksi)-1} ---------- = -\exp[a(\ksi)] b(\ksi) ---------------- ---------- ,
// d \gamma d \gamma p_c d \gamma
//
// d p_c v_ini
// ---------- = p_c ----------------- (2p - \bar{p}_c - p_s),
// d \gamma \kappa - \lambda
//
// d \bar{p}_c b(\ksi) v_ini
// ----------- = -\bar{p}_c ---------------- (2p - \bar{p}_c - p_s)
// d \gamma \kappa - \lambda
//
//
// dqdg(0) = -qtr[0] * (b*v_ini)/(kappa-lambda) * (2.0*i1s-qtr[0]-qtr[1]);
dqdgds(0,0) = dqdgds(0,1) = dqdgds(0,2) = -qtr[0] * (b*v_ini)/(kappa-lambda) * 2.0/3.0;
 
 
// q[1] = p_s = k*s
//
// d p_s
// ----------- = 0.0 because p_s is constant for the given strain level
// d \gamma
//
dqdgds(1,0) = dqdgds(1,1) = dqdgds(1,2) = dqdgds(1,3) = dqdgds(1,4) = dqdgds(1,5) = 0.0;
 
return;
}
 
 
 
/**
The function computes derivatives of hardening paramters
with respect of consistency parameter gamma.
 
@param ipp - integration point number
@param ido - index of internal variables for given material in the ipp other array
@param sig - full stress tensor
@param qtr - %vector of hardening variables
@param epsp - %vector of attained plastic strains
@param dqdgds - %matrix where the resulting derivatives are stored, its dimensions must be qtr.n x qtr.n
 
 
Created by Tomas Koudelka, 05.2022
*/
void dsmmat::dqpardgammadqpar(long ipp, long ido, vector &sig, vector &qtr, vector &epsp, matrix &dqdgdq)
{
double v_ini, v_lambda1, v_kappa1, p1, i1s, epsvp;
double p_atm = 101325.0;
double s, sr, fs, b, c, c1, ksi;
long ncompstr = Mm->ip[ipp].ncompstr;
strastrestate ssst = Mm->ip[ipp].ssst;
vector epst(ASTCKVEC(6));
// mean stress
i1s = first_invar (sig)/3.0;
// initial value of specific volume under small pressure p_1 for the normal consolidation line (v_{\lambda 1} = N)
v_lambda1 = Mm->ic[ipp][0];
// initial reference presure
p1 = Mm->ic[ipp][1];
// initial value of specific volume under small pressure p_1 for the swelling line (v_{\kappa 1})
v_kappa1 = Mm->ip[ipp].eqother[ido+ncompstr+3];
// specific volume for intial stress state
v_ini = Mm->ip[ipp].eqother[ido+ncompstr+4];
 
s = Mm->givenonmechq(suction, ipp); // suction pressure s
//limitation of positive suction
if(s >=0.0)
s=0.0;
s = fabs(s);
sr = Mm->givenonmechq(saturation_degree, ipp); // degree of saturation S_r
 
// actual value of preconsolidation pressure for the fully saturated state
give_full_vector (epst, epsp, ssst);
epsvp = first_invar(epst);
//double pc_new = p1 * exp((v_kappa1 - v_lambda1 + v_ini*epsvp)/(kappa-lambda));
// specific volume for the actual preconsolidation pressure:
//
// v_{pc} = v_{\lambda1} - \lambda \ln(p_c/p_1)
//double v_pc = v_lambda1 - lambda * log(pc_new/p1);
 
// suction function:
//
// s / p_{atm}
// f(s) = 1 + -----------------------
// 10.7 + 2.4(s / p_{atm})
//
fs = 1.0 + (s/p_atm) / (10.7 + 2.4*(s/p_atm));
if (fs < 1.0)
fs = 1.0;
 
// bonding variable:
//
// \ksi = f(s) (1 - S_r)
//
ksi = (1-sr)*fs;
 
// \tilde{c}_1
// c_1 = --------------------
// 1
// -------------- + 1
// v_{pc}-1
 
// c1 = c1_tilde/(1.0/(v_pc-1.0)+1.0); // according to Borja
c1 = c1_tilde; // according to Gallipoli
 
 
//
// c(\ksi) = 1 - c_1 [1-\exp(c_2 \ksi)]
//
c = 1.0 - c1*(1.0-exp(c2*ksi));
 
//
// \lambda - \kappa
// b(\ksi) = --------------------------
// \lambda c(\ksi) - \kappa
//
b = (lambda - kappa)/(lambda*c - kappa);
 
 
// q[0] = \bar{p}_c = -\exp[a(\ksi)] (-p_c)^{b(\ksi)}
//
// p_c = p_1 exp[(v_{\kappa_1} - v_{\lambda_1} + eps_{vp} v_{ini})/(\kappa - \lambda)]
//
// p_1 = const
// p_{c0} = const
// \sigma_{m0} = const
// v_{\kappa_1} = const
// v_{p_{c0}} = v_{\kappa_1} - \kappa \ln(p_{c0}/p_1) = const
// v_{ini} = v_{p_{c0}} + \kappa \ln(p_{c0}/\sigma_{m0}) = const
// v_{\lambda_1} = v_{p_{c0}} - \lambda \ln(p_{c0}/p_1) = const
//
// d \bar{p}_c d p_c (-p_c)^{b(\ksi)} d p_c
// ----------- = -\exp[a(\ksi)] b(\ksi)(-p_c)^{b(\ksi)-1} ---------- = -\exp[a(\ksi)] b(\ksi) ---------------- ---------- ,
// d \gamma d \gamma p_c d \gamma
//
// d p_c v_ini
// ---------- = p_c ----------------- (2p - \bar{p}_c - p_s),
// d \gamma \kappa - \lambda
//
// d \bar{p}_c b(\ksi) v_ini
// ----------- = -\bar{p}_c ---------------- (2p - \bar{p}_c - p_s)
// d \gamma \kappa - \lambda
//
//
// dqdg(0) = -qtr[0] * (b*v_ini)/(kappa-lambda) * (2.0*i1s-qtr[0]-qtr[1]);
// wrong //dqdgdq(0,0) = 2.0*qtr[0] * (b*v_ini)/(kappa-lambda);
dqdgdq(0,0) = -(b*v_ini)/(kappa-lambda) * (2.0*i1s-2.0*qtr[0]-qtr[1]);
dqdgdq(0,1) = qtr[0] * (b*v_ini)/(kappa-lambda);
 
 
// q[1] = p_s = k*s
//
// d p_s
// ----------- = 0.0 because p_s is constant for the given strain level
// d \gamma
//
dqdgdq(1,0) = dqdgdq(1,1) = 0.0;
 
return;
}
 
 
 
/**
This function computes plastic modulus.
 
@param ipp - integration point number
@param ido - index of internal variables for given material in the ipp other array
@param sig - stress tensor in Voigt notation
@param qtr - %vector of hardening parameters
@param epsp - %vector of attained plastic strains
 
@retval The function returns value of the plastic modulus.
 
Created by Tomas Koudelka, 09.2012
*/
double dsmmat::plasmodscalar(long ipp, long ido, vector &sig, vector &qtr, vector &epsp)
{
double ret;
vector dfq(ASTCKVEC(2));
vector dqg(ASTCKVEC(2));
 
deryieldfq(sig, qtr, dfq);
der_q_gamma(ipp, ido, sig, qtr, epsp, dqg);
scprd(dfq, dqg, ret);
 
return -ret;
}
 
 
 
/**
This function computes new value of the hardening parameter q.
 
@param ipp - integration point pointer
@param ido - index of internal variables for given material in the ipp other array
@param eps - %vector of the attained strains in Voigt notation
@param epsp - %vector of the attained plastic strains in Voigt notation
@param sig - attained stress tensor in Voigt notation
@param ssst - stress/strain state parameter (for the used vector_tensor function)
@param q - %vector of the hardening parameters
 
Created by Tomas Koudelka, 09.2012
*/
void dsmmat::updateq(long ipp, long ido, vector &eps, vector &epsp, vector &sig, vector &q)
{
vector epst(ASTCKVEC(6));
vector depsp(epsp.n);
double v_kappa1, v_lambda1, p1, depsvp, v_ini, pc_new;
double v_pc, p_atm = 101325.0;
double s, sr, fs, a, b, c, c1, ksi;
strastrestate ssst = Mm->ip[ipp].ssst;
long ncompstr = Mm->ip[ipp].ncompstr;
long i;
// initial value of specific volume under small pressure p_1 for the normal consolidation line (v_lambda1 = 1+N)
v_lambda1 = Mm->ic[ipp][0];
// initial reference presure
p1 = Mm->ic[ipp][1];
// original specific volume before any loading
v_kappa1 = Mm->ip[ipp].eqother[ido+ncompstr+3];
// specific volume for intial stress state
v_ini = Mm->ip[ipp].eqother[ido+ncompstr+4];
 
// Original version of pc calculation - problems with tension
// vk = v_ini*(1+epsv)+kappa*log(i1s/p1);
// pc_new = p1 * exp((vk-v_lambda1)/(kappa-lambda));
//
// Alternative version of pc calculation - 'less' accurate in benchmarks
// pc_new = p1 * exp((v_kappa1 - v_lambda1 + v_ini*epsv)/(kappa-lambda));
// vk = v_ini*(1+epsv)+kappa*log(i1s/p1);
 
for (i=0; i<ncompstr; i++)
depsp[i] = epsp[i];// + Mm->ic[ipp][3+i];
 
give_full_vector(epst, depsp, ssst);
depsvp = first_invar(epst);
 
pc_new = p1 * exp((v_kappa1 - v_lambda1 + v_ini*depsvp)/(kappa-lambda));
 
// For the partially saturated soil,
// the effective preconsolidation pressure \bar{p}_c is related to the saturated
// preconsolidation pressure p_c according to bonding variable \ksi
//
// \bar{p}_c = -exp[a(\ksi)] (-p_c)^{b(\ksi)}
//
//
// specific volume for the actual preconsolidation pressure:
//
// v_{pc} = v_{\lambda1} - \lambda \ln(p_c/p_1)
v_pc = v_lambda1 - lambda * log(pc_new/p1);
 
s = Mm->givenonmechq(suction, ipp); // suction pressure s
//limitation of positive suction
if(s >=0.0)
s=0.0;
s = fabs(s);
sr = Mm->givenonmechq(saturation_degree, ipp); // degree of saturation S_r
 
// suction function:
//
// s / p_{atm}
// f(s) = 1 + -----------------------
// 10.7 + 2.4(s / p_{atm})
//
fs = 1.0 + (s/p_atm) / (10.7 + 2.4*(s/p_atm));
if (fs < 1.0)
fs = 1.0;
 
// bonding variable:
//
// \ksi = f(s) (1 - S_r)
//
ksi = (1-sr)*fs;
 
// \tilde{c}_1
// c_1 = --------------------
// 1
// -------------- + 1
// v_{pc}-1
// c1 = c1_tilde/(1.0/(v_pc-1.0)+1.0); // according to Borja
c1 = c1_tilde; // according to Gallipoli
 
 
//
// c(\ksi) = 1 - c_1 [1-\exp(c_2 \ksi)]
//
c = 1.0 - c1*(1.0-exp(c2*ksi));
 
//
// a(\ksi) = v_{lambda_1} [c(\ksi)-1]/[\lambda c(\ksi) - \kappa)
//
a = (v_lambda1 - 1.0)*(c - 1.0)/(lambda*c - kappa);
 
//
// \lambda - \kappa
// b(\ksi) = --------------------------
// \lambda c(\ksi) - \kappa
//
b = (lambda - kappa)/(lambda*c - kappa);
 
//
// effective preconsolidation pressure:
//
// q[0] = \bar{p}_c = -exp[a(\ksi)] (-p_c)^{b(\ksi)}
//
q[0] = -exp(a)*pow(-pc_new, b);
 
// apparent adhesion due to suction
// (right intersection of the yield surface with p axis):
//
// q[1] = p_s = k s
//
q[1] = ks * s;
return;
}
 
 
 
/**
This function computes material stiffnes matrix.
 
@param d - allocated matrix structure for material stiffness %matrix in the reduced format
@param ipp - integration point number
@param ido - index of internal variables for given material in the ipp other array
 
Created by Tomas Koudelka, 09.2012
*/
void dsmmat::matstiff (matrix &d, long ipp, long ido)
{
double zero=1.0e-20;
 
switch (Mp->nlman->stmat){
case initial_stiff:
// initial elastic matrix
Mm->elmatstiff(d, ipp, ido);
break;
case tangent_stiff:
case secant_stiff:
case incr_tangent_stiff:
case ijth_tangent_stiff:{
// consistent tangent stiffness matrix
long n = Mm->ip[ipp].ncompstr;
if (sra.give_tsra() == cp){
// algorithmic consistent stiffness matrix for the cutting plane algorithm is computed in the course of stress return
if (d.m != n){ // material stiffness matrix used for element in the case of plane stress/strain states
for(long i=0; i<d.m; i++) // copy just the first d.n(=3) components at all matrix rows
memcpy(&d(i,0), Mm->ip[ipp].other+ido+n+15+n*i, d.n*sizeof(*Mm->ip[ipp].other));
}
else{ // dimensions of material stiffness matrix matches the ones for element material stiffness matrix
matrix auxm;
makerefm(auxm, Mm->ip[ipp].other+ido+n+15, n, n);
copym(auxm, d);
}
}
else{
// compute algorithmic stiffness matrix for closest point projection stress return algorithm
matrix de(ASTCKMAT(6, 6)), ddfdst(ASTCKMAT(6,6));
matrix e(ASTCKMAT(6, 6)), auxd(ASTCKMAT(6,6)), tmp(ASTCKMAT(6, 6));
double gamma = Mm->ip[ipp].other[ido+n];
identm(e);
Mm->elmatstiff(de, ipp, spacestress);
dderyieldfsigma(ddfdst);
cmulm(gamma, de, auxd);
mxm(auxd, ddfdst, tmp);
addm(e, tmp, auxd);
invm(auxd, tmp, zero);
mxm(tmp, de, auxd);
// matrix representation of the fourth order tensor
tensor4_ematrix(d, auxd, Mm->ip[ipp].ssst);
}
break;
}
}
}
 
 
 
/**
This function computes elasto-plastic material stiffnes matrix.
 
@param d - allocated matrix structure for material stiffness %matrix in the reduced format
@param ipp - integration point number
@param ido - index of internal variables for given material in the ipp other array
 
Created by Tomas Koudelka, 09.2012
*/
void dsmmat::depmatstiff (matrix &d, long ipp, long ido)
{
switch (Mp->nlman->stmat){
case initial_stiff:
// initial elastic matrix
Mm->elmatstiff(d, ipp, ido);
break;
case tangent_stiff:
case secant_stiff:
case incr_tangent_stiff:
case ijth_tangent_stiff:{
// consitent tangent stiffness matrix
long n = Mm->ip[ipp].ncompstr;
long ncompq = 2;
matrix de(ASTCKMAT(n, n)), auxm;
vector sig(ASTCKVEC(n)), q(ASTCKVEC(ncompq)), epsp(ASTCKVEC(n));
vector dfds(ASTCKVEC(n)), dgds(ASTCKVEC(n));
vector sigt(ASTCKVEC(6)), dfdst(ASTCKVEC(6)), dgdst(ASTCKVEC(6));
vector dedgds(ASTCKVEC(n)), dedfds(ASTCKVEC(n));
strastrestate ssst = Mm->ip[ipp].ssst;
double denomh, denomd, denom, gamma, f, err=sra.give_err();
 
// prepare actual values of needed quantities
copyv(Mm->ip[ipp].stress, sig); // stresses
copyv(Mm->ip[ipp].other+ido, epsp); // plastic strains
gamma = Mm->ip[ipp].other[ido+n+0]; // cumulated plastic multiplier
q(0) = Mm->ip[ipp].other[ido+n+1]; // hardening parameter \bar{p}_c
q(1) = Mm->ip[ipp].other[ido+n+2]; // hardening parameter k_s
give_full_vector(sigt, sig, ssst); // 6 component vector of stresses
 
// check actual stress state: f <= 0.0
f = yieldfunction(sigt, q);
if ((f < -err) || (gamma == 0.0 && (f < err))){
// stress state is in the elastic domain,
// i.e. material has been subjected by elastic loading/unloading ->
// -> return actual elastic stiffness matrix
Mm->elmatstiff(d, ipp, ssst);
return;
}
 
// stress state is on/close to the yield surface
// material has been subjected by plastic loading ->
 
// compute elasto-plastic matrix
 
// D_e \frac{dg}{d\sigma} (\frac{df}{d\sigma})^T D_e
// D_{ep} = D_e - ---------------------------------------------------
// (\frac{df}{d\sigma})^T D_e \frac{dg}{d\sigma} + H
//
// H = -\frac{df}{dq} \frac{dq}{d\lambda}
Mm->elmatstiff(de, ipp, ssst);
deryieldfsigma(sigt, q, dfdst);
derpotsigma(sigt, q, dgdst);
// conversion of full tensor notation to vector notation
give_red_vector(dfdst, dfds, ssst);
// conversion of full tensor notation to vector notation
give_red_vector(dgdst, dgds, ssst);
mxv(de,dgds,dedgds);
mxv(de,dfds,dedfds);
denomh = plasmodscalar(ipp, ido, sig, q, epsp);
scprd(dfds, dedgds, denomd);
// preserve minimum stiffness for perfect plastic material, i.e. if the hardening modulus is 'close' to zero (H->0)
// if (fabs(denomh/denomd) < 1.0e-3)
// denomh = sgn(denomh)*1.0e-3*denomd;
denom = denomd+denomh;
 
if (n == d.m){
// material stiffness matrix has identical dimensions with the ones of stiffness matrix used in
// assembling of element stiffness matrix on finite element -> auxm will be reference on matrix d
makerefm(auxm, d.a, d.m, d.n);
nullm(auxm);
}
else{
// material stiffness matrix has different dimensions than the stiffness matrix used in
// assembling of element stiffness matrix on finite element -> auxm will be reference on matrix d
reallocm(RSTCKMAT(n, n, auxm));
}
// calculate matrix in the nominator
vxv(dedgds, dedfds, auxm);
// scaling by the denominator
cmulm(1.0/denom, auxm);
// resulting material stiffness matrix
subm(de, auxm, auxm);
 
// resulting material stiffness matrix with dimensions adjusted for finite element computation
if (n != d.m){
// resulting material stiffness matrix dimensions must be adjusted for finite element computation
extractblock(auxm, d, 0, 0);
}
else{
// nothing is needed, matrix auxm is direct reference to the matrix in argument d
// hence d contains resulting material stiffness matrix with appropriate dimensions for
// the stiffness matrix on the finite element
}
/*
double zero=1.0e-20;
matrix de(ASTCKMAT(6, 6)), ddfdst(ASTCKMAT(6,6));
matrix e(ASTCKMAT(6, 6)), auxd(ASTCKMAT(6,6)), tmp(ASTCKMAT(6, 6));
long n = Mm->ip[ipp].ncompstr;
double gamma = Mm->ip[ipp].other[ido+n];
identm(e);
Mm->elmatstiff(de, ipp, spacestress);
dderyieldfsigma(ddfdst);
cmulm(gamma, de, auxd);
mxm(auxd, ddfdst, tmp);
addm(e, tmp, auxd);
invm(auxd, tmp, zero);
mxm(tmp, de, auxd);
// matrix representation of the fourth order tensor
tensor4_ematrix(d, auxd, Mm->ip[ipp].ssst);*/
break;
}
}
}
 
/**
The function computes stress increments due to suction and temperature changes 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 krejci, 03/2023
*/
void dsmmat::nlstressesincr (long ipp, long im, long ido)
//
{
double sigm_eff_prev,sigm_eff,dsigm_eff,em,km,depsvm,p0,f_beta,depss;
long i,ncomp;
// stress/strain state
strastrestate ss = Mm->ip[ipp].ssst;
ncomp=Mm->ip[ipp].ncompstr;
matrix d(ASTCKMAT(ncomp,ncomp));
vector depsv(ASTCKVEC(ncomp)),sig(ASTCKVEC(ncomp)),dsigma(ASTCKVEC(ncomp)),sigt(ASTCKVEC(6));
for (i=0;i<ncomp;i++)
Mm->ip[ipp].eqother[ido+ncomp+15+ncomp*ncomp+1+i] = 0.0;
//trial addition of microstructure effect - not completed!!!
/*
if (Mm->ip[ipp].tm[im-1] == effective_stress){
sigm_eff_prev = Mm->ip[ipp].eqother[ido+ncomp+15+ncomp*ncomp];//effective mean stress from previous time step
sigm_eff = Mm->ip[ipp].eqother[ido+ncomp+5];//effective mean stress
Mm->ip[ipp].other[ido+ncomp+15+ncomp*ncomp] = sigm_eff;//storing effective mean stress from previos time step
dsigm_eff = sigm_eff - sigm_eff_prev;
//km = exp(-am*sigm_eff)/betam;
em = 0.35;
km = 0.21;
km = (1 + em)/km*fabs(sigm_eff);
depsvm = dsigm_eff/km;
p0 = Mm->ip[ipp].eqother[ido+ncomp+1]; // p_c (hardening parameter - effective preconsolidation pressure)
//interaction function:
f_beta = 0.0;
if(dsigm_eff > 0.0){//microstructural swelling
f_beta = 0.1 - 1.1*pow((1.0-sigm_eff/p0),2.0);
}
if(dsigm_eff < 0.0){//microstructural constraction
f_beta = -0.1 + 1.1*pow((sigm_eff/p0),0.5);
}
depss = f_beta*depsvm;
//only uniaxial
if(ss==bar){
depsv[0]=depss;
}
else{
depsv[0]=depss;
depsv[1]=depss;
}
if(ss==planestrain) depsv[3]=depss;
if(ss==planestress) depsv[3]=depss;
if(ss==axisymm) depsv[2]=depss;
if(ss==spacestress) depsv[2]=depss;
fillm(0.0,d);
matstiff (d, ipp, ido);
mxv (d,depsv,dsigma);
for (i=0;i<ncomp;i++)
Mm->ip[ipp].eqother[ido+ncomp+15+ncomp*ncomp+1+i] = dsigma(i);
}
 
*/
 
}
 
 
/**
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 Krejci, 03/2023
*/
void dsmmat::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; j<sig.n; i++, j++)
sig(j) = Mm->ip[ipp].eqother[ido+ncomp+15+ncomp*ncomp+1+i];
}
 
 
 
/**
This function computes stresses at given integration point ipp,
depending on the reached strains.
The cutting plane algorithm is used. The stress and the other attribute of
given integration point is actualized.
 
@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
 
Created by Tomas Koudelka, 09.2012
*/
void dsmmat::nlstresses (long ipp, long im, long ido)
//
{
int errr;
long i,ni,ncomp=Mm->ip[ipp].ncompstr, matcomp=0, ret;
double gamma, err, pnewdt = 1.0;
vector epsn(ASTCKVEC(ncomp)), epsp(ASTCKVEC(ncomp)), q(ASTCKVEC(2));
vector epsa(ASTCKVEC(ncomp)), sig(ASTCKVEC(ncomp)), dfds(ASTCKVEC(ncomp)), dgds(ASTCKVEC(ncomp));
matrix d;
vector dfdst(ASTCKVEC(6)), dgdst(ASTCKVEC(6));
vector epst(ASTCKVEC(6)), epsnt(ASTCKVEC(6)), epspt(ASTCKVEC(6)), sigt(ASTCKVEC(6));
//vector dev(ASTCKVEC(6));
double i1s, j2s, epsv, epsvp;
double dtime = Mp->timecon.actualforwtimeincr();
// stress/strain state
//strastrestate ssst = Mm->ip[ipp].ssst;
//double nu;
 
// initial values
for (i=0; i<ncomp; i++)
{
epsn[i] = Mm->ip[ipp].strain[i];
epsp[i] = Mm->ip[ipp].eqother[ido+i];
// It is necessary to substract initial strains in order to invoke initial nonzero stress
// state for zero displacements (i.e. zero strains)
// sig = E*(eps - eps_p), sig_0 = E*eps_0. For eps = 0: sig = sig_0 => eps_p = -eps_0
// epsp[i] -= Mm->ic[ipp][3+i];
}
gamma=Mm->ip[ipp].eqother[ido+ncomp];
q[0] = Mm->ip[ipp].eqother[ido+ncomp+1]; // effective preconsolidation pressure \bar{p}_c
q[1] = Mm->ip[ipp].eqother[ido+ncomp+2]; // apparent adhesion p_s = k * s
 
// stress return algorithm
switch(sra.give_tsra ())
{
case cp:
ni=sra.give_ni ();
err=sra.give_err ();
matcomp = actualize_stiffmat(*Mp->nlman, Mp->istep, Mp->jstep);
if (Mp->istep >= 265){
matcomp = 0;
}
if (matcomp) reallocm(RSTCKMAT(ncomp, ncomp, d));
ret = Mm->cutting_plane (ipp, im, ido, gamma, epsn, epsp, q, ni, err, matcomp, d);
if (ret)
pnewdt = 0.5;
break;
case gsra:
ni=sra.give_ni ();
err=sra.give_err ();
Mm->newton_stress_return (ipp, im, ido, gamma, epsn, epsp, q, ni, err);
break;
default:
print_err("wrong type of stress return algorithm is required", __FILE__, __LINE__, __func__);
abort ();
}
/*
////////////////////////////////
// elastic material for debug??
// initial values
for (i=0;i<ncomp;i++){
epsn[i]=epsp[i]=Mm->ip[ipp].strain[i];
}
reallocm(RSTCKMAT(ncomp, ncomp, d));
Mm->elmatstiff (d,ipp,ssst);
nu = 0.3;
mxv (d,epsn,sig);
if (Mm->ip[ipp].ssst == planestress)
Mm->ip[ipp].strain[3] = -nu / (1.0 - nu) * (epsn[0]+epsn[1]);
if ((Mp->eigstrains == 4) || (Mp->eigstrains == 5))
{
for (i=0;i<ncomp;i++)
sig(i) += Mm->eigstresses[ipp][i];
}
for (i=0;i<ncomp;i++){
Mm->ip[ipp].stress[i]=sig(i);
}
////////////////////////////////
*/
 
 
// new data storage
for (i=0; i<ncomp; i++){
//epsp[i] += Mm->ic[ipp][3+i];
Mm->ip[ipp].other[ido+i]=epsp[i];
}
Mm->ip[ipp].other[ido+ncomp]=gamma;
Mm->ip[ipp].other[ido+ncomp+1]=q[0]; // the first hardening parameter \bar{p}_c
Mm->ip[ipp].other[ido+ncomp+2]=q[1]; // the second hardening parameter p_s
// other[ido+ncomp+3] = v_lambda1; it is the initial value and therefore it does not require actualization
// other[ido+ncomp+4] = v_ini; it is the initial value and therefore it does not require actualization
 
Mm->givestress(0, ipp, sig);
 
give_full_vector(sigt,sig,Mm->ip[ipp].ssst);
give_full_vector(epsnt,epsn,Mm->ip[ipp].ssst);
give_full_vector(epspt,epsp,Mm->ip[ipp].ssst);
 
i1s = first_invar (sigt)/3.0;
// the second invariant of deviator
// it is expressed with the help of the stress components
// components of the deviator are not needed
j2s = sqrt(j2_stress_invar (sigt));
 
epsv = first_invar (epsnt);
epsvp = first_invar (epspt);
Mm->ip[ipp].other[ido+ncomp+5] = i1s;
Mm->ip[ipp].other[ido+ncomp+6] = j2s;
Mm->ip[ipp].other[ido+ncomp+7] = epsv;
Mm->ip[ipp].other[ido+ncomp+8] = epsvp;
Mm->ip[ipp].other[ido+ncomp+9] = Mm->givenonmechq(saturation_degree, ipp);
// volumetric strain rate
//Mm->ip[ipp].other[ido+ncomp+10] = (epsv - Mm->ip[ipp].eqother[ido+ncomp+7])/dtime;
// the volumetric strain rate is computed via generalized trapesoidal rule
Mm->ip[ipp].other[ido+ncomp+10] = 0.5*((epsv - Mm->ip[ipp].eqother[ido+ncomp+7])/dtime + Mm->ip[ipp].eqother[ido+ncomp+10]);
 
// reference presure = p1
double p1 = Mm->ic[ipp][1];
// specific volume at the reference pressure p_1 = v_lambda1
double v_lambda1 = Mm->ic[ipp][0];
// specific volume for the actual preconsolidation pressure = v_pc
double v_pc = v_lambda1 - lambda * log(q[0]/p1);
// specific volume for the actual pressure p
double v;
if (i1s < 0.0)
v = v_pc + kappa*log(q[0]/i1s);
else
v = v_pc + kappa*log(-q[0]);
// actual porosity n
Mm->ip[ipp].other[ido+ncomp+11] = (v-1.0)/v;
// suction
Mm->ip[ipp].other[ido+ncomp+12] = Mm->givenonmechq(suction, ipp);
// Young modulus
Mm->ip[ipp].other[ido+ncomp+13] = give_actual_ym(ipp, im, ido);
// time step scaling factor
Mm->ip[ipp].other[ido+ncomp+14] = pnewdt;
 
if (matcomp)
copym(d, Mm->ip[ipp].other+ido+ncomp+15);
 
errr = check_math_errel(Mm->elip[ipp]);
}
 
 
 
 
/**
Function returns flag whether actualize the stiffness matrix according to the setup of the nonlinear solver and
attained number of steps.
 
@param[in] smt - type of the stiffness matrix modification in NR method
@param[in] istep - number of load increment step in NR method
@param[in] jstep - number of inner iteration step in NR method
 
@retval 0 - in the case that actualization of the stiffness matrix is NOT required
@retval 1 - in the case that actualization of the stiffness matrix is required
*/
long dsmmat::actualize_stiffmat(const nonlinman &nlman, long istep, long jstep)
{
long ret = 0;
switch (nlman.stmat){
case initial_stiff:
break;
case tangent_stiff:
ret = 1;
break;
case secant_stiff:
case incr_tangent_stiff:{
if (jstep <= 0)
ret = 1;
break;
}
case ijth_tangent_stiff:{
if (((jstep <= 0) && (istep % nlman.ithstiffchange == 0)) ||
((jstep+1) % nlman.jthstiffchange == 0))
ret = 1;
break;
}
default:{
print_err("unknown type of stiffness matrix is required",__FILE__,__LINE__,__func__);
}
}
return ret;
}
 
 
 
/**
This 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
 
Created by Tomas Koudelka, 09.2012
*/
void dsmmat::updateval (long ipp, long im, long ido)
{
long i,n = Mm->ip[ipp].ncompstr;
 
double e = comp_actual_ym(ipp, im, ido);
for (i=0;i<n;i++){
Mm->ip[ipp].eqother[ido+i]=Mm->ip[ipp].other[ido+i];
}
Mm->ip[ipp].eqother[ido+n] = Mm->ip[ipp].other[ido+n]; // gamma
Mm->ip[ipp].eqother[ido+n+1] = Mm->ip[ipp].other[ido+n+1]; // p_c (hardening parameter - effective preconsolidation pressure)
Mm->ip[ipp].eqother[ido+n+2] = Mm->ip[ipp].other[ido+n+2]; // p_s (hardening parameter - apparent adhesion)
//
// Following three values of the specific volume are constant and they
// are stored directly in the eqother array during the intial step
//
// Mm->ip[ipp].eqother[ido+n+3] = Mm->ip[ipp].other[ido+n+3]; // v_lambda1
// Mm->ip[ipp].eqother[ido+n+4] = Mm->ip[ipp].other[ido+n+4]; // v_ini
//
Mm->ip[ipp].eqother[ido+n+5] = Mm->ip[ipp].other[ido+n+5]; // i1s;
Mm->ip[ipp].eqother[ido+n+6] = Mm->ip[ipp].other[ido+n+6]; // j2s;
Mm->ip[ipp].eqother[ido+n+7] = Mm->ip[ipp].other[ido+n+7]; // epsv;
Mm->ip[ipp].eqother[ido+n+8] = Mm->ip[ipp].other[ido+n+8]; // epsvp;
// saturation degree
Mm->ip[ipp].eqother[ido+n+9] = Mm->ip[ipp].other[ido+n+9]; // Sr
// volumteric strain rate
Mm->ip[ipp].eqother[ido+n+10] = Mm->ip[ipp].other[ido+n+10]; // depsv/dt
// actual porosity n
Mm->ip[ipp].eqother[ido+n+11] = Mm->ip[ipp].other[ido+n+11];
// suction
Mm->ip[ipp].eqother[ido+n+12] = Mm->ip[ipp].other[ido+n+12]; //s
// Young modulus
Mm->ip[ipp].eqother[ido+n+13] = Mm->ip[ipp].other[ido+n+13] = e;
// time step scaling factor
Mm->ip[ipp].eqother[ido+n+14] = Mm->ip[ipp].other[ido+n+14];
// stiffness matrix
for (i=0;i<n*n;i++){
Mm->ip[ipp].eqother[ido+n+15+i] = Mm->ip[ipp].other[ido+n+15+i];
}
//effective mean stress from previous time step
Mm->ip[ipp].eqother[ido+n+15+n*n+1]=Mm->ip[ipp].other[ido+n+15+n*n];
 
// stress increments - it is not needed
//for (i=0;i<n;i++){
//Mm->ip[ipp].eqother[ido+n+15+n*n+i]=Mm->ip[ipp].other[ido+n+15+n*n+1+i];
//}
}
 
 
 
/**
The function returns actual Young modulus value.
 
@param ipp - integration point number
@param im - index of material type for given ip
@param ido - index of internal variables for given material in the ipp other array
 
*/
double dsmmat::give_actual_ym(long ipp, long im, long ido)
{
long ncomp=Mm->ip[ipp].ncompstr;
double e = Mm->ip[ipp].other[ido+ncomp+13];
 
return e;
}
 
 
 
/**
The function computes actual Young modulus value.
 
@param ipp - integration point number
@param im - index of material type for given ip
@param ido - index of internal variables for given material in the ipp other array
 
*/
double dsmmat::comp_actual_ym(long ipp, long im, long ido)
{
long idem = Mm->ip[ipp].gemid();
long ncompo = Mm->givencompeqother(ipp, im);
double e;
 
// initial Young modulus
double e_ini = Mm->give_initial_ym(ipp, idem, ido+ncompo);
// actual Poisson's ratio
double nu = give_actual_nu(ipp, im, ido);
 
// actual values of strains
long ncomp=Mm->ip[ipp].ncompstr;
strastrestate ssst = Mm->ip[ipp].ssst;
//vector epsp(ASTCKVEC(ncomp));
vector epst(ASTCKVEC(6));
vector eps(ASTCKVEC(ncomp));
vector epsp(ASTCKVEC(ncomp));
vector sig(ASTCKVEC(ncomp));
vector q(ASTCKVEC(1));
 
// actual total volumetric strain
Mm->givestrain(0, ipp, eps);
give_full_vector(epst, eps, ssst);
double epsv = first_invar(epst);
// actual plastic volumteric strain
//Mm->giveother(ipp, ido, ncomp, epsp);
// total volumetric strain from the last converged step
double epsvo = Mm->ip[ipp].eqother[ido+ncomp+7];
// total volumetric plastic strain from the last converged step
double epsvpo = Mm->ip[ipp].eqother[ido+ncomp+8];
 
// actual plastic strain
for(long i=0; i<ncomp; i++)
epsp(i) = Mm->ip[ipp].other[ido];
give_full_vector(epst, epsp, ssst);
double epsvp = first_invar(epst);
 
// actual value of p_c
//updateq(ipp, ido, eps, epsp, sig, q);
//double pc = q(0);
double pc = Mm->ip[ipp].other[ido+ncomp+1];
 
/*
// initial value of elastic strain
for (long i=0; i<ncomp; i++)
eps(i) = Mm->ic[ipp][3+i];
give_full_vector(auxt, eps, ssst);
double epsv_ini = first_invar(auxt);
if (epsv >= epsv_ini)
return e_ini;*/
// actual value of of specific volume
double v_ini = Mm->ip[ipp].eqother[ido+ncomp+4];
//double v = v_ini*(1.0+epsv);
 
//double p = pc/exp((v-v_pc)/kappa);
double po = Mm->ip[ipp].eqother[ido+ncomp+5];
if ((po == 0.0) || (epsv == 0.0))
return e_ini;
if (po > pc){
// for the unloading: \Delta eps^{el}_V = \Delta eps_V
// actual p according actual swelling line
double epsve = (epsv-epsvo) - (epsvp - epsvpo);
double p = po*exp(-(epsve)*v_ini/kappa);
if (epsve == 0.0)
e = 3.0*(1.0-2.0*nu)*v_ini*(-p)/kappa;
else
e = 3.0*(1.0-2.0*nu)*(p-po)/(epsve);
}
else{
e = e_ini;
}
 
//e = 3.0*(1.0-2.0*nu)*v*(-p)/kappa;
 
return e;
}
 
 
 
/**
The function returns actual Poisson's ratio.
 
@param ipp - integration point number
@param im - index of material type for given ip
@param ido - index of internal variables for given material in the ipp other array
 
*/
double dsmmat::give_actual_nu(long ipp, long im, long ido)
{
long idem = Mm->ip[ipp].gemid();
long ncompo = Mm->givencompeqother(ipp, im);
double nu = Mm->give_initial_nu(ipp, idem, ido+ncompo);
 
return nu;
}
 
 
/**
The function returns time step scaling factor required by the 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 scaling factor provided by the dsmmat model
 
Created by Tomas Koudelka, 5.2022
*/
double dsmmat::dstep_red(long ipp, long im, long ido)
{
long ncomp = Mm->ip[ipp].ncompstr;
return (Mm->ip[ipp].other[ido+ncomp+14]);
}
 
 
 
/**
Function returns irreversible plastic strains.
 
@param ipp - integration point number in the mechmat ip array.
@param ido - index of the first internal variable for given material in the ipp other array
@param epsp - %vector of irreversible strains
Returns vector of irreversible strains via parameter epsp
 
Created by Tomas Koudelka, 09.2012
*/
void dsmmat::giveirrstrains (long ipp, long ido, vector &epsp)
{
long i;
for (i=0;i<epsp.n;i++)
epsp[i] = Mm->ip[ipp].eqother[ido+i];
}
 
 
 
/**
This function extracts consistency parametr gamma for the reached equilibrium state
from the integration point other array.
 
@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 consistency parameter.
 
Created by Tomas Koudelka, 09.2012
*/
double dsmmat::give_consparam (long ipp,long ido)
{
long ncompstr;
double gamma;
 
ncompstr=Mm->ip[ipp].ncompstr;
gamma = Mm->ip[ipp].eqother[ido+ncompstr];
 
return gamma;
}
 
 
 
/**
The function extracts saturation degree s from the integration point eqother array.
This value remains constant from initialization of the model.
 
@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 saturation degree.
 
Created by Tomas Krejci, 14/12/2014
*/
double dsmmat::give_saturation_degree(long ipp, long ido)
{
long ncompstr;
double s;
 
ncompstr=Mm->ip[ipp].ncompstr;
s = Mm->ip[ipp].other[ido+ncompstr+9];
return s;
}
 
/**
The function extracts preconsolidation pressure p_c for the attained state
from the integration point other array.
 
@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 preconsolidation pressure.
 
Created by Tomas Koudelka, 8.10.2013
*/
double dsmmat::give_preconspress(long ipp, long ido)
{
long ncompstr;
double pc;
 
ncompstr=Mm->ip[ipp].ncompstr;
pc = Mm->ip[ipp].other[ido+ncompstr+1];
return pc;
}
 
 
 
/**
The function extracts virgin void ratio e_lambda1 for the attained state (it is constant initial value)
from the integration point eqother array. This value remains constant from initialization of the model.
 
@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 virgin porosity e_lambda1.
 
Created by Tomas Koudelka, 8.10.2013
*/
double dsmmat::give_virgporosity(long ipp, long ido)
{
long ncompstr;
double e_lambda1;
 
ncompstr=Mm->ip[ipp].ncompstr;
e_lambda1 = Mm->ip[ipp].eqother[ido+ncompstr+3]-1.0;
return e_lambda1;
}
 
 
 
/**
The function extracts initial porosity n_ini for the attained state (it is constant initial value)
from the integration point eqother array. This value remains constant from initialization of the model.
 
@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 initial porosity e_ini.
 
Created by Tomas Koudelka, 8.10.2013
*/
double dsmmat::give_iniporosity(long ipp, long ido)
{
long ncompstr;
double v_ini, n_ini;
 
ncompstr=Mm->ip[ipp].ncompstr;
v_ini = Mm->ip[ipp].eqother[ido+ncompstr+4]; // v_ini = 1.0 + e_ini
n_ini = (v_ini-1.0)/v_ini;
return n_ini;
}
 
 
 
/**
The function extracts porosity for the actual state from the integration point other array.
 
@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, 06.2020
*/
double dsmmat::give_porosity(long ipp, long ido)
{
long ncompstr;
double n;
 
ncompstr=Mm->ip[ipp].ncompstr;
n = Mm->ip[ipp].other[ido+ncompstr+11];
return (n);
}
 
 
 
/**
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 06.2020
*/
double dsmmat::give_strain_vol_rate(long ipp, long ido)
{
long ncomp = Mm->ip[ipp].ncompstr;
 
return Mm->ip[ipp].other[ido+ncomp+10];
}
 
 
 
/**
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.
*/
void dsmmat::give_reqnmq(long *anmq)
{
//if (pr_suc_f == no){
anmq[saturation_degree-1] = 1;
anmq[suction-1] = 1;
//}
//if (pr_tempr_f == no)
//anmq[temperature-1] = 1;
}
 
 
 
/**
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, 09.2012
*/
void dsmmat::changeparam (atsel &atm,vector &val)
{
long i;
for (i=0;i<atm.num;i++)
{
switch (atm.atrib[i])
{
case 0:
m=val[i];
break;
case 1:
lambda=val[i];
break;
case 2:
kappa=val[i];
break;
case 3:
c1_tilde=val[i];
break;
case 4:
c2=val[i];
break;
case 5:
ks=val[i];
break;
default:
print_err("wrong number of atribute", __FILE__, __LINE__, __func__);
}
}
}
/trunk/SIFEL/MEFEL/SRC/dsm.h
0,0 → 1,157
#ifndef DSMMAT_H
#define DSMMAT_H
 
#include "galias.h"
#include "gfunct.h"
#include "xfile.h"
#include "alias.h"
#include "strretalg.h"
struct matrix;
struct vector;
struct atsel;
class nonlinman;
 
 
/**
This class defines double structure plasticity model for expansive clays based on cam-clay material model coupled with moisture transfer
and on a double structure concept according to:
Sanchez, M., Gens, A., Do Nascimento Guimares, L., and Olivella, S., A double structure generalized plasticity model for expansive materials,
International Journal for Numerical and Analytical Methods in Geomechanics, vol. 29, no. 8, pp. 751-787, 2005. doi:10.1002/nag.434.
 
- this concept is not working for the curent MEFEL version, which assumes total values (not their rates) of strains and stresses
 
- it must be reformulated and derived
 
- not completed!! - not working!!
 
 
Plasticity model - modified cam-clay material model:
 
The material is defined by
three usual camclay material constants :
m - is frictional constant and it depends on the frictional angle phi
lambda - slope of the normal consolidationa line
kappa - slope of the swelling line
 
Additionally, there are three parameters which controls
evolution of hardening with respect to degree of saturation and suction
c1_tilde, c2 - controls the ratio of specific volumes v/v_sat (partially saturated/fully saturated)
ks - controls apparent adhesion (intersection of yield surface with p axis)
In addition to these material constants, several initial values
have to be specified at each integration point in the following order :
v_kappa1 - initial specific volume at the reference pressure p1 after
unloading from initial consolidation pressure p_c0 (v_kappa0)
p1 - reference pressure (p_1), it must be negative
p_c0 - initial consolidation pressure, it must be negative
sig0_1 -
. \
. \ components of eigenstresses
. /
sig0_ncomp -
Order of the eqother array components
id | description
------------------+------------------------------------------------
<0; ncompstr-1> | plastic strains
ncompstr | gamma - consistency parameter
ncompstr+1 | hardening parameter p_c - consolidation pressure
ncompstr+2 | hardening parameter p_s - apparent adhesion
ncompstr+3 | v_lambda1 - initial value of specific volume on the NCL at reference pressure p1
. | v_ini - initial specific volume
. | i1s - mean stress
. | j2s - the second invariant of stress deviator
. | epsv - total volume strain
ncompstr+8 | epsvp - plastic volume strain
ncompstr+9 | degree of saturation
ncompstr+10 | depsv/dt - volumtric strain rate
ncompstr+11 | actual porosity e
 
10.2012
TKo
*/
class dsmmat
{
public:
dsmmat (void);
~dsmmat (void);
void read (XFILE *in);
void initval(long ipp, long im, long ido);
double cohesion(vector &qtr);
double yieldfunction (vector &sig, vector &q);
void deryieldfsigma (vector &sig, vector &q, vector &dfds);
void dderyieldfsigma (matrix &ddfds);
void derpotsigma (vector &sig, vector &q, vector &dgds);
void deryieldfq(vector &sig, vector &q, vector &dq);
void deryieldfdqdq(matrix &ddfdq);
void deryieldfdsdq(matrix &dfdsdqt);
void der_q_gamma(long ipp, long ido, vector &sig, vector &qtr, vector &epsp, vector &dqdg);
void dqpardgammadsigma(long ipp, long ido, vector &sig, vector &qtr, vector &epsp, matrix &dqdgds);
void dqpardgammadqpar(long ipp, long ido, vector &sig, vector &qtr, vector &epsp, matrix &dqdgdq);
double plasmodscalar(long ipp, long ido, vector &sig, vector &qtr, vector &epsp);
void updateq(long ipp, long ido, vector &eps, vector &epsp, vector &sig, vector &q);
// void updateq(vector &epsp, strastrestate ssst, vector &q);
void matstiff (matrix &d, long ipp,long ido);
void depmatstiff (matrix &d, long ipp, long ido);
void nlstressesincr (long ipp,long im,long ido);
void givestressincr (long lcid, long ipp, long im, long ido, long fi, vector &sig);
void nlstresses (long ipp,long im,long ido);
long actualize_stiffmat(const nonlinman &nlman, long istep, long jstep);
void updateval (long ipp, long im, long ido);
double comp_actual_ym(long ipp, long im, long ido);
double give_actual_ym(long ipp, long im, long ido);
double give_actual_nu(long ipp, long im, long ido);
double dstep_red(long ipp, long im, long ido);
void giveirrstrains (long ipp, long ido, vector &epsp);
double give_consparam (long ipp, long ido);
double give_preconspress(long ipp, long ido);
double give_saturation_degree(long ipp, long ido);
double give_virgporosity(long ipp, long ido);
double give_iniporosity(long ipp, long ido);
double give_porosity(long ipp, long ido);
double give_strain_vol_rate(long ipp, long ido);
void give_reqnmq(long *anmq);
void changeparam (atsel &atm, vector &val);
 
/// frictional constant
double m;
 
/// slope of normal consolidation line
double lambda;
 
/// slope of swelling line
double kappa;
 
/// first parameter for control of the v/v_sat ratio evolution
double c1_tilde;
 
/// second parameter for control of the v/v_sat ratio evolution
double c2;
 
/// coefficent of apparent adhesion due to suction pressure
double ks;
 
/// soil swelling index reference value
double kappa_s0;
 
/// parameters for the strain rate caculation caused by the suction change
double aks1,aks2;
/// parameters for the thermal strain rate caculation
double a0,a2;
 
/// flag for suction definition (yes=suction evolution is prescribed by suc_fn, no=suction is taken from TRFEL)
//answertype pr_suc_f;
/// function of prescribed suction evolution
//gfunct suc_fn;
/// flag for temperature definition (yes=temperature is prescribed by tempr_fn, no=temperature is taken from TRFEL)
//answertype pr_tempr_f;
/// function of prescribed temperature evolution
//gfunct tempr_fn;
 
/// stress return algorithm
strretalg sra;
};
 
#endif
/trunk/SIFEL/MEFEL/SRC/effstress.cpp
143,7 → 143,7
{
pp = varppv->getval(Mp->time);
sr = varsrv->getval(Mp->time);
// set effective_pore_pressure_component of nonmechq array to constant value
// set effective_pore_pressure_component of nonmechq array to constant value, saturation degree is assued as the effective stress factor chi
Mm->storenonmechq(eff_pore_pressure, ipp, pp*sr);
}
 
/trunk/SIFEL/MEFEL/SRC/elastisomat.cpp
405,18 → 405,17
d[0][0]=s*(1-nu); d[0][1]=s*nu; d[0][2]=s*nu;
d[1][0]=d[0][1]; d[1][1]=d[0][0]; d[1][2]=d[0][1];
d[2][0]=d[0][1]; d[2][1]=d[0][1]; d[2][2]=d[0][0];
 
d[3][3]=g; d[4][4]=g; d[5][5]=g;
 
////////////////////////////////////////////////////////////
// this printing below is only for debug:
fprintf(Out,"\n\n vysledna matice D^M\n");
for (i=0;i<6;i++){
for (j=0;j<6;j++)
fprintf(Out,"%e \n",d[i][j]);
fprintf(Out,"\n");
}
 
//fprintf(Out,"\n\n vysledna matice D^M\n");
//for (i=0;i<6;i++){
//for (j=0;j<6;j++)
// fprintf(Out,"%e \n",d[i][j]);
//fprintf(Out,"\n");
//}
}
 
 
/trunk/SIFEL/MEFEL/SRC/elemswitch.cpp
3957,8 → 3957,13
*/
void stiffmat (long lcid,long eid,matrix &sm)
{
long i,j;
elemtype te;
//debug??!!
//fprintf(Out,"\n stifness matrix eid=%ld\n",eid+1);
//fflush(Out);
 
te = Mt->give_elem_type (eid);
 
switch (te){
4170,6 → 4175,13
default:
print_err("unknown element type is required", __FILE__, __LINE__, __func__);
}
 
//debug??!!
//fprintf(Out,"\n stiffness matrix eid=%ld\n",eid+1);
//for (i=0;i<sm.m;i++)
//for (j=0;j<sm.n;j++)
// fprintf(Out,"%lf ",sm[i][j]);
//fflush(Out);
}
 
 
5615,10 → 5627,10
Mm->eigstresses = Mm->aip_eigstresses;
Mm->tempstrains = Mm->aip_tempstrains;
 
#ifdef INC_OPENMP
#pragma omp parallel num_threads(4)
#pragma omp for nowait
#endif
//#ifdef INC_OPENMP
// #pragma omp parallel num_threads(4)
// #pragma omp for
//#endif
 
// just call computenlstresses procedure on all auxiliary integration points
// and check for math errors
/trunk/SIFEL/MEFEL/SRC/generalmod.cpp
51,7 → 51,7
qstatev[6] = SrM
qstatev[7] = a_scan (required on input)
qstatev[8] = re
 
Order of parameters in the array rkf_parms
rkf_parms[0] = err_sig
rkf_parms[1] = h_min
91,88 → 91,47
garray_move(stress_gen, stress_gen_init, ngstress);
garray_move(strain_gen, strain_gen_init, ngstrain);
garray_move(qstatev, qstatev_init, nstatev);
initialise_parameters(parms);
 
if (parms) initialise_parameters(parms);
 
//Initialises state variables and parameters (flag 0)
if (flag == 0) {
initialise_variables(strain_gen, stress_gen, qstatev, dstrain_gen, 1.0, parms, kinc);
}
 
//direct stiffness matrix (approximate, but can be calculated with zero strain increment provided)
else if (flag == 3) {
double dstrain_gen_zero[max_ngstrain];
garray_set(dstrain_gen_zero, 0, max_ngstrain);
errormath += correct_statev_values(strain_gen, stress_gen, qstatev, dstrain_gen_zero, 1);
direct_stiffness_matrix(strain_gen, stress_gen, qstatev, dstrain_gen, 1.0, DDtan_gen, parms, kinc);
 
direct_stiffness_matrix(strain_gen, stress_gen, qstatev, dstrain_gen, 1.0, DDtan_gen, parms, kinc, flag);
}
 
//Updates variables, if flag == 1 also stiffness matrix by perturbation
else if (flag == 1 || flag == 2) {
 
errormath += correct_statev_values(strain_gen, stress_gen, qstatev, dstrain_gen, 1);
 
//Update variables
errorrkf += calc_rkf(strain_gen, stress_gen, qstatev, dstrain_gen, dtime, parms, rkf_statev, rkf_parms, kinc);
errormath += correct_statev_values(strain_gen, stress_gen, qstatev, dstrain_gen, 2);
 
//Calculate stiffness matrix by perturbation of current strain increment
if(flag == 1) {
long error_statev_perturbate = 0;
bool perturbate=false;
if(kinc<20 && rkf_parms[4]<10) perturbate=true;
if(perturbate) {
double stress_gen_pert[max_ngstress];
double strain_gen_pert[max_ngstrain];
double dstrain_gen_pert[max_ngstrain];
double qstatev_pert[max_nstatev];
garray_set(stress_gen_pert, 0.0, max_ngstress);
garray_set(strain_gen_pert, 0.0, max_ngstrain);
garray_set(dstrain_gen_pert, 0.0, max_ngstrain);
garray_set(qstatev_pert, 0.0, max_nstatev);
double pertinc_all[c_ngstrain];
for(int i=0; i<6; i++) pertinc_all[i]=1.e-6;
pertinc_all[6]=-sairentry0*1.e-6; //ds
pertinc_all[7]=1.e-3; //dT
for(int i=0; i<ngstrain; i++) {//stiffness matrix as dDsig/dDepsiolon
 
garray_move(dstrain_gen, dstrain_gen_pert, ngstrain);
dstrain_gen_pert[i]+=pertinc_all[i];
garray_move(stress_gen_init, stress_gen_pert, ngstress);
garray_move(strain_gen_init, strain_gen_pert, ngstrain);
garray_move(qstatev_init, qstatev_pert, nstatev);
errorrkf += calc_rkf(strain_gen_pert, stress_gen_pert, qstatev_pert, dstrain_gen_pert, dtime, parms, rkf_statev, rkf_parms, kinc);
error_statev_perturbate += correct_statev_values(strain_gen_pert, stress_gen_pert, qstatev_pert, dstrain_gen_pert, 3);
for(int j=0; j<ngstress; j++) {
DDtan_gen[j*ngstrain+i]=(stress_gen_pert[j]-stress_gen[j])/pertinc_all[i];
}
}
}
 
if (!perturbate || errorrkf || errormath || error_statev_perturbate) {
direct_stiffness_matrix(strain_gen_init, stress_gen_init, qstatev_init, dstrain_gen, dtime, DDtan_gen, parms, kinc);
}
errormath += correct_DDtan_gen(strain_gen, stress_gen, DDtan_gen);
direct_stiffness_matrix(strain_gen_init, stress_gen_init, qstatev_init, dstrain_gen, dtime, DDtan_gen, parms, kinc, flag);
}
//cout<<-strain_gen[6]<<" "<<DDtan_gen[6]<<" "<<-stress_gen[0]<<endl;//debug print
}
else {
cout<<"Generalmod called with wrong flag"<<endl;
cout<<"Generalmod called with wrong flag"<<endl;
}
 
if(check_math_error() || errormath) {
cout<<"Generalmodel ended up with math error"<<endl;
long matherror_here=check_math_error();
if(matherror_here || errormath) {
cout<<"Generalmodel ended up with math error, errormath = "<<errormath<<", matherror_here = "<<matherror_here<<", errorrkf = "<<errorrkf<<", flag = "<<flag<<endl;
return(1);
}
 
if(errorrkf) {
garray_move(stress_gen_init, stress_gen, ngstress);
garray_move(strain_gen_init, strain_gen, ngstrain);
205,7 → 164,7
double dsignet[9], double &Sr_new, double dqstatev[], int kinc) {
 
long errorfsigq = 0;
 
//BEGIN convert increments to rates
dsuction/=dtime;
dTemper/=dtime;
225,17 → 184,20
garray_set(&H_unsat[0][0],0,9);
garray_set(&HT_unsat[0][0],0,9); // initialises tensors
double fm=0.5; // initially sets fm double-structure coupling factor to 0.5
double fm_lambda_act=0.5;
double fu=0; // initially sets fu factor (to Hs and HT) to zero
double SrM=qstatev[6]; // takes the macrostructural Sr from the state variables vector
double Sr=qstatev[2];
double Sr=qstatev[2];
bool swelling=false;
 
give_LNH(signet, suction, Temper, qstatev, hypo_L, hypo_N, H_unsat, HT_unsat, fm, fu); // calculates tangent operators
 
double eM=qstatev[5]; // takes the macrostructural void ratio from the state variables vector
//double SrM=qstatev[6]; // does NOT take Sr again
double a_scan=qstatev[7]; // takes scanning curve
double re=qstatev[8]; // takes re (relative void ratio)
double sewM=aer*sairentry0*eM0/eM*(aTparam+bTparam*Temper)/(aTparam+bTparam*Trparam);
 
give_LNH(signet, suction, Temper, qstatev, hypo_L, hypo_N, H_unsat, HT_unsat, swelling, fu); // calculates tangent operators
 
if(re<0) {
if(debug) cout<<"re<0 for some reason, correcting it, just for fm calculation. re="<<re<<" eM="<<eM<<" em="<<qstatev[4]<<" e="<<qstatev[0]<<" ascan="<<a_scan<<endl;
re=0;
272,41 → 234,33
//Trial trace of dep_m for the given iteration
double trdepm=0; // here trdepm is initialised to zero, and this value is used in the first iteration
 
double sewM=aer*sairentry0*eM0/eM*(aTparam+bTparam*Temper)/(aTparam+bTparam*Trparam);
double rlambda_for_ascan=0;
double rlambda_for_se=0;
double rlambda=give_rlambda(suction, a_scan, dsuction, sewM, SrM, rlambda_for_ascan, rlambda_for_se);
bool swelling=true;
 
double iterfactor=0;
 
while(1) {
 
//calculation of the double structure coupling factor
swelling=true;
 
bool notbytrdepm=false;
if(fabs(dsuction)>1.e-4) notbytrdepm=true;
 
if(!notbytrdepm && trdepm<0) swelling=false;
else if (notbytrdepm && dsuction<0) swelling=false;
 
double fm_swelling=1-gscalar_power(re,mmparam); //swelling
fm=(csh*(suction/sewM));
if(swelling) fm=fm_swelling;
else if(fm>(1-fm_swelling)) fm=1-fm_swelling;
if(fm<0) fm=0;
else if (fm>1) fm=1;
 
if(num_iter == 0 || num_iter == 1 || num_iter == 5 || num_iter % 50 == 0)
give_LNH(signet, suction, Temper, qstatev, hypo_L, hypo_N, H_unsat, HT_unsat, fm, fu);
give_LNH(signet, suction, Temper, qstatev, hypo_L, hypo_N, H_unsat, HT_unsat, swelling, fu);
 
depM[0]=deps[0]-fm*trdepm/3;
depM[4]=deps[4]-fm*trdepm/3;
depM[8]=deps[8]-fm*trdepm/3;
give_fm(fm, fm_lambda_act, suction, sewM, re, swelling);
double depm[9];
garray_set(depm,0,9);
 
for(int i=0; i<3; i++) depM[3*i+i]=deps[3*i+i]-fm*trdepm/3;
 
double DM[3][3];
garray_set(&DM[0][0], 0, 3*3);
garray_move(depM, &DM[0][0], 3*3);
340,26 → 294,25
dsignet_iter[3*i+j]=dsigMef[3*i+j]-kron_delta[i][j]*chi*(corr_s+corr_eM+corr_T);
}
}
double em=qstatev[4];
 
if(num_iter>1000) {//for zero eM all the deformation is due to microstructure
fu=0;
garray_set(depM,0,9);
fm=1;
 
trdepm=(deps[0]+deps[4]+deps[8]);
double pefsat=(signet[0]+signet[4]+signet[8])/3+suction;
double dpefsat=-(trdepm-alpha_s*dTemper)*pefsat/kappam;
double demdpm=give_demdpm(pefsat, em);
double dpefsat=(trdepm-alpha_s*dTemper)*(1+em)/demdpm;
dsignet_iter[0]=dsignet_iter[4]=dsignet_iter[8]=(dpefsat-dsuction);
}
 
//Calculate microstructural strain corresponding to the obtained dsignet in the current iteration.
double depm_iter[9];
garray_set(depm_iter,0,9);
calc_depm(signet, suction, Temper, dsuction, dTemper, dsignet_iter, depm_iter, fu);
double trdepm_iter = calc_trdepm(signet, suction, Temper, em, dsuction, dTemper, dsignet_iter, fu);
 
//Calculate the difference between microstructural strain obtained in the current iteration and the trial strain trdepm
double old_error_measure=error_measure;
error_measure=trdepm-3*depm_iter[0];
error_measure=trdepm-trdepm_iter;
 
//Solution found
if(gscalar_dabs(error_measure)<mexerror)
386,26 → 339,26
trdepm+=step_depm;
*/
if((old_error_measure>0 && error_measure<0) || (old_error_measure<0 && error_measure>0)) iterfactor+=1;
trdepm=(3*depm_iter[0]+iterfactor*trdepm)/(iterfactor+1); // after the first iteration trdepm is updated from zero to 1/4 of 3*depm_iter[0] (+3/4 of trdepm later when trdepm is not zero)
 
trdepm=(trdepm_iter+iterfactor*trdepm)/(iterfactor+1); // after the first iteration trdepm is updated from zero to 1/4 of 3*depm_iter[0] (+3/4 of trdepm later when trdepm is not zero)
 
if(num_iter>1000) {
errorfsigq = true;
if(debug) {
cout<<endl<<"-----------------------------------------------------"<<endl;
cout<<"Error in microstructural iterations."<<endl;
cout<<"Error in microstructural iterations."<<endl;
for(int i=0; i<6; i++) cout<<"signet["<<i<<"] "<<signet[i]<<endl;
cout<<"suction "<<suction<<endl;
for(int i=0; i<nstatev; i++) cout<<"qstatev["<<i<<"] "<<qstatev[i]<<endl;
cout<<"-----------------------------------------------------"<<endl;
}
exit(0);
exit(1);
 
}
num_iter++;
}
garray_move(dsignet_iter, dsignet, 9);
 
//BEGIN rates back to increments
dsuction*=dtime;
dTemper*=dtime;
416,10 → 369,61
//this calculates dqstatev, it is not updating the original values
int flag=2;
update_hisv(signet, suction, Temper, qstatev, deps, dsuction, dTemper, dsignet, Sr_new, dqstatev, flag, fu, kinc);
 
return(errorfsigq);
}
 
void Hypoplasti_unsat_expansive_thermal_2017::give_fm(double& fm, double& fm_lambda_act, double suction, double sewM, double re, bool swelling) {
 
double fm_swelling=1-gscalar_power(re,mmparam); //swelling
fm=(csh*(suction/sewM));
 
if(swelling) fm=fm_swelling;
else if(fm>(1-fm_swelling)) fm=1-fm_swelling;
 
if(fm<0) fm=0;
else if (fm>1) fm=1;
 
fm_lambda_act = -fm; //in the paper 2017, sign fm was wrong in lambda_act calculation
}
 
void Hypoplasti_unsat_expansive_thermal_2022::give_fm(double& fm, double& fm_lambda_act, double suction, double sewM, double re, bool swelling) {
 
double fm_swelling=1-gscalar_power(re,mmparam); //swelling
fm=(csh*(suction/sewM));
 
if(swelling) fm=fm_swelling;
else if(fm>(1-fm_swelling)) fm=1-fm_swelling;
 
if(fm<0) fm=0;
else if (fm>1) fm=1;
 
fm_lambda_act = -fm; //in the paper 2017, sign fm was wrong in lambda_act calculation
}
 
void Hypoplasti_unsat_expansive_thermal::give_fm(double& fm, double& fm_lambda_act, double suction, double sewM, double re, bool swelling) {
 
double fm_swelling=1-gscalar_power(re,mmparam);
double fm_shrinkage=csh*(suction/sewM);
if(suction>sewM) fm_shrinkage=csh;
if (fm_shrinkage > (1-fm_swelling)) fm_shrinkage=1-fm_swelling;
 
if(fm_swelling<0) fm_swelling=0;
else if (fm_swelling>1) fm_swelling=1;
if(fm_shrinkage<0) fm_shrinkage=0;
else if (fm_shrinkage>1) fm_shrinkage=1;
 
if(swelling) fm=fm_swelling;
else fm=fm_shrinkage;
 
fm_lambda_act=fm_shrinkage;
}
 
 
/*void Hypoplasti_unsat_expansive_thermal_2022::give_fm(double& fm, double& fm_lambda_act, double suction, double sewM, double re, double swelling) {
 
}*/
 
/**
The function calculates state variable increment vector dqstatev[]. The old values of qstatev[0] (void ratio) and qstatev[6] (a_scan) must be provided by the FEM (even for the initialisation stage). The order of state variables is as follows:
[0]e (required on input)
464,28 → 468,31
//calculating state variable increments/new values
double delta_e=(1+evoid)*gtrace(D);
double evoid_new=evoid+delta_e;
if(evoid_new<0) evoid_new=0;
double Temper_new=Temper+dTemper;
 
double signet_new[9];
garray_add(signet, dsignet, signet_new, 9);
double suction_new=suction+dsuction;
double emstarT=exp(alpha_s*(Temper-Trparam)+log(1+emstar))-1.0;
double emstarT_new=exp(alpha_s*(Temper_new-Trparam)+log(1+emstar))-1.0;
 
double pefsat_new=(signet_new[0]+signet_new[4]+signet_new[8])/3+suction_new;
double pefsat=(signet[0]+signet[4]+signet[8])/3.0+suction;
double em=qstatev[4];
if(fu>1) fu=1;
double d_em=(1.0+em)*(alpha_s*dTemper-kappam/pefsat*(pefsat_new-pefsat));
double em_new=em;
 
if(d_em>0) d_em*=(1.0-fu);
double em_new=em+d_em;
 
if(flag==0) {
em_new=exp(kappam*log(smstar/pefsat_new)+log(1+emstarT_new))-1.0;
em=exp(kappam*log(smstar/pefsat)+log(1+emstarT))-1.0;
double pefsat_new=(signet_new[0]+signet_new[4]+signet_new[8])/3+suction_new;
double pefsat=(signet[0]+signet[4]+signet[8])/3.0+suction;
double emstarT=exp(alpha_s*(Temper-Trparam))-1.0;
double emstarT_new=exp(alpha_s*(Temper_new-Trparam))-1.0;
double em_pefsat_new=init_em_pefsat(pefsat_new);
double em_pefsat=init_em_pefsat(pefsat);
em_new=exp(log(1+em_pefsat_new)+log(1+emstarT_new))-1.0;
em=exp(log(1+em_pefsat)+log(1+emstarT))-1.0;
}
 
double trdepm = calc_trdepm(signet, suction, Temper, em, dsuction, dTemper, dsignet, fu);
double d_em=(1+em)*trdepm;
em_new=em+d_em;
 
double min_void=0.0001;
if(em_new<min_void) em_new=min_void;
if(em<min_void) em=min_void;
531,17 → 538,18
double se=sedM*(aer+a_scan-aer*a_scan);
 
double a_scan_new=0.0;
double sD=0.0;
double SrM=qstatev[6];
if (suction<sewM) {
// suction at the main drying curve - equation (39) of Masin[2]
sD=sedM/se*suction;
double sD=sedM/se*suction;
double sWM=sewM/(gscalar_power(SrM,(1/lambdap0)));
double sDM=sWM/aer;
double d_a_scan=0.0;
double rlambda_for_ascan=0;
double rlambda_for_se=0;
double rlambda=give_rlambda(suction, a_scan, dsuction, sewM, SrM, rlambda_for_ascan, rlambda_for_se);
 
if(aer<1) d_a_scan = (1.0-rlambda_for_ascan)/(sD*(1.0-aer))*(suction_new-suction);
if(aer<1 && suction<sWM && suction>sDM ) d_a_scan = (1.0-rlambda_for_ascan)/(sD*(1.0-aer))*(suction_new-suction);
a_scan_new=a_scan+d_a_scan;
if (a_scan_new>1.0 )
a_scan_new=1.0;
575,7 → 583,7
dqstatev[6]=SrM_new-SrM;
dqstatev[7]=a_scan_new-qstatev[7];
dqstatev[8]=0; //re: to be filled later
 
//calculate new state variables, needed just for re
double qstatev_new[c_nstatev];
garray_add(qstatev, dqstatev, qstatev_new, c_nstatev);
585,11 → 593,11
double sigef_new[9];
make_sig_unsat(signet_new, suction_new, SrM_new, sigef_new, suction_new);
double pmeanef_new=-(sigef_new[0]+sigef_new[4]+sigef_new[8])/3.0;
 
double emaxisot_new=min_void;
if(pmeanef_new<1.0) emaxisot_new=exp(Nuse_new)-1.0;
else if(Nuse_new > lambda_use_new*log(pmeanef_new)) emaxisot_new=exp(Nuse_new-lambda_use_new*log(pmeanef_new))-1.0; // maximum void ratio for the state corresponding to NCL - equation (88) of Masin[2]
 
if ( /*((evoid_new>emaxisot_new) && (evoid_new>evoid)) ||*/ ((evoid_new<min_void) && (evoid_new<evoid)) ) {
dqstatev[0]=0.0; // rate of total void ratio
dqstatev[4]=0.0; // rate of void ratio on microlevel
597,7 → 605,7
}
double re_new=min_void;
if(emaxisot_new>em_new) re_new=(evoid_new-em_new)/(emaxisot_new-em_new);
 
if(re_new<min_void) re_new=min_void;
else if(re_new>1) re_new=1;
 
606,6 → 614,12
dqstatev[8]=dre;
}
 
double Hypoplasti_unsat_expansive_thermal::init_em_pefsat(double pefsat) {
double em_pefsat = exp(kappam*log(smstar/pefsat)+log(1+emstar))-1;
return em_pefsat;
}
 
 
/**
The function calculates the macrostructural effective stress.
 
619,7 → 633,7
 
Created by D. Masin 13.7.2015
*/
void Hypoplasti_unsat_expansive_thermal::make_sig_unsat(double sig[3*3], double suction, double SrM,
void Hypoplasti_unsat_expansive_thermal::make_sig_unsat(double sig[3*3], double suction, double SrM,
double tensor_unsat[3*3], double &scalar_unsat) {
 
garray_set(tensor_unsat, 0, 3*3);
648,22 → 662,25
 
Created by D. Masin 13.7.2015
*/
void Hypoplasti_unsat_expansive_thermal::calc_depm(double signet[9], double suction, double Temper, double dsuction,
double dTemper, double dsignet[9], double depm[9], double fu) {
double Hypoplasti_unsat_expansive_thermal::calc_trdepm(double signet[9], double suction, double Temper, double em, double dsuction, double dTemper, double dsignet[9], double fu) {
 
double pefsat=(signet[0]+signet[4]+signet[8])/3+suction;
double dpefsat=(dsignet[0]+dsignet[4]+dsignet[8])/3+dsuction;
double demdpm=give_demdpm(pefsat, em);
double trdepm=demdpm*dpefsat/(1+em)+alpha_s*dTemper;
 
garray_set(depm,0,9);
depm[0]=depm[4]=depm[8]=-kappam*(dpefsat/pefsat)/3;
for(int i=0; i<3; i++) depm[3*i+i]+=alpha_s*dTemper/3;
if(fu>1)
fu=1;
if((depm[0]+depm[4]+depm[8])>0) {
for(int i=0; i<3; i++) depm[3*i+i]*=(1.0-fu);
}
if(fu>1) fu=1;
if(trdepm>0) trdepm*=(1.0-fu);
return trdepm;
}
 
double Hypoplasti_unsat_expansive_thermal::give_demdpm(double pefsat, double em) {
if(pefsat>-1) pefsat=-1;
double demdpm = -kappam*(1+em)/pefsat;
return demdpm;
}
 
 
/**
The function calculates current position and slope of normal compression line Nuse and lambda_use, and also the derivatives (dpe/ds)/pe and (dpe/dT)/pe
 
703,7 → 720,7
// Hvorslev equivalent pressure - equation (74) of Masin[2]
double pe=exp((Nuse-log(1+evoid))/lambda_use);
dpeds_divpe=0;
 
double eM=qstatev[5]; // takes the macrostructural void ratio from the state variables vector
double sewM=aer*sairentry0*eM0/eM*(aTparam+bTparam*Temper)/(aTparam+bTparam*Trparam);
 
729,7 → 746,7
*/
void Hypoplasti_unsat_expansive_thermal::give_LNH(double signet[9], double suction,
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], double fm, double &fu) {
double HT_unsat[3][3], bool swelling, double &fu) {
 
double sig_ef[9];
double stresssuction=0;
740,9 → 757,9
garray_set(&T[0][0], 0, 3*3);
garray_move(sig_ef, &T[0][0], 3*3);
double p_mean=-gtrace(T)/3;
if(p_mean<0) {
if(p_mean<1) {
if(debug) cout<<"Correcting mean stress, p_mean="<<p_mean<<endl;
p_mean=0;
p_mean=1;
}
 
double kron_delta[3][3];
866,15 → 883,19
//get lambda_act for constant suction;
double eM=qstatev[5];
double em=qstatev[4];
double pefsat=-((signet[0]+signet[4]+signet[8])/3+suction);
double lambda_act=lambda_use;
if (unsat_active) {
// lambda_act=lambda_use/(1.0-(nparam-lparam*log(p))*(1.0+e)/e);
lambda_act=(lambda_use*eM*(1+em)-(p_mean/pefsat)*kappam*(1+eM)*(1+em)*(nparam-lparam*log(p_mean))-(p_mean/pefsat)*kappam*fm*eM*(1+em))/(eM*(1+em)-(1+evoid)*(nparam-lparam*log(p_mean)));
// double A=kappam*(1+eM)*(nparam-lparam*log(p))/eM+kappam*fm;
// double citatel=lambda_use-A*(p/pefsat)*(1-kappam*(1+eM)*SrM*lambdap0*suction/(eM*pefsat));
// double jmenovatel=1-(1+e)/(eM*(1+em))*(nparam-lparam*log(p)-A*SrM*lambdap0*suction/pefsat);
// lambda_act=citatel/jmenovatel;
double fm=0, fm_lambda_act=0;
double re=qstatev[8]; // takes re (relative void ratio)
double sewM=aer*sairentry0*eM0/eM*(aTparam+bTparam*Temper)/(aTparam+bTparam*Trparam);
 
give_fm(fm, fm_lambda_act, suction, sewM, re, swelling);
double pefsat=(signet[0]+signet[4]+signet[8])/3+suction;
double demdpm=give_demdpm(pefsat, em);
 
double p_mean_positive=p_mean;
if(p_mean_positive<1.0) p_mean_positive=1.0;
lambda_act=(lambda_use*eM*(1+em)+demdpm*p_mean_positive*(1+eM)*(nparam-lparam*log(p_mean_positive))+fm_lambda_act*demdpm*p_mean_positive*eM)/(eM*(1+em)-(1+evoid)*(nparam-lparam*log(p_mean_positive)));
}
fs=9*p_mean/2*(1/kappa+1/lambda_act)/Am;
garray_multiply(&hypo_L[0][0][0][0], &hypo_L[0][0][0][0], fs, 81);
927,10 → 948,10
fu=gscalar_power(pdivpsbs, 2);
else if (pdivpsbs>5)
fu=gscalar_power(5, 2);
double cic=1;
if(nparam<0) fu=0;
double fu_Hunsat = nparam<0 ? 0 : fu;
 
bool m0_OCRindep_collapse=true;
double cic=1;
if(m0_OCRindep_collapse && fd<fdsbs) {
cic=(lambda_act+kappa)*(gscalar_power(2.0,alpha_power)-fd)+2*kappa*fd;
cic=cic/((lambda_act+kappa)*(gscalar_power(2.0,alpha_power)-fdsbs)+2*kappa*fdsbs);
940,8 → 961,8
garray_multiply(&T[0][0], &H_unsat[0][0], dpeds_divpe*cic*lambda_use/lambda_act, 9);
garray_set(&HT_unsat[0][0], 0, 3*3);
garray_multiply(&T[0][0], &HT_unsat[0][0], dpedT_divpe*cic*lambda_use/lambda_act, 9);
garray_multiply(&H_unsat[0][0], &H_unsat[0][0], fu, 9); //H times fd/fdSOM
garray_multiply(&HT_unsat[0][0], &HT_unsat[0][0], fu, 9); //HT times fd/fdSOM
garray_multiply(&H_unsat[0][0], &H_unsat[0][0], fu_Hunsat, 9); //H times fd/fdSOM
garray_multiply(&HT_unsat[0][0], &HT_unsat[0][0], fu_Hunsat, 9); //HT times fd/fdSOM
}
 
double Hypoplasti_unsat_expansive_thermal::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) {
960,7 → 981,7
double dSrM_dse=rlambda_for_se*lambdap0*SrM/se;
double dse_deM=-sairentry0*eM0/(eM*eM)*(aTparam+bTparam*Temper)/(aTparam+bTparam*Trparam);
double dse_dT=sairentry0*eM0*bTparam/(eM*(aTparam+bTparam*Trparam));
 
double dSrM=dSrM_ds*dsuction+dSrM_dse*(dse_deM*deM+dse_dT*dTemper);
 
SrM_new=SrM+dSrM;
970,8 → 991,8
 
}
 
double Hypoplasti_unsat_expansive_thermal_original::give_rlambda(double suction, double a_scan, double dsuction, double sewM, double SrM, double& rlambda_for_ascan, double& rlambda_for_se) {
double Hypoplasti_unsat_expansive_thermal_2017::give_rlambda(double suction, double a_scan, double dsuction, double sewM, double SrM, double& rlambda_for_ascan, double& rlambda_for_se) {
 
double rlambda=0;
if(a_scan<1-1.0e-10 && a_scan>1.0e-10 && aer<1)
rlambda=rlambdascan;
985,23 → 1006,23
return rlambda;
}
 
double Hypoplasti_unsat_expansive_thermal::give_rlambda(double suction, double a_scan, double dsuction, double sewM, double SrM, double& rlambda_for_ascan, double& rlambda_for_se) {
double Hypoplasti_unsat_expansive_thermal_2022::give_rlambda(double suction, double a_scan, double dsuction, double sewM, double SrM, double& rlambda_for_ascan, double& rlambda_for_se) {
 
double scanpower=3;
double SrMlimit=0.75;
double SrMmax=1.0;
double WRCpower=1.1;
double Sepower=3;
double Sepower=3.0;
 
double fact=a_scan; //wetting within main curves
if(dsuction>0) fact=1-a_scan; //drying within main curves
 
double rlambda=1;
rlambda_for_se=1;
if(fact<1.e-10) fact=0;
 
if(aer<1) rlambda=gscalar_power(fact, scanpower);
 
if(SrM>1) SrM=1;
if(suction>=sewM) {//drying from 0
rlambda=0;
1008,24 → 1029,57
rlambda_for_se=0;
}
rlambda_for_ascan=rlambda;
 
//wetting to 0, rlambda_for_ascan remains 1 here
if(dsuction>0 && SrM>SrMlimit) {
rlambda=gscalar_power((SrMmax-SrM)/(1-SrMlimit), WRCpower);
rlambda_for_se=gscalar_power((SrMmax-SrM)/(1-SrMlimit), Sepower);
rlambda=gscalar_power((SrMmax-SrM)/(SrMmax-SrMlimit), WRCpower);
rlambda_for_se=gscalar_power((SrMmax-SrM)/(SrMmax-SrMlimit), Sepower);
}
return rlambda;
 
return rlambda;
}
 
void Hypoplasti_unsat_expansive_thermal::direct_stiffness_matrix(double strain_gen[], double stress_gen[], double qstatev[],
double dstrain_gen[], double dtime, double *DDtan_gen, double parms[], int kinc) {
double Hypoplasti_unsat_expansive_thermal::give_rlambda(double suction, double a_scan, double dsuction, double sewM, double SrM, double& rlambda_for_ascan, double& rlambda_for_se) {
 
double scanpower=3;
double SrMlimit=0.2; //was SrMlimit=0.75;
double SrMmax=1.0;
double WRCpower=1.0; //was WRCpower=1.1;
double Sepower=3.0;
 
double fact=a_scan; //wetting within main curves
if(dsuction>0) fact=1-a_scan; //drying within main curves
 
double rlambda=1;
rlambda_for_se=1;
if(fact<1.e-10) fact=0;
 
if(aer<1) rlambda=gscalar_power(fact, scanpower);
 
if(SrM>1) SrM=1;
if(suction>=sewM) {//drying from 0
rlambda=0;
rlambda_for_se=0;
}
rlambda_for_ascan=rlambda;
 
//wetting to 0, rlambda_for_ascan remains 1 here
if(dsuction>0 && SrM>SrMlimit) {
rlambda=gscalar_power((SrMmax-SrM)/(SrMmax-SrMlimit), WRCpower);
rlambda_for_se=gscalar_power((SrMmax-SrM)/(SrMmax-SrMlimit), Sepower);
}
 
return rlambda;
}
 
void Hypoplasti_unsat_expansive_thermal::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 signet[9];
double Sr=0;
double othervar[5]={0,0,0,0,0};
 
convert_from_general(stress_gen, signet, othervar, ngstress-6, 1);
convert_from_general(stress_gen, signet, othervar, ngstress-6, 1);
Sr=othervar[0];
 
double ddum9[9];
1032,11 → 1086,19
convert_from_general(strain_gen, ddum9, othervar, ngstrain-6, 2);
double suction=othervar[0];
double Temper=othervar[1];
 
double pertinc_all[c_ngstrain];
garray_set(pertinc_all, 0, ngstrain);
for(int i=0; i<6; i++) pertinc_all[i]=1.e-6;
pertinc_all[6]=-sairentry0/100; //ds
pertinc_all[7]=0.1; //dT
if(flag!=3) { //segmentation fault without this
for(int i=0; i<ngstrain; i++) {
if(dstrain_gen[i]<0) pertinc_all[i]=-gscalar_dabs(pertinc_all[i]);
else pertinc_all[i]=gscalar_dabs(pertinc_all[i]);
}
}
 
garray_set(DDtan_gen, 0, c_ngstrain*c_ngstress);
 
1083,9 → 1145,8
garray_set(&hypo_N[0][0],0,9);
garray_set(&H_unsat[0][0],0,9);
garray_set(&HT_unsat[0][0],0,9);
double fm=0;
double fu=0;
give_LNH(signet, suction, Temper, qstatev, hypo_L, hypo_N, H_unsat, HT_unsat, fm, fu);
give_LNH(signet, suction, Temper, qstatev, hypo_L, hypo_N, H_unsat, HT_unsat, false, fu);
garray_move(&hypo_L[0][0][0][0], &DDtan[0][0][0][0], 81);
convert4th_to_abaqus(DDtan, DDtan_abq);
 
1097,18 → 1158,18
}
}
 
void Hypoplasti_unsat_expansive_thermal::initialise_variables(double strain_gen[], double stress_gen[], double qstatev[],
void Hypoplasti_unsat_expansive_thermal::initialise_variables(double strain_gen[], double stress_gen[], double qstatev[],
double dstrain_gen[], double dtime, double parms[], int kinc) {
 
double signet[9];
garray_set(signet, 0.0, 9);
double othervar[5]={0,0,0,0,0};
convert_from_general(stress_gen, signet, othervar, ngstress-6, 1);
convert_from_general(stress_gen, signet, othervar, ngstress-6, 1);
double Sr=othervar[0];
 
double dqstatev[c_nstatev];
garray_set(dqstatev, 0.0, nstatev);
 
double zeroinctens[9]={0,0,0,0,0,0,0,0,0};
double ddum9[9]={0,0,0,0,0,0,0,0,0};
double zeroincscal=0;
1127,7 → 1188,7
 
if(qstatev[5]<0) {
cout<<"Initial value of eM is lower than 0 and this is not allowed, please re-initialise, eM="<<qstatev[5]<<endl;
exit(0);
exit(1);
}
 
double ddum3333[3][3][3][3];
1135,7 → 1196,7
double ddum=0;
garray_set(&ddum3333[0][0][0][0],0,81);
garray_set(&ddum33[0][0],0,9);
give_LNH(signet, suction, Temper, qstatev, ddum3333, ddum33, ddum33, ddum33, ddum, fu);
give_LNH(signet, suction, Temper, qstatev, ddum3333, ddum33, ddum33, ddum33, false, fu);
if(fu>1) {
cout<<"Warning, void ratio and stress state were initialised outside SBS, fu="<<fu<<endl;
}
1173,22 → 1234,29
aer=parms[20];
lambdap0=parms[21];
pt=parms[22];
 
alphaG=1;
alphanu=alphaG;
alphaE=gscalar_power(alphaG,1./0.8);
 
rlambdascan=0.1;
//end define parameters
//end define parameters
}
 
long General_model::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 errorrkf = false;
//if not specified, initialise rkf_parms & rkf_statev to default values
if(rkf_parms==NULL) {
double rkf_parms_default[nrkf_parms] = {1.0e-5,1.0e-17,1,1.0e-3,7};
 
//Order of parameters in the array rkf_parms
//rkf_parms[0] = err_sig, default 1.e-3
//rkf_parms[1] = h_min, default 1.e-17
//rkf_parms[2] = ni, default 1000
//rkf_parms[3] = sv_rkf_zero, default 1.e-3
//rkf_parms[4] = rkt, default 4
double rkf_parms_default[nrkf_parms] = {1.0e-3,1.0e-17,1000,1.0e-3,4}; //{1.0e-5,1.0e-17,1,1.0e-3,7};
rkf_parms=&rkf_parms_default[0];
}
if(rkf_statev==NULL) {
1195,42 → 1263,42
double rkf_statev_default[nrkf_statev] = {0,0,1,0.1};
rkf_statev=&rkf_statev_default[0];
}
int rkt = rkf_parms[4]<10 ? rkf_parms[4]:(rkf_parms[4]-10);
 
int rkt = rkf_parms[4];
switch (rkt){
case 1: { //case rkt=1 forward Euler
case 1: { //case rkt=1 forward Euler
double signet[9];
garray_set(signet, 0.0, 9);
double othervar[5]={0,0,0,0,0};
convert_from_general(stress_gen, signet, othervar, ngstress-6, 1);
double Sr=othervar[0];
 
double ddum9[9];
convert_from_general(strain_gen, ddum9, othervar, ngstrain-6, 2);
double suction=othervar[0];
double Temper=othervar[1];
 
double dstress_gen[max_ngstress];
double dqstatev[max_nstatev];
garray_set(dstress_gen, 0.0, ngstress);
garray_set(dqstatev, 0.0, nstatev);
 
double gmod_deps[9];
garray_set(gmod_deps, 0, 9);
garray_set(gmod_deps, 0, 9);
convert_from_general(dstrain_gen, gmod_deps, othervar, ngstrain-6, 2);
double dsuction=othervar[0];
double dTemper=othervar[1];
 
double dsignet[9];
garray_set(dsignet, 0, 9);
double Sr_new=0;
 
errorrkf = calc_fsigq(signet, suction, Temper, qstatev, gmod_deps, dsuction, dTemper, dtime, dsignet, Sr_new, dqstatev, kinc);
 
othervar[0]=Sr_new-Sr;
garray_set(dstress_gen,0,ngstress);
convert_to_general(dstress_gen, dsignet, othervar,(ngstress-6),1);
 
//Update external variables
for (int i=0; i<ngstress; i++) stress_gen[i] += dstress_gen[i];
for (int i=0; i<nstatev; i++) qstatev[i] += dqstatev[i];
1363,7 → 1431,7
double General_model::gscalar_power( double a, double b ) {
/* if(b==0.5 && a<0) {
cout<<"Attempting to calculate square root of a negative number";
exit(0);
exit(1);
}
double result=0.;
if ( b==0. )
1379,7 → 1447,7
return ret;
}
else if (a>=0 && !isnan(a) && !isnan(b)) return 0;
else
else
{
if(debug) cout<<"Error in calculating power "<<a<<"^"<<b<<endl;
return(0.0);
1394,26 → 1462,26
return tmp;
}
void General_model::garray_add( double a[], double b[], double c[], long int n ) {
register long int i=0;
long int i=0;
for ( i=0; i<n; i++ ) c[i] = a[i] + b[i];
}
double General_model::garray_inproduct( double a[], double b[], long int n ) {
register long int i=0;
long int i=0;
double result=0.;
for ( i=0; i<n; i++ ) result += a[i]*b[i];
return result;
}
void General_model::garray_move( double from[], double to[], long int n ) {
// register long int i=0;
// long int i=0;
// for ( i=0; i<n; i++ ) to[i] = from[i];
memcpy(to, from, sizeof(*from)*n);
}
void General_model::garray_multiply( double a[], double b[], double c, long int n ) {
register long int i=0;
long int i=0;
for ( i=0; i<n; i++ ) b[i] = c * a[i];
}
void General_model::garray_set( double *ptr, double value, long int n ) { //@GS initialises the array to "value" (e.g. to zero)
// register long int i=0;
// long int i=0;
// for ( i=0; i<n; i++ ) *(ptr+i) = value;
if (value == 0.0)
memset(ptr, 0, sizeof(*ptr)*n);
1443,13 → 1511,13
}
else {
cout<<"n must be 1-3"<<endl;
exit(0);
exit(1);
}
}
return result;
}
void General_model::gmatrix_ab( double *a, double *b, double *c, long int n, long int m, long int k ) { // c[n][k] = a[n][m] * b[m][k]
register long int i=0, j=0, l=0;
long int i=0, j=0, l=0;
 
for ( i=0; i<n; i++ ) {
for ( j=0; j<k; j++ ) {
1462,7 → 1530,7
}
}
void General_model::gmatrix_a4b( double a[3][3][3][3], double b[], double c[] ) {
register long int i=0, j=0, k=0, l=0;
long int i=0, j=0, k=0, l=0;
 
for ( i=0; i<3; i++ ) {
for ( j=0; j<3; j++ ) {
1484,10 → 1552,9
return round(value * factor) / factor;
}
long General_model::test_math_err() {
if ((errno == EDOM) || (errno == ERANGE))
return 1;
 
return 0;
if (errno == EDOM) return 1;
else if(errno == ERANGE) return 2;
else return 0;
}
 
//@GS Functions adapted from SIFEL
1529,7 → 1596,8
long k, j;
long ni = rkf_parms[2];
long stopk = 0;
long ngcomp = max_ngstress + max_nstatev;
long max_ngcomp = max_ngstress + max_nstatev;
long ngcomp = ngstress + nstatev;
double k1[max_ngstress + max_nstatev], k2[max_ngstress + max_nstatev], y1[max_ngstress + max_nstatev], y2[max_ngstress + max_nstatev], y_hat[max_ngstress + max_nstatev], y_til[max_ngstress + max_nstatev], y_err[max_ngstress + max_nstatev];
double strain_gen_aux[max_ngstrain], dstrain_gen_aux[max_ngstrain];
long herr;
1537,6 → 1605,20
double g_suction=0, g_dsuction=0, g_Temper=0, g_dTemper=0, g_Sr=0, g_Sr_new=0;
double g_signet[9], g_deps[9], g_ddum9[9], g_othervar[5], g_dsignet[9], g_dSr[1];
long error=0;
//initialising variables
for (j=0; j<max_ngcomp; j++) {
k1[j]=0;
k2[j]=0;
y1[j]=0;
y2[j]=0;
y_hat[j]=0;
y_til[j]=0;
y_err[j]=0;
if(j<max_ngstrain) {
strain_gen_aux[j]=0;
dstrain_gen_aux[j]=0;
}
}
//}
//{ preparation
// set initial substep length
1561,7 → 1643,7
//{ first call to calc_fsigq
// calculate Forward Euler
convert_from_general (y1, g_signet, g_othervar, (ngstress-6), 1);
 
g_Sr = g_othervar[0];
convert_from_general (strain_gen_aux, g_ddum9, g_othervar, (ngstrain-6), 2);
g_suction=g_othervar[0];
1588,7 → 1670,7
//{ second call to calc_fsigq
// calculate Forward Euler for half step
convert_from_general (y1, g_signet, g_othervar, (ngstress-6), 1);
 
g_Sr = g_othervar[0];
convert_from_general (strain_gen_aux, g_ddum9, g_othervar, (ngstrain-6), 2);
g_suction=g_othervar[0];
1614,7 → 1696,7
//}
//{ third call to calc_fsigq
convert_from_general (y2, g_signet, g_othervar, (ngstress-6), 1);
 
g_Sr = g_othervar[0];
convert_from_general (strain_gen_aux, g_ddum9, g_othervar, (ngstrain-6), 2);
g_suction=g_othervar[0];
1745,10 → 1827,11
double dtmin = rkf_parms[1];
double idtsub = dtsub;
double sv_rkf_zero = rkf_parms[3]; //needed
long k;
long j, k;
long ni = rkf_parms[2];
long stopk = 0;
long ngcomp = max_ngstress + max_nstatev;
long max_ngcomp = max_ngstress + max_nstatev;
long ngcomp = ngstress + nstatev;
double k1[max_ngstress + max_nstatev], y1[max_ngstress + max_nstatev];
double strain_gen_aux[max_ngstrain], dstrain_gen_aux[max_ngstrain];
// additional variables (for calc_fsigq)
1755,6 → 1838,15
double g_suction=0, g_dsuction=0, g_Temper=0, g_dTemper=0, g_Sr=0, g_Sr_new=0;
double g_signet[9], g_deps[9], g_ddum9[9], g_othervar[5], g_dsignet[9], g_dSr[1];
long error=0;
//initialising variables
for (j=0; j<max_ngcomp; j++) {
k1[j]=0;
y1[j]=0;
if(j<max_ngstrain) {
strain_gen_aux[j]=0;
dstrain_gen_aux[j]=0;
}
}
//}
//{ preparation
// set initial substep length
1772,7 → 1864,7
// dstrain_gen_aux = h*dstrain_gen;
garray_addmult(NULL, dstrain_gen, h, dstrain_gen_aux, ngstrain);
convert_from_general (y1, g_signet, g_othervar, (ngstress-6), 1);
 
g_Sr = g_othervar[0];
convert_from_general (strain_gen_aux, g_ddum9, g_othervar, (ngstrain-6), 2);
g_suction=g_othervar[0];
1789,7 → 1881,7
 
if (check_math_error() || errorfsigq) return 1;
garray_add(y1, k1, y1, ngcomp);
 
neval += 3;
rkf_statev[0] = neval;
// substep is accepted, !FE solution taken
1855,7 → 1947,8
long k, j;
long ni = rkf_parms[2];
long stopk = 0;
long ngcomp = max_ngstress + max_nstatev;
long max_ngcomp = max_ngstress + max_nstatev;
long ngcomp = ngstress + nstatev;
long stvcomp;
double k1[max_ngstress+ max_nstatev], k2[max_ngstress + max_nstatev], k3[max_ngstress + max_nstatev], y1[max_ngstress + max_nstatev], y2[max_ngstress + max_nstatev], y3[max_ngstress + max_nstatev], y_hat[max_ngstress + max_nstatev], y_til[max_ngstress + max_nstatev], y_err[max_ngstress + max_nstatev];
double strain_gen_aux[max_ngstrain], dstrain_gen_aux[max_ngstrain];
1864,6 → 1957,22
double g_suction=0, g_dsuction=0, g_Temper=0, g_dTemper=0, g_Sr=0, g_Sr_new=0;
double g_signet[9], g_deps[9], g_ddum9[9], g_othervar[5], g_dsignet[9], g_dSr[1];
long error=0;
//initialising variables
for (j=0; j<max_ngcomp; j++) {
k1[j]=0;
k2[j]=0;
k3[j]=0;
y1[j]=0;
y2[j]=0;
y3[j]=0;
y_hat[j]=0;
y_til[j]=0;
y_err[j]=0;
if(j<max_ngstrain) {
strain_gen_aux[j]=0;
dstrain_gen_aux[j]=0;
}
}
//}
//{ preparation
// set initial substep length
1889,7 → 1998,7
//{ first call to calc_fsigq
// calculate initial vector of coefficients for the first stage of Runge-Kutta method
convert_from_general (y1, g_signet, g_othervar, (ngstress-6), 1);
 
g_Sr = g_othervar[0];
convert_from_general (strain_gen_aux, g_ddum9, g_othervar, (ngstrain-6), 2);
g_suction=g_othervar[0];
1929,7 → 2038,7
//{ second call to calc_fsigq
// calculate coefficients for the second stage of Runge-Kutta method
convert_from_general (y2, g_signet, g_othervar, (ngstress-6), 1);
 
g_Sr = g_othervar[0];
convert_from_general (strain_gen_aux, g_ddum9, g_othervar, (ngstrain-6), 2);
g_suction=g_othervar[0];
1962,7 → 2071,7
//{ third call to calc_fsigq
// calculate coefficients for the third stage of Runge-Kutta method
convert_from_general (y3, g_signet, g_othervar, (ngstress-6), 1);
 
g_Sr = g_othervar[0];
convert_from_general (strain_gen_aux, g_ddum9, g_othervar, (ngstrain-6), 2);
g_suction=g_othervar[0];
2127,7 → 2236,8
long k, j;
long ni = rkf_parms[2];
long stopk = 0;
long ngcomp = max_ngstress + max_nstatev;
long max_ngcomp = max_ngstress + max_nstatev;
long ngcomp = ngstress + nstatev;
long stvcomp;
double k1[max_ngstress + max_nstatev], k2[max_ngstress + max_nstatev], k3[max_ngstress + max_nstatev], k4[max_ngstress + max_nstatev];
double y1[max_ngstress + max_nstatev], y2[max_ngstress + max_nstatev], y3[max_ngstress + max_nstatev], y_hat[max_ngstress + max_nstatev], y_til[max_ngstress + max_nstatev], y_err[max_ngstress + max_nstatev];
2137,6 → 2247,23
double g_suction=0, g_dsuction=0, g_Temper=0, g_dTemper=0, g_Sr=0, g_Sr_new=0;
double g_signet[9], g_deps[9], g_ddum9[9], g_othervar[5], g_dsignet[9], g_dSr[1];
long error=0;
//initialising variables
for (j=0; j<max_ngcomp; j++) {
k1[j]=0;
k2[j]=0;
k3[j]=0;
k4[j]=0;
y1[j]=0;
y2[j]=0;
y3[j]=0;
y_hat[j]=0;
y_til[j]=0;
y_err[j]=0;
if(j<max_ngstrain) {
strain_gen_aux[j]=0;
dstrain_gen_aux[j]=0;
}
}
//}
//{ preparation
// set initial substep length
2216,7 → 2343,7
//{ second call to calc_fsigq
// calculate coefficients for the second stage of Runge-Kutta method
errorfsigq += correct_statev_values(strain_gen_aux, y2, y2+ngstress, dstrain_gen_aux, 4);
convert_from_general (y2, g_signet, g_othervar, (ngstress-6), 1);
convert_from_general (y2, g_signet, g_othervar, (ngstress-6), 1);
g_Sr = g_othervar[0];
convert_from_general (strain_gen_aux, g_ddum9, g_othervar, (ngstrain-6), 2);
g_suction=g_othervar[0];
2369,7 → 2496,7
// select optimal RK substep length
h = min2(4.0*h, h_opt);
if (h > 1.0) h = 1.0;
if(err_sig >= 1) h = 1/err_sig; //Constant number of substeps
if(err_sig >= 1) h = 1/err_sig; //Constant number of substeps
// store the last attained RK substep length to be the initial substep length in the next RKF method call
dtsub = h;
rkf_statev[3] = dtsub;
2458,7 → 2585,8
long k, j;
long ni = rkf_parms[2];
long stopk = 0;
long ngcomp = max_ngstress + max_nstatev;
long max_ngcomp = max_ngstress + max_nstatev;
long ngcomp = ngstress + nstatev;
long stvcomp;
double k1[max_ngstress + max_nstatev], k2[max_ngstress + max_nstatev], k3[max_ngstress + max_nstatev], k4[max_ngstress + max_nstatev], k5[max_ngstress + max_nstatev];
double y1[max_ngstress + max_nstatev], y2[max_ngstress + max_nstatev], y3[max_ngstress + max_nstatev], y4[max_ngstress + max_nstatev], y_hat[max_ngstress + max_nstatev], y_til[max_ngstress + max_nstatev], y_err[max_ngstress + max_nstatev];
2468,6 → 2596,24
double g_suction=0, g_dsuction=0, g_Temper=0, g_dTemper=0, g_Sr=0, g_Sr_new=0;
double g_signet[9], g_deps[9], g_ddum9[9], g_othervar[5], g_dsignet[9], g_dSr[1];
long error=0;
//initialising variables
for (j=0; j<max_ngcomp; j++) {
k1[j]=0;
k2[j]=0;
k3[j]=0;
k4[j]=0;
y1[j]=0;
y2[j]=0;
y3[j]=0;
y4[j]=0;
y_hat[j]=0;
y_til[j]=0;
y_err[j]=0;
if(j<max_ngstrain) {
strain_gen_aux[j]=0;
dstrain_gen_aux[j]=0;
}
}
//}
//{ preparation
// set initial substep length
2492,7 → 2638,7
//{ first call to calc_fsigq
// calculate initial vector of coefficients for the first stage of Runge-Kutta method
convert_from_general (y1, g_signet, g_othervar, (ngstress-6), 1);
 
g_Sr = g_othervar[0];
convert_from_general (strain_gen_aux, g_ddum9, g_othervar, (ngstrain-6), 2);
g_suction=g_othervar[0];
2535,7 → 2681,7
//{ second call to calc_fsigq
// calculate coefficients for the second stage of Runge-Kutta method
convert_from_general (y2, g_signet, g_othervar, (ngstress-6), 1);
 
g_Sr = g_othervar[0];
convert_from_general (strain_gen_aux, g_ddum9, g_othervar, (ngstrain-6), 2);
g_suction=g_othervar[0];
2568,7 → 2714,7
//{ third call to calc_fsigq
// calculate coefficients for the third stage of Runge-Kutta method
convert_from_general (y3, g_signet, g_othervar, (ngstress-6), 1);
 
g_Sr = g_othervar[0];
convert_from_general (strain_gen_aux, g_ddum9, g_othervar, (ngstrain-6), 2);
g_suction=g_othervar[0];
2601,7 → 2747,7
//{ fourth call to calc_fsigq
// calculate coefficients for the fourth stage of Runge-Kutta method
convert_from_general (y4, g_signet, g_othervar, (ngstress-6), 1);
 
g_Sr = g_othervar[0];
convert_from_general (strain_gen_aux, g_ddum9, g_othervar, (ngstrain-6), 2);
g_suction=g_othervar[0];
2635,7 → 2781,7
//{ fifth call to calc_fsigq
// calculate coefficients for the fifth stage of Runge-Kutta method
convert_from_general (y_til, g_signet, g_othervar, (ngstress-6), 1);
 
g_Sr = g_othervar[0];
convert_from_general (strain_gen_aux, g_ddum9, g_othervar, (ngstrain-6), 2);
g_suction=g_othervar[0];
2792,7 → 2938,8
long k, j;
long ni = rkf_parms[2];
long stopk = 0;
long ngcomp = max_ngstress + max_nstatev;
long max_ngcomp = max_ngstress + max_nstatev;
long ngcomp = ngstress + nstatev;
long stvcomp;
double k1[max_ngstress + max_nstatev], k2[max_ngstress + max_nstatev], k3[max_ngstress + max_nstatev], k4[max_ngstress + max_nstatev], k5[max_ngstress + max_nstatev], k6[max_ngstress + max_nstatev];
double y1[max_ngstress + max_nstatev], y2[max_ngstress + max_nstatev], y3[max_ngstress + max_nstatev], y4[max_ngstress + max_nstatev], y5[max_ngstress + max_nstatev], y6[max_ngstress + max_nstatev];
2803,6 → 2950,29
double g_suction=0, g_dsuction=0, g_Temper=0, g_dTemper=0, g_Sr=0, g_Sr_new=0;
double g_signet[9], g_deps[9], g_ddum9[9], g_othervar[5], g_dsignet[9], g_dSr[1];
long error=0;
//initialising variables
for (j=0; j<max_ngcomp; j++) {
k1[j]=0;
k2[j]=0;
k3[j]=0;
k4[j]=0;
k5[j]=0;
k6[j]=0;
y1[j]=0;
y2[j]=0;
y3[j]=0;
y4[j]=0;
y5[j]=0;
y6[j]=0;
y_hat[j]=0;
y_til[j]=0;
y_err[j]=0;
if(j<max_ngstrain) {
strain_gen_aux[j]=0;
dstrain_gen_aux[j]=0;
}
}
 
//}
//{ preparation
// set initial substep length
2828,7 → 2998,7
//{ first call to calc_fsigq
// calculate initial vector of coefficients for the first stage of Runge-Kutta method
convert_from_general (y1, g_signet, g_othervar, (ngstress-6), 1);
 
g_Sr = g_othervar[0];
convert_from_general (strain_gen_aux, g_ddum9, g_othervar, (ngstrain-6), 2);
g_suction=g_othervar[0];
2871,7 → 3041,7
//{ second call to calc_fsigq
// calculate coefficients for the second stage of Runge-Kutta method
convert_from_general (y2, g_signet, g_othervar, (ngstress-6), 1);
 
g_Sr = g_othervar[0];
convert_from_general (strain_gen_aux, g_ddum9, g_othervar, (ngstrain-6), 2);
g_suction=g_othervar[0];
2904,7 → 3074,7
//{ third call to calc_fsigq
// calculate coefficients for the third stage of Runge-Kutta method
convert_from_general (y3, g_signet, g_othervar, (ngstress-6), 1);
 
g_Sr = g_othervar[0];
convert_from_general (strain_gen_aux, g_ddum9, g_othervar, (ngstrain-6), 2);
g_suction=g_othervar[0];
2937,7 → 3107,7
//{ fourth call to calc_fsigq
// calculate coefficients for the fourth stage of Runge-Kutta method
convert_from_general (y4, g_signet, g_othervar, (ngstress-6), 1);
 
g_Sr = g_othervar[0];
convert_from_general (strain_gen_aux, g_ddum9, g_othervar, (ngstrain-6), 2);
g_suction=g_othervar[0];
2970,7 → 3140,7
//{ fifth call to calc_fsigq
// calculate coefficients for the fifth stage of Runge-Kutta method
convert_from_general (y5, g_signet, g_othervar, (ngstress-6), 1);
 
g_Sr = g_othervar[0];
convert_from_general (strain_gen_aux, g_ddum9, g_othervar, (ngstrain-6), 2);
g_suction=g_othervar[0];
3003,7 → 3173,7
//{ sixth call to calc_fsigq
// calculate coefficients for the sixth stage of Runge-Kutta method
convert_from_general (y6, g_signet, g_othervar, (ngstress-6), 1);
 
g_Sr = g_othervar[0];
convert_from_general (strain_gen_aux, g_ddum9, g_othervar, (ngstrain-6), 2);
g_suction=g_othervar[0];
3177,7 → 3347,7
}
 
void General_model::garray_subtract (double a[], double b[], double c[], long int n) {
register long int i=0;
long int i=0;
for (i=0; i<n; i++) c[i] = a[i] - b[i];
}
 
3204,7 → 3374,7
return sqrt(s);
}
 
long Hypoplasti_unsat_expansive_thermal::correct_statev_values(double strain_gen[], double stress_gen[],
long Hypoplasti_unsat_expansive_thermal::correct_statev_values(double strain_gen[], double stress_gen[],
double qstatev[], double dstrain_gen[], int call) {
 
//BEGIN tension cutoff
3213,18 → 3383,18
convert_from_general (strain_gen, ddum9, othervar, ngstrain-6, 2);
double suction=othervar[0];
double Temper=othervar[1];
 
double signet[9]={0,0,0,0,0,0,0,0,0};
convert_from_general (stress_gen, signet, othervar, ngstress-6, 1);
 
double sigef[9]={0,0,0,0,0,0,0,0,0};
double SrM=qstatev[6];
make_sig_unsat(signet, suction, SrM, sigef, suction);
double chixsuction=sigef[0]-signet[0];
 
double signet_corrected[9]={0,0,0,0,0,0,0,0,0};
garray_move(signet, signet_corrected, 9);
 
bool printstat=false;
if(sigef[0]>0) {
printstat=true;
3243,12 → 3413,12
}
long errormath = 0;
if(debug & printstat & call != 4) {
 
if (call == 3) errormath++;
cout<<"Correcting signet, call "<<call<<", signet[0]="<<signet[0]<<", signet[4]="<<signet[4]<<", signet[8]="<<signet[8]<<", sigef[0]="<<sigef[0]<<", sigef[4]="<<sigef[4]<<", sigef[8]="<<sigef[8]<<", suction="<<suction<<", dsuction="<<dstrain_gen[6]<<", SrM="<<SrM<<endl;
cout<<"Correcting signet, call "<<call<<", signet[0]="<<signet[0]<<", signet[4]="<<signet[4]<<", signet[8]="<<signet[8]<<", sigef[0]="<<sigef[0]<<", sigef[4]="<<sigef[4]<<", sigef[8]="<<sigef[8]<<", suction="<<suction<<", dsuction="<<dstrain_gen[6]<<", SrM="<<SrM<<endl;
garray_move(signet_corrected, signet, 9);
}
 
convert_to_general(stress_gen, signet, othervar, ngstress-6, 1);
//END tension cutoff
 
3256,7 → 3426,7
for(int i=0; i<ngstrain; i++) {if(isnan( dstrain_gen[i] )) errormath++;}
for(int i=0; i<ngstress; i++) {if(isnan( stress_gen[i] )) errormath++;}
for(int i=0; i<nstatev; i++) {if(isnan( qstatev[i] )) errormath++;}
 
return(errormath);
}
 
3264,14 → 3434,14
//Check that dSr/ds is not negative, which is not physical
if(strain_gen[6]>sairentry0 && DDtan_gen[54]<0) DDtan_gen[54]=0;
//check NAN error of stiffness matrix
long errormath = 0;
long errormath = 0;
for(int j=0; j<ngstress*ngstrain; j++) if(isnan(DDtan_gen[j])) errormath += 1;
return (errormath);
};
 
bool General_model::check_math_error() {
bool matherror=test_math_err();
long General_model::check_math_error() {
long matherror=test_math_err();
errno = 0;
if(matherror) return(true);
else return(false);
if(matherror) return(matherror);
else return(0);
}
/trunk/SIFEL/MEFEL/SRC/generalmod.h
41,7 → 41,7
struct General_model {
 
//Numbers of variables
int nparms, nstatev, ngstrain, ngstress;
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;
50,14 → 50,14
static const int nrkf_statev = 4;
bool debug;
 
General_model(int np, int ns, int ngstra, int ngstre) : nparms(np), nstatev(ns), ngstrain(ngstra), ngstress(ngstre) {};
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) {return(0);};
 
virtual bool calc_fsigq(double signet[9], double suction, double Temper, double *qstatev,
double deps[9], double dsuction, double dTemper, double dtime,
double deps[9], double dsuction, double dTemper, double dtime,
double dsignet[9], double &Sr_new, double dqstatev[], int kinc) {return(0);};
 
//Functions for general stress-full 9x9 convention conversion
108,7 → 108,7
 
//Additional routines
long rkf_redstep (double rc, double &h, double hmin);
bool check_math_error();
long check_math_error();
virtual long correct_statev_values(double strain_gen[], double stress_gen[], double qstatev[], double dstrain_gen[], int call) {return(0);};
virtual long correct_DDtan_gen(double strain_gen[], double stress_gen[], double *DDtan_gen) {return(0);};
};
117,12 → 117,14
/****************** 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){};
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
139,6 → 141,9
 
/* 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,
145,7 → 150,7
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 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,
152,15 → 157,14
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);
void calc_depm(double signet[9], double suction, double Temper, double dsuction,
double dTemper, double dsignet[9], double depm[9], double fu);
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], double fm,
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);
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
173,11 → 177,27
/* 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_original : Hypoplasti_unsat_expansive_thermal {
Hypoplasti_unsat_expansive_thermal_original() : Hypoplasti_unsat_expansive_thermal(){};
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
93,6 → 93,7
Neval = 0.0;
Omp_wtime = 0.0;
Elemfrc = NULL;
}
 
 
106,7 → 107,7
Modified by Tomas Koudelka, 08.2021
*/
void delete_glob(void)
{
{
delete Smat; Smat = NULL;
delete Mmat; Mmat = NULL;
delete Dmat; Dmat = NULL;
175,6 → 176,8
delete Pqifc; Pqifc = NULL;
delete Tlatt; Tlatt = NULL;
 
delete [] Elemfrc;
 
Ndofm = Mespr = 0;
}
 
/trunk/SIFEL/MEFEL/SRC/global.h
96,6 → 96,7
class quadrilatkirch;
class dkq;
class tetralattice;
struct vector;
#endif
 
#ifndef EXTERN
328,6 → 329,9
 
EXTERN double Omp_wtime;
 
// array of element internal force vectors Elemfrc[i][j] means j-th component of internal force vector of i-th element
EXTERN vector *Elemfrc;
 
/// function initializes all global variables to null values
void initnull_glob (void);
 
/trunk/SIFEL/MEFEL/SRC/globmat.cpp
24,6 → 24,9
#include <omp.h>
#endif
 
//#define DEBUGELEMFRC
//#include <chrono>
//#include <thread>
 
/**
Function assembles stiffness %matrix.
59,12 → 62,11
if (Mp->lbtype==1)
abort ();
/*
FILE *ma;
ma=fopen ("matice.txt","w");
*/
//FILE *ma;
//ma=fopen ("matice.txt","w");
 
for (i=0;i<Mt->ne;i++){
if (Gtm->leso[i]==1){
// only active elements are assembled
140,10 → 142,12
Smat->localize (lm,cn,i);
}
}
 
/*
Smat->printmat (ma);
fclose (ma);
*/
//Smat->printmat (ma);
//fclose (ma);
/*
fclose (ma);
509,11 → 513,24
vector ifor, aifor;
vector r, mstr;
matrix bd, dd;
ivector h(Ndofm);
long hi = 0;
// 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);
reallocv(ndofe, Elemfrc[i]);
}
}
#endif
 
// number of elements
long ne=Mt->ne;
#ifdef INC_OPENMP
528,16 → 545,18
#pragma omp parallel \
num_threads(Numth),\
private(i, j, ndofe, ndofemn, eid, cn, err, ifor, aifor, r, mstr, bd, dd),\
firstprivate(ncomp)
firstprivate(ncomp), shared(intfor, hi, h)
 
{
#pragma omp for nowait, reduction(+:mstresscomp[:6])
#pragma omp for reduction(+:mstresscomp[:6])
#endif
for (i=0;i<ne;i++){
for (i=0;i<ne;i++) {
if (Gtm->leso[i]==1){
#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
583,8 → 602,8
if (mstress_cn[j]){
#ifdef INC_OPENMP
mstresscomp[j] += ifor[j];
//#pragma omp atomic update
// intfor[mstress_cn[j]-1] += ifor[j];
#pragma omp atomic update
intfor[mstress_cn[j]-1] += ifor[j];
#else
intfor[mstress_cn[j]-1] += ifor[j];
#endif
603,9 → 622,21
}
else{
// the element does not contain hanging node nor homogenization
locglob (intfor,ifor.a,cn.a,ndofe);
#ifdef INC_OPENMP
#pragma omp critical
{
h[hi] = hi;
hi++;
locglob (intfor,ifor.a,cn.a,ndofe);
}
#else
locglob (intfor,ifor.a,cn.a,ndofe);
#endif
}
}
#ifdef DEBUGELEMFRC
copyv(ifor, Elemfrc[i]);
#endif
}
#ifdef INC_OPENMP
}
624,6 → 655,30
druntime = (clock() - druntime)/(double)CLOCKS_PER_SEC;
Omp_wtime += druntime;
#endif
#ifdef DEBUGELEMFRC
fprintf(Out, "\nistep=%ld, jstep=%ld\n", Mp->istep, Mp->jstep);
// nullv (intfor,Ndofm);
for(i=0; i<Mt->ne; i++){
/* ndofe=Mt->give_ndofe(i);
ndofemn = Gtm->give_ndofe (i);
reallocv (RSTCKIVEC(ndofemn,cn));
Mt->give_code_numbers (i,cn.a);
locglob (intfor,Elemfrc[i].a, cn.a, ndofe);*/
fprintf(Out, "eid=%4ld\n", i+1);
for(j=0; j<Elemfrc[i].n; j++)
fprintf(Out, " % .15le", Elemfrc[i][j]);
fprintf(Out, "\n");
}
fprintf(Out, "\nElement order: istep=%ld, jstep=%ld\n", Mp->istep, Mp->jstep);
for(i=0; i<Mt->ne; i++)
fprintf(Out, "%5ld\n", h(i));
/*
fprintf(Out, "\nInternal force vector: istep=%ld, jstep=%ld\n", Mp->istep, Mp->jstep);
for(i=0; i<Ndofm; i++){
fprintf(Out, " % .15le\n", intfor[i]);
}*/
fflush(Out);
#endif
}
 
 
1039,7 → 1094,7
for(i=0; i<Mm->tnip; i++)
{
u = Mm->givenonmechq(pore_pressure, i);
u = Mm->givenonmechq(eff_pore_pressure, i);
reallocv(RSTCKVEC(Mm->ip[i].ncompstr, sig));
sigt[0] = sigt[1] = sigt[2] = u;
give_red_vector(sigt,sig,Mm->ip[i].ssst);
1381,7 → 1436,110
}
 
 
/**
The function extracts prescribed displacements on one element.
@param lcid - number of load case
@param eid - element id
@param r - array of prescribed displacements, it is output parameter
@return The function returns extracted prescribed displacements in the array r from previous time step. Only for time-dependent problems.
 
20/04/2023 by TKr according to JK
*/
void elprevprdispl (long lcid,long eid,double *r)
{
long i,ii,ndofe,ndofemn;
double oldtime;
ivector cn,nod,ncn;
vector rr;
// the number of DOFs on element
// this number is equal to the number of DOFs without hanging nodes
ndofe = Mt->give_ndofe (eid);
// 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);
if (ndofe != ndofemn){
// there are hanging nodes on element
reallocv (RSTCKIVEC(ndofemn,cn));
reallocv (RSTCKVEC(ndofemn,rr));
ndofe=ndofemn;
}
else{
// there are no hanging nodes on element
reallocv (RSTCKIVEC(ndofe,cn));
reallocv (RSTCKVEC(ndofe,rr));
}
// code numbers on element
Mt->give_code_numbers (eid,cn.a);
switch (Mp->tprob){
case forced_dynamics:
case mech_timedependent_prob:{
oldtime = Mp->time-Mp->timecon.backwarddt;
// lcid must be equal to zero
for (i=0;i<ndofe;i++){
ii=cn[i];
if (ii<0)
rr[i]=Mb->dlc[lcid].get_pd(oldtime, ii);
}
break;
}
case growing_mech_structure:{
oldtime = Mp->time-Mp->timecon.backwarddt;
// lcid must be equal to zero
// loop over the number of DOFs on element (including DOFs in hanging nodes)
for (i=0;i<ndofe;i++){
ii=cn[i];
if (ii<0)
rr[i]=Mb->dlc[lcid].get_pd(oldtime, ii);
}
// initial displacements from previous free state of dof
// in the case that the dof has got support or prescribed displacement actually
// must not be included to the computation of the right hand side because
// the displacements of the neighbour free dofs are already included in the
// displacement vector (r) as well as in the load vector from the previous time step (fp)
break;
}
default:{
print_err("unknown type of problem is required", __FILE__, __LINE__, __func__);
}
}// end of the switch (Mp->tprob)
// the variables ndofe and ndofemn have to be obtained again
// because they are possibly rewritten
//
// the number of DOFs on element
// this number is equal to the number of DOFs without hanging nodes
ndofe = Mt->give_ndofe (eid);
// 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);
if (ndofe != ndofemn){
// there are hanging nodes on element
mxv (Mt->elements[eid].tmat->a,rr.a,r,ndofe,ndofemn);
}
else{
// there are no hanging nodes on element
copyv (rr,r);
}
if (Mp->tprob == growing_mech_structure){
// subtraction of initial displacements
Mt->elements[eid].subtrinitdispl (r,ndofe);
}
}
 
 
 
/**
The function extracts displacements on one node with the index nid and stores them in the %vector r.
 
/trunk/SIFEL/MEFEL/SRC/globmat.h
25,6 → 25,7
 
void eldispl (long lcid,long eid,double *r);
void elprdispl (long lcid,long eid,double *r);
void elprevprdispl (long lcid,long eid,double *r);
 
void noddispl (long lcid,double *r, long nid);
void select_noddispl (long lcid,double *r,long nid);
/trunk/SIFEL/MEFEL/SRC/homogmatm.cpp
0,0 → 1,412
/*
File: homogmatm.cpp
Author: Tomas Krejci, 22/07/2022
Purpose: Calculates properties of homogenized elastic material
*/
#include "mechmat.h"
#include "probdesc.h"
#include "homogmatm.h"
#include "matrix.h"
#include "vector.h"
#include "stochdriver.h"
#include "global.h"
#include "intpoints.h"
#include "vecttens.h"
 
 
 
/**
Constructor initializes data members to zero or default values.
 
Created by TKr,
*/
homogmatm::homogmatm (void)
{
allocm (6,6,dd);
 
hom_mattypem = 0;
hom_mattypem_number = 0;
}
 
 
 
/**
Destructor is defined only for the formal purposes.
 
Created by TKr,
*/
homogmatm::~homogmatm (void)
{
destrm(dd);
}
 
 
 
/**
Function reads material parameters from the opened text file.
@param in - pointer to the opened XFILE
 
@return The function does not return anything.
 
Created by TKr,
*/
void homogmatm::read (XFILE *in)
{
xfscanf (in,"%ld %ld",&hom_mattypem,&hom_mattypem_number);
hom_mattypem_number = hom_mattypem_number-1;
}
 
/**
Function prints material parameters into the opened text file.
@param out - pointer to the opened FILE
 
@return The function does not return anything.
 
Created by TKr
*/
void homogmatm::print (FILE *out)
{
fprintf (out," %ld %ld",hom_mattypem,hom_mattypem_number+1);
}
 
 
/**
Function assembles stiffness %matrix of material.
@param d - stiffness %matrix of material (output)
@param ssst - strain/stress state
 
@return The function returns material stiffness %matrix in the parameter d.
 
Created by TKr
*/
void homogmatm::matstiff (matrix &d,strastrestate ssst)
{
switch (ssst){
case planestress:{
matstiff_plstress (d);
break;
}
case planestrain:{
matstiff_plstrain (d);
break;
}
case axisymm:{
matstiff_axi (d);
break;
}
case spacestress:{
matstiff_spacestr (d);
break;
}
default:{
print_err("unknown number of components of stress tensor is required", __FILE__, __LINE__, __func__);
}
}
}
 
 
/**
Function creates stiffness matrix of the elastic
isotropic material for 2D problems (plane stress).
 
@param d - stiffness matrix of the material
 
@return The function returns material stiffness %matrix in the parameter d.
 
Created by TKr
*/
void homogmatm::matstiff_plstress (matrix &d)
{
d[0][0] = dd[0][0]; d[0][1] = dd[0][1]; d[0][2] = dd[0][2];
d[1][0] = dd[1][0]; d[1][1] = dd[1][1]; d[1][2] = dd[1][2];
d[2][0] = dd[2][0]; d[2][1] = dd[2][1]; d[2][2] = dd[2][2];
}
 
 
 
/**
Function creates stiffness %matrix of the elastic
isotropic material for 2D problems (plane strain).
 
@param d - stiffness %matrix of the material
 
@return The function returns material stiffness %matrix in the parameter d.
 
Created by TKr
*/
void homogmatm::matstiff_plstrain (matrix &d)
{
d[0][0] = dd[0][0]; d[0][1] = dd[0][1]; d[0][2] = dd[0][2];
d[1][0] = dd[1][0]; d[1][1] = dd[1][1]; d[1][2] = dd[1][2];
d[2][0] = dd[2][0]; d[2][1] = dd[2][1]; d[2][2] = dd[2][2];
 
// zde rozmyslet
if (d.m > 3)
{
d[0][3] = dd[0][1]; d[1][3] = dd[1][0];
d[3][0] = dd[1][0]; d[3][1] = dd[1][0]; d[3][3] = dd[1][1];
}
}
 
 
 
/**
Function creates stiffness %matrix of the elastic
isotropic material for 2D axisymmetric problems.
 
@param d - stiffness %matrix of the material
 
@return The function returns material stiffness %matrix in the parameter d.
 
Created by TKr, 19.7.2001
*/
void homogmatm::matstiff_axi (matrix &d)
{
d[0][0] = dd[0][0]; d[0][1] = dd[0][1]; d[0][2] = dd[0][2]; d[0][3] = dd[0][3];
d[1][0] = dd[1][0]; d[1][1] = dd[1][1]; d[1][2] = dd[1][2]; d[1][3] = dd[1][3];
d[2][0] = dd[2][0]; d[2][1] = dd[2][1]; d[2][2] = dd[2][2]; d[2][3] = dd[2][3];
d[3][0] = dd[3][0]; d[3][1] = dd[3][1]; d[3][2] = dd[3][2]; d[3][3] = dd[3][3];
}
 
 
/**
Function creates stiffness %matrix of the elastic
isotropic material for 3D problems.
@param d - stiffness %matrix of the material
 
Created by TKr
*/
void homogmatm::matstiff_spacestr (matrix &d)
{
d[0][0] = dd[0][0]; d[0][1] = dd[0][1]; d[0][2] = dd[0][2]; d[0][3] = dd[0][3]; d[0][4] = dd[0][4]; d[0][5] = dd[0][5];
d[1][0] = dd[1][0]; d[1][1] = dd[1][1]; d[1][2] = dd[1][2]; d[1][3] = dd[1][3]; d[1][4] = dd[1][4]; d[1][5] = dd[1][5];
d[2][0] = dd[2][0]; d[2][1] = dd[2][1]; d[2][2] = dd[2][2]; d[2][3] = dd[2][3]; d[2][4] = dd[2][4]; d[2][5] = dd[2][5];
d[3][0] = dd[3][0]; d[3][1] = dd[3][1]; d[3][2] = dd[3][2]; d[3][3] = dd[3][3]; d[3][4] = dd[3][4]; d[3][5] = dd[3][5];
d[4][0] = dd[4][0]; d[4][1] = dd[4][1]; d[4][2] = dd[4][2]; d[4][3] = dd[4][3]; d[4][4] = dd[4][4]; d[4][5] = dd[4][5];
d[5][0] = dd[5][0]; d[5][1] = dd[5][1]; d[5][2] = dd[5][2]; d[5][3] = dd[5][3]; d[5][4] = dd[5][4]; d[5][5] = dd[5][5];
}
 
 
 
 
/**
Function assembles compliance %matrix of material.
@param c - complience %matrix of material (output)
@param ssst - strain/stress state
 
@return The function returns material complience %matrix in the parameter d.
 
Created by TKr
*/
void homogmatm::matcompl (matrix &c,strastrestate ssst)
{
matrix d;
allocm (6,6,d);
matstiff (d,ssst);
//c = invm(d);
 
destrm(d);
}
 
 
/**
function assembles the conductivity %matrix after homogenization
@param d - array of %matrix entries
Created by TKr
*/
void homogmatm::assemble_matrices (double *d,long ncomp,long dim)
{
if (ncomp == 3){
dd[0][0]=d[0]; dd[0][1]=d[1]; dd[0][2]=d[2];
dd[1][0]=d[3]; dd[1][1]=d[4]; dd[1][2]=d[5];
dd[2][0]=d[6]; dd[2][1]=d[7]; dd[2][2]=d[8];
 
/* fprintf (Out,"\n");
fprintf (Out,"\n\n d[0] = %e",d[0]);
fprintf (Out,"\n\n d[1] = %e",d[1]);
fprintf (Out,"\n\n d[2] = %e",d[2]);
fprintf (Out,"\n\n d[3] = %e",d[3]);
fprintf (Out,"\n\n d[4] = %e",d[4]);
fprintf (Out,"\n\n d[5] = %e",d[5]);
fprintf (Out,"\n\n d[6] = %e",d[6]);
fprintf (Out,"\n\n d[7] = %e",d[7]);
fprintf (Out,"\n\n d[8] = %e",d[8]);
fprintf (Out,"\n");
fflush(Out);
*/
}
 
if (ncomp == 4){
dd[0][0]=d[0]; dd[0][1]=d[1]; dd[0][2]=d[2]; dd[0][3]=d[3];
dd[1][0]=d[4]; dd[1][1]=d[5]; dd[1][2]=d[6]; dd[1][3]=d[7];
dd[2][0]=d[8]; dd[2][1]=d[9]; dd[2][2]=d[10]; dd[2][3]=d[11];
dd[3][0]=d[12]; dd[3][1]=d[13]; dd[3][2]=d[14]; dd[3][3]=d[15];
}
 
if (ncomp == 6){
dd[0][0]=d[0]; dd[0][1]=d[1]; dd[0][2]=d[2]; dd[0][3]=d[3]; dd[0][4]=d[4]; dd[0][5]=d[5];
dd[1][0]=d[6]; dd[1][1]=d[7]; dd[1][2]=d[8]; dd[1][3]=d[9]; dd[1][4]=d[10]; dd[1][5]=d[11];
dd[2][0]=d[12]; dd[2][1]=d[13]; dd[2][2]=d[14]; dd[2][3]=d[15]; dd[2][4]=d[16]; dd[2][5]=d[17];
dd[3][0]=d[18]; dd[3][1]=d[19]; dd[3][2]=d[20]; dd[3][3]=d[21]; dd[3][4]=d[22]; dd[3][5]=d[23];
dd[4][0]=d[24]; dd[4][1]=d[25]; dd[4][2]=d[26]; dd[4][3]=d[27]; dd[4][4]=d[28]; dd[4][5]=d[29];
dd[5][0]=d[30]; dd[5][1]=d[31]; dd[5][2]=d[32]; dd[5][3]=d[33]; dd[5][4]=d[34]; dd[5][5]=d[35];
 
/* fprintf (Out,"\n");
fprintf (Out,"\n\n d[0] = %e",d[0]);
fprintf (Out,"\n\n d[1] = %e",d[1]);
fprintf (Out,"\n\n d[2] = %e",d[2]);
fprintf (Out,"\n\n d[3] = %e",d[3]);
fprintf (Out,"\n\n d[4] = %e",d[4]);
fprintf (Out,"\n\n d[5] = %e",d[5]);
fprintf (Out,"\n\n d[6] = %e",d[6]);
fprintf (Out,"\n\n d[7] = %e",d[7]);
fprintf (Out,"\n\n d[8] = %e",d[8]);
fprintf (Out,"\n\n d[9] = %e",d[9]);
fprintf (Out,"\n\n d[10] = %e",d[10]);
fprintf (Out,"\n\n d[11] = %e",d[11]);
fprintf (Out,"\n\n d[12] = %e",d[12]);
fprintf (Out,"\n\n d[13] = %e",d[13]);
fprintf (Out,"\n\n d[14] = %e",d[14]);
fprintf (Out,"\n\n d[15] = %e",d[15]);
fprintf (Out,"\n\n d[16] = %e",d[16]);
fprintf (Out,"\n\n d[17] = %e",d[17]);
fprintf (Out,"\n\n d[18] = %e",d[18]);
fprintf (Out,"\n\n d[19] = %e",d[19]);
fprintf (Out,"\n\n d[20] = %e",d[20]);
fprintf (Out,"\n\n d[21] = %e",d[21]);
fprintf (Out,"\n\n d[22] = %e",d[22]);
fprintf (Out,"\n\n d[23] = %e",d[23]);
fprintf (Out,"\n\n d[24] = %e",d[24]);
fprintf (Out,"\n\n d[25] = %e",d[25]);
fprintf (Out,"\n\n d[26] = %e",d[26]);
fprintf (Out,"\n\n d[27] = %e",d[27]);
fprintf (Out,"\n\n d[28] = %e",d[28]);
fprintf (Out,"\n\n d[29] = %e",d[29]);
fprintf (Out,"\n\n d[30] = %e",d[30]);
fprintf (Out,"\n\n d[31] = %e",d[31]);
fprintf (Out,"\n\n d[32] = %e",d[32]);
fprintf (Out,"\n\n d[33] = %e",d[33]);
fprintf (Out,"\n\n d[34] = %e",d[34]);
fprintf (Out,"\n\n d[35] = %e",d[35]);
fprintf (Out,"\n");
fflush(Out);
*/
}
}
 
 
/**
This function initializes material model data
with respect of consistency parameter gamma.
 
@param ipp - integration point number
@param ido - index of internal variables for given material in the ipp other array
 
Created by TKr
*/
void homogmatm::initval(long ipp, long im, long ido)
{
//Mm->ip[ipp].other[ido+0] = Mm->ip[ipp].eqother[ido+0] = 0.0;
//Mm->ip[ipp].other[ido+1] = Mm->ip[ipp].eqother[ido+1] = 0.0;
}
 
 
/**
Function computes true stresses.
@param ipp - number of integration point
@return The function does not return anything.
 
Created by TKr
*/
void homogmatm::nlstresses (long ipp, long im, long ido)
{
long i, n = Mm->ip[ipp].ncompstr;
vector eps(n),sig(n),epst(ASTCKVEC(6));
strastrestate ssst = Mm->ip[ipp].ssst;
matrix d(n,n);
// initial values
for (i=0;i<n;i++){
eps[i]=Mm->ip[ipp].strain[i];
}
matstiff (d,ssst);
mxv (d,eps,sig);
 
/* //it is necessary to complete here:
if (Mm->ip[ipp].ssst == planestress)
Mm->ip[ipp].strain[3] = -nu / (1.0 - nu) * (eps[0]+eps[1]);
*/
 
if ((Mp->eigstrains == 4) || (Mp->eigstrains == 5))
{
for (i=0;i<n;i++)
sig(i) += Mm->eigstresses[ipp][i];
}
for (i=0;i<n;i++){
Mm->ip[ipp].stress[i]=sig(i);
}
}
 
/**
This 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 ido - index of internal variables for given material in the ipp other array
 
Created by TKr
*/
void homogmatm::updateval (long ipp,long ido)
{
//Mm->ip[ipp].eqother[ido+0] = Mm->ip[ipp].other[ido+0]; //
//Mm->ip[ipp].eqother[ido+1] = Mm->ip[ipp].other[ido+1]; //
}
 
 
 
/**
The function returns rate of the volumetric strain rate 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 TKr according to Tomas Koudelka
*/
double homogmatm::give_strain_vol(long ipp, long ido)
{
//return Mm->ip[ipp].eqother[ido+1];
}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/trunk/SIFEL/MEFEL/SRC/homogmatm.h
0,0 → 1,49
#ifndef HOMOGMATM_H
#define HOMOGMATM_H
 
#include "alias.h"
#include "genfile.h"
#include "iotools.h"
struct matrix;
struct vector;
struct atsel;
 
/**
The class homogmatm defines elastic isotropic material model.
Material parameters are:
- Young's modulus (modulus of elasticity)
- Poisson's ratio
Created by TKr,
*/
class homogmatm
{
public:
homogmatm (void);
~homogmatm (void);
void read (XFILE *in);
void print (FILE *out);
 
void matstiff (matrix &d,strastrestate ssst);
void matstiff_plstress (matrix &d);
void matstiff_plstrain (matrix &d);
void matstiff_axi (matrix &d);
void matstiff_spacestr (matrix &d);
void matcompl (matrix &c,strastrestate ssst);
 
void assemble_matrices (double *d,long ncomp, long dim);
 
void initval(long ipp, long im, long ido);
void nlstresses (long ipp, long im, long ido);
void updateval (long ipp,long ido);
double give_strain_vol(long ipp, long ido);
matrix dd;
 
long hom_mattypem; //material type for mogenization
long hom_mattypem_number; //number of material for homogenization
 
};
 
#endif
/trunk/SIFEL/MEFEL/SRC/hypoplunsatexptherm2.cpp
1,1190 → 1,1187
#include <stdlib.h>
#include <float.h>
#include "generalmod.h"
#include "global.h"
#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, params, 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, params, 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];
 
//if((Mp->time >= 5.375400e+05) && ipp == 0)
//fprintf (stdout,"\n zde cas!!"); //debug
 
rkf_stat = huet.soil_model(eps.a, sig.a, statev.a, deps.a, dtime, dd_gen.a, params, 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, params, 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, params, 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, params, 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 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 "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 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/mechmat.cpp
27,6 → 27,7
#include "camclay.h"
#include "camclaycoup.h"
#include "bbm.cpp"
#include "dsm.cpp"
#include "shefplast.h"
#include "hissplas.h"
#include "glasgmech.h"
1350,6 → 1351,18
}
break;
}
case doublestructuremat:{
if (Mespr==1) fprintf (stdout,"\n number of double structure materials for clays %ld",numt);
dsm = new dsmmat [numt];
for (j=0;j<numt;j++){
k=numt+1;
xfscanf (in,"%ld",&k);
if (k>numt || k<1)
print_err("wrong number of double structure materials for clays",__FILE__,__LINE__,__func__);
dsm[k-1].read (in);
}
break;
}
case hypoplastmat:{
if (Mespr==1) fprintf (stdout,"\n number of hypoplast materials for coupling %ld",numt);
hypopl = new hypoplast [numt];
2674,8 → 2687,16
compute_ipstrains(lcid);
Mp->strainstate = 1;
}
bbm[ip[ipp].idm[im]].initval(ipp, ido);
bbm[ip[ipp].idm[im]].initval(ipp, im, ido);
break;
case doublestructuremat:
if (Mp->strainstate == 0)
{
compute_ipstrains(lcid);
Mp->strainstate = 1;
}
dsm[ip[ipp].idm[im]].initval(ipp, im, ido);
break;
case hypoplastmat:
if (Mp->strainstate == 0)
{
3606,6 → 3627,7
case modcamclaymat:
case modcamclaycoupmat:
case bbmcoupmat:
case doublestructuremat:
case hypoplastmat:
case hypoplastusatthermat:
case shefpl:
3797,9 → 3819,13
ncompo += givencompeqother (ipp, im+1);
break;
case bbmcoupmat:
ncompo=ncompstr+13;
ncompo=ncompstr+15+ncompstr*ncompstr+ncompstr;
ncompo += givencompeqother (ipp, im+1);
break;
case doublestructuremat:
ncompo=ncompstr+15+ncompstr*ncompstr+1+ncompstr;
ncompo += givencompeqother (ipp, im+1);
break;
case homomatm:
break;
case hypoplastmat:
4093,7 → 4119,7
double e = 0.0;
 
switch (ip[ipp].tm[im])
{
{
case elisomat:
e = eliso[ip[ipp].idm[im]].e;
break;
4107,6 → 4133,15
e = cclayc[ip[ipp].idm[im]].give_actual_ym(ipp,im,ido);
break;
}
case bbmcoupmat:{
e = bbm[ip[ipp].idm[im]].give_actual_ym(ipp,im,ido);
break;
}
case doublestructuremat:
{
e = dsm[ip[ipp].idm[im]].give_actual_ym(ipp,im,ido);
break;
}
case creepeffym:
e = creffym[ip[ipp].idm[im]].give_actual_ym();
break;
4158,11 → 4193,16
case nonlocplastmat:
case nonlocdamgmat:
case nonlocalmicroM4:
case creep_damage:
ncompo = givencompeqother(ipp, im);
ncompo -= givencompeqother(ipp, im+1);
e = give_actual_ym(ipp, im+1, ido+ncompo); // these artificial materials sould not have internal variables, i.e. ncompo=0 -> no ido index shift
break;
case creep_damage:
ncompo = givencompeqother(ipp, im);
ncompo -= givencompeqother(ipp, im+1); // number of other components of creep material model
ncompo -= givencompeqother(ipp, im+2); // number of other components of damage material model
e = give_actual_ym(ipp, im+1, ido+ncompo); // these artificial materials sould not have internal variables, i.e. ncompo=0 -> no ido index shift
break;
case shrinkagemat:
ncompo = givencompeqother(ipp, im);
ncompo -= givencompeqother(ipp, im+1); // ido index shift due to the shrinkage material
4247,7 → 4287,15
e = cclayc[ip[ipp].idm[im]].give_actual_ym(ipp,im,ido);
break;
}
case bbmcoupmat:
case bbmcoupmat:{
e = bbm[ip[ipp].idm[im]].give_actual_ym(ipp,im,ido);
break;
}
case doublestructuremat:
{
e = dsm[ip[ipp].idm[im]].give_actual_ym(ipp,im,ido);
break;
}
case shefpl:
case glasgowmechmat:
case glasgowdamage:
4280,9 → 4328,14
case nonlocplastmat:
case nonlocdamgmat:
case nonlocalmicroM4:
ncompo = givencompeqother(ipp, im);
ncompo -= givencompeqother(ipp, im+1);
e = give_initial_ym(ipp, im+1, ido+ncompo); // these artificial materials should have no internal variables (ncompo=0) -> no ido index shift
break;
case creep_damage:
ncompo = givencompeqother(ipp, im);
ncompo -= givencompeqother(ipp, im+1);
ncompo -= givencompeqother(ipp, im+2);
e = give_initial_ym(ipp, im+1, ido+ncompo); // these artificial materials should have no internal variables (ncompo=0) -> no ido index shift
break;
case effective_stress:
4329,7 → 4382,7
double nu = 0.0;
 
switch (ip[ipp].tm[im])
{
{
case elisomat:
nu = eliso[ip[ipp].idm[im]].nu;
break;
4343,6 → 4396,14
nu = cclayc[ip[ipp].idm[im]].give_actual_nu(ipp, im, ido);
break;
}
case bbmcoupmat:{
nu = bbm[ip[ipp].idm[im]].give_actual_nu(ipp, im, ido);
break;
}
case doublestructuremat:{
nu = dsm[ip[ipp].idm[im]].give_actual_nu(ipp, im, ido);
break;
}
case creepeffym:
nu = creffym[ip[ipp].idm[im]].give_actual_nu();
break;
4445,7 → 4506,7
double nu = 0.0;
 
switch (ip[ipp].tm[im])
{
{
case elisomat:
nu = eliso[ip[ipp].idm[im]].nu;
break;
4474,6 → 4535,7
case modcamclaymat:
case modcamclaycoupmat:
case bbmcoupmat:
case doublestructuremat:
case shefpl:
case glasgowmechmat:
case glasgowdamage:
4828,6 → 4890,10
s = bbm[i].give_saturation_degree(ipp,ido);
break;
}
case doublestructuremat:{
s = dsm[i].give_saturation_degree(ipp,ido);
break;
}
case hypoplastusatthermat:{
s = hypoplustherm[i].give_sr(ipp,ido);
break;
5000,6 → 5066,10
pc = bbm[i].give_preconspress(ipp,ido);
break;
}
case doublestructuremat:{
pc = dsm[i].give_preconspress(ipp,ido);
break;
}
case effective_stress:
ncompo = givencompeqother(ipp, im);
ncompo -= givencompeqother(ipp, im+1);
5052,6 → 5122,10
e_lambda1 = bbm[i].give_virgporosity(ipp,ido);
break;
}
case doublestructuremat:{
e_lambda1 = dsm[i].give_virgporosity(ipp,ido);
break;
}
case hypoplastmat:{
e_lambda1 = hypopl[i].give_virgporosity(ipp,ido);
break;
5108,6 → 5182,10
n_ini = bbm[i].give_iniporosity(ipp,ido);
break;
}
case doublestructuremat:{
n_ini = dsm[i].give_iniporosity(ipp,ido);
break;
}
case hypoplastmat:{
n_ini = hypopl[i].give_iniporosity(ipp,ido);
break;
5172,6 → 5250,10
n = bbm[i].give_porosity(ipp, ido);
break;
}
case doublestructuremat:{
n = dsm[i].give_porosity(ipp, ido);
break;
}
case hypoplastusatthermat:{
n = hypoplustherm[i].give_porosity(ipp,ido);
break;
5261,6 → 5343,10
epsvr = bbm[i].give_strain_vol_rate(ipp, ido);
break;
}
case doublestructuremat:{
epsvr = dsm[i].give_strain_vol_rate(ipp, ido);
break;
}
case hypoplastusatthermat:{
epsvr = hypoplustherm[i].give_strain_vol_rate(ipp,ido);
break;
5337,6 → 5423,10
cp = bbm[i].give_consparam (ipp,ido);
break;
}
case doublestructuremat:{
cp = dsm[i].give_consparam (ipp,ido);
break;
}
case hissplasmat:{
cp = hisspl[i].give_consparam (ipp,ido);
break;
5638,6 → 5728,10
bbm[ip[ipp].idm[im]].giveirrstrains(ipp, ido, epsirr);
break;
}
case doublestructuremat:{
dsm[ip[ipp].idm[im]].giveirrstrains(ipp, ido, epsirr);
break;
}
case hissplasmat:{
hisspl[ip[ipp].idm[im]].giveirrstrains(ipp, ido, epsirr);
break;
5841,6 → 5935,9
case bbmcoupmat:
bbm[im].give_reqnmq(anmq);
break;
case doublestructuremat:
dsm[im].give_reqnmq(anmq);
break;
case hypoplastmat:
hypopl[im].give_reqnmq(anmq);
break;
6090,6 → 6187,11
bbm[i].matstiff (d,ipp,ido);
break;
}
case doublestructuremat:{
i=ip[ipp].idm[im];
dsm[i].matstiff (d,ipp,ido);
break;
}
case homomatm:{
i=ip[ipp].idm[im];
hommatm[i].matstiff (d,ip[ipp].ssst);
6674,6 → 6776,10
bbm[ip[ipp].idm[im]].nlstresses (ipp,im,ido);
break;
}
case doublestructuremat:{
dsm[ip[ipp].idm[im]].nlstresses (ipp,im,ido);
break;
}
case homomatm:{
hommatm[ip[ipp].idm[im]].nlstresses (ipp,im,ido);
break;
6879,8 → 6985,9
*/
void mechmat::computenlstressesincr (long ipp,long im,long ido)
{
switch (ip[ipp].tm[im]){
long ncompo;
switch (ip[ipp].tm[im]){
case creep_damage:{
crdam[ip[ipp].idm[im]].nlstressesincr (ipp, im, ido);
break;
6903,20 → 7010,26
creffym[ip[ipp].idm[im]].nlstressesincr(ipp,im,ido);
break;
}
/*
case lemaitr:{
lmtr[ip[ipp].idm[im]].nlstresses (ipp,ido);
break;
}
case creepbaz:{
crbaz[ip[ipp].idm[im]].nlstresses (ipp,im,ido);
break;
}
*/
/*
case lemaitr:{
lmtr[ip[ipp].idm[im]].nlstresses (ipp,ido);
break;
}
case creepbaz:{
crbaz[ip[ipp].idm[im]].nlstresses (ipp,im,ido);
break;
}
*/
case consolidation:{
csol[ip[ipp].idm[im]].nlstressesincr (ipp);
break;
}
case effective_stress:{
ncompo = givencompeqother(ipp, im);
ncompo -= givencompeqother(ipp, im+1); // ido index shift due to the effective stress material
computenlstressesincr (ipp,im+1,ido+ncompo);
break;
}
case viscoplasticity:{
visplas[ip[ipp].idm[im]].nlstressesincr (ipp,im,ido);
break;
6925,6 → 7038,14
hypoplustherm[ip[ipp].idm[im]].nlstressesincr(ipp,im,ido);
break;
}
case bbmcoupmat:{
bbm[ip[ipp].idm[im]].nlstressesincr(ipp,im,ido);
break;
}
case doublestructuremat:{
dsm[ip[ipp].idm[im]].nlstressesincr(ipp,im,ido);
break;
}
case elisomat:
case homomatm:
case simplas1d:
6941,9 → 7062,7
case chenplast:
case modcamclaymat:
case modcamclaycoupmat:
case bbmcoupmat:
case shefpl:
case effective_stress:
case glasgowmechmat:
case glasgowdamage:
case scaldamage:
7929,9 → 8048,13
break;
}
case bbmcoupmat:{
bbm[ip[ipp].idm[im]].updateval (ipp,ido);
bbm[ip[ipp].idm[im]].updateval (ipp,im, ido);
break;
}
case doublestructuremat:{
dsm[ip[ipp].idm[im]].updateval (ipp,im, ido);
break;
}
case hypoplastmat:{
hypopl[ip[ipp].idm[im]].updateval (ipp,im,ido);
break;
8164,6 → 8287,7
case modcamclaymat:
case modcamclaycoupmat:
case bbmcoupmat:
case doublestructuremat:
case hypoplastmat:
case hypoplastusatthermat:
case hissplasmat:
8418,7 → 8542,6
case druckerprager2:
case chenplast:
case modcamclaymat:
case bbmcoupmat:
case hissplasmat:
case microplaneM4:
case microsimp:
8471,6 → 8594,12
case modcamclaycoupmat:
cclayc[ip[ipp].idm[im]].dstep_red(ipp, im, ido);
break;
case bbmcoupmat:
bbm[ip[ipp].idm[im]].dstep_red(ipp, im, ido);
break;
case doublestructuremat:
dsm[ip[ipp].idm[im]].dstep_red(ipp, im, ido);
break;
case hypoplastmat:
ret = hypopl[ip[ipp].idm[im]].dstep_red(ipp,im,ido);
break;
8558,6 → 8687,10
f = bbm[ip[ipp].idm[idpm]].yieldfunction (sig,q);
break;
}
case doublestructuremat:{
f = dsm[ip[ipp].idm[idpm]].yieldfunction (sig,q);
break;
}
case hissplasmat:{
f = hisspl[ip[ipp].idm[idpm]].yieldfunction (sig,q);
break;
8632,6 → 8765,10
bbm[ip[ipp].idm[idpm]].deryieldfsigma (sig, q, dfdst);
break;
}
case doublestructuremat:{
dsm[ip[ipp].idm[idpm]].deryieldfsigma (sig, q, dfdst);
break;
}
default:
print_err("unknown plasticity model is required",__FILE__,__LINE__,__func__);
 
8704,6 → 8841,10
bbm[ip[ipp].idm[idpm]].deryieldfsigma (sig, q, dgdst);
break;
}
case doublestructuremat:{
dsm[ip[ipp].idm[idpm]].deryieldfsigma (sig, q, dgdst);
break;
}
default:
print_err("unknown plasticity model is required",__FILE__,__LINE__,__func__);
 
8760,10 → 8901,14
case modcamclaycoupmat:{
cclayc[ip[ipp].idm[idpm]].deryieldfq (sig, q, dq);
break;
}
case bbmcoupmat:{
bbm[ip[ipp].idm[idpm]].deryieldfq (sig, q, dq);
break;
}
case doublestructuremat:{
dsm[ip[ipp].idm[idpm]].deryieldfq (sig, q, dq);
break;
}
case chenplast:{
chplast[ip[ipp].idm[idpm]].deryieldfdq (sig,q,dq);
8816,6 → 8961,10
bbm[ip[ipp].idm[idpm]].dderyieldfsigma (dfdsdst);
break;
}
case doublestructuremat:{
dsm[ip[ipp].idm[idpm]].dderyieldfsigma (dfdsdst);
break;
}
case chenplast:{
chplast[ip[ipp].idm[idpm]].deryieldfdsigmadsigma (sig,dfdsdst);
break;
8875,6 → 9024,10
bbm[ip[ipp].idm[idpm]].dderyieldfsigma (dgdsdst);
break;
}
case doublestructuremat:{
dsm[ip[ipp].idm[idpm]].dderyieldfsigma (dgdsdst);
break;
}
case chenplast:{
chplast[ip[ipp].idm[idpm]].deryieldfdsigmadsigma (sig, dgdsdst);
break;
8935,6 → 9088,10
bbm[ip[ipp].idm[idpm]].deryieldfdsdq (dfdsdqt);
break;
}
case doublestructuremat:{
dsm[ip[ipp].idm[idpm]].deryieldfdsdq (dfdsdqt);
break;
}
case chenplast:{
chplast[ip[ipp].idm[idpm]].deryieldfdsigmadq (sig,q,dfdsdqt);
break;
8990,6 → 9147,10
bbm[ip[ipp].idm[idpm]].deryieldfdsdq (dgdsdqt);
break;
}
case doublestructuremat:{
dsm[ip[ipp].idm[idpm]].deryieldfdsdq (dgdsdqt);
break;
}
case chenplast:{
chplast[ip[ipp].idm[idpm]].deryieldfdsigmadq (sig,q,dgdsdqt);
break;
9039,6 → 9200,14
cclayc[ip[ipp].idm[idpm]].der_q_gamma(ipp, ido, sig, q, epsp, dqdg);
break;
}
case bbmcoupmat:{
bbm[ip[ipp].idm[idpm]].der_q_gamma(ipp, ido, sig, q, epsp, dqdg);
break;
}
case doublestructuremat:{
dsm[ip[ipp].idm[idpm]].der_q_gamma(ipp, ido, sig, q, epsp, dqdg);
break;
}
default:
print_err("unknown plasticity model is required",__FILE__,__LINE__,__func__);
}
9079,6 → 9248,14
cclayc[ip[ipp].idm[idpm]].dqpardgammadsigma(ipp, ido, sig, q, epsp, dqdgdst);
break;
}
case bbmcoupmat:{
bbm[ip[ipp].idm[idpm]].dqpardgammadsigma(ipp, ido, sig, q, epsp, dqdgdst);
break;
}
case doublestructuremat:{
dsm[ip[ipp].idm[idpm]].dqpardgammadsigma(ipp, ido, sig, q, epsp, dqdgdst);
break;
}
default:
print_err("unknown plasticity model is required",__FILE__,__LINE__,__func__);
 
9117,6 → 9294,14
cclayc[ip[ipp].idm[idpm]].dqpardgammadqpar(ipp, ido, sig, q, epsp, dqdgdq);
break;
}
case bbmcoupmat:{
bbm[ip[ipp].idm[idpm]].dqpardgammadqpar(ipp, ido, sig, q, epsp, dqdgdq);
break;
}
case doublestructuremat:{
dsm[ip[ipp].idm[idpm]].dqpardgammadqpar(ipp, ido, sig, q, epsp, dqdgdq);
break;
}
default:
print_err("unknown plasticity model is required",__FILE__,__LINE__,__func__);
 
9176,6 → 9361,10
bbm[ip[ipp].idm[idpm]].deryieldfq (sig, q, dq);
break;
}
case doublestructuremat:{
dsm[ip[ipp].idm[idpm]].deryieldfq (sig, q, dq);
break;
}
case chenplast:{
chplast[ip[ipp].idm[idpm]].deryieldfdq (sig,q,dq);
break;
9486,9 → 9675,13
break;
}
case bbmcoupmat:{
ret = bbm[ip[ipp].idm[idpm]].plasmodscalar(ipp, ido, sig, qtr);
ret = bbm[ip[ipp].idm[idpm]].plasmodscalar(ipp, ido, sig, qtr, epsp);
break;
}
case doublestructuremat:{
ret = dsm[ip[ipp].idm[idpm]].plasmodscalar(ipp, ido, sig, qtr, epsp);
break;
}
default:
print_err("unknown plasticity model is required",__FILE__,__LINE__,__func__);
 
9540,7 → 9733,8
case modcamclaycoupmat:{
break;
}
case bbmcoupmat:{
case bbmcoupmat:
case doublestructuremat:{
break;
}
default:
9594,7 → 9788,8
case modcamclaycoupmat:{
break;
}
case bbmcoupmat:{
case bbmcoupmat:
case doublestructuremat:{
break;
}
/*
9673,6 → 9868,10
bbm[ip[ipp].idm[idpm]].updateq(ipp, ido, eps, epsp, sig, q);
break;
}
case doublestructuremat:{
dsm[ip[ipp].idm[idpm]].updateq(ipp, ido, eps, epsp, sig, q);
break;
}
default:
print_err("unknown plasticity model is required",__FILE__,__LINE__,__func__);
 
11668,6 → 11867,7
case creep_damage:{
ncompo = givencompeqother(ipp, im);
ncompo -= givencompeqother(ipp, im+1);
ncompo -= givencompeqother(ipp, im+2);
givestressincr (lcid, ipp, im+1, ido+ncompo, fi, sig);
break;
}
11696,6 → 11896,14
hypoplustherm[i].givestressincr(lcid, ipp, im, ido, fi, sig);
break;
}
case bbmcoupmat:{
i=ip[ipp].idm[im];
bbm[i].givestressincr(lcid, ipp, im, ido, fi, sig);
}
case doublestructuremat:{
i=ip[ipp].idm[im];
dsm[i].givestressincr(lcid, ipp, im, ido, fi, sig);
}
/*
case consolidation:{
csol[ip[ipp].idm[im]].give_dstresses_eqother (ipp,ido,sig);
11728,7 → 11936,6
case chenplast:
case modcamclaymat:
case modcamclaycoupmat:
case bbmcoupmat:
case shefpl:
case glasgowmechmat:
case glasgowdamage:
/trunk/SIFEL/MEFEL/SRC/mechmat.h
27,6 → 27,7
class doubdp;
class drprag2;
class bbmmat;
class dsmmat;
class camclay;
class camclaycoup;
class shefplast;
869,6 → 870,8
doubdp *ddpm;
/// Drucker-Prager model of plasticity prepare by Standa Sysala from IGN
drprag2 *drprm2;
/// double structure model
dsmmat *dsm;
/// modified barcelona basic model
bbmmat *bbm;
/// modified cam-clay model
/trunk/SIFEL/MEFEL/SRC/mtsolver.cpp
778,9 → 778,9
if (Mespr==1) fprintf (stdout,"\n MEFEL Time step = %ld, Time %e, Time increment = %e",istep,Mp->time,dt);
if (Mespr==1) fprintf (stdout,"\n ------------------------------------------------------------------------\n");
 
//if (Mespr==1) fprintf (Out,"\n\n ------------------------------------------------------------------------");
//if (Mespr==1) fprintf (Out,"\n MEFEL Time step = %ld, Time %e, Time increment = %e",istep,Mp->time,dt);
//if (Mespr==1) fprintf (Out,"\n ------------------------------------------------------------------------\n");
if (Mespr==1) fprintf (Out,"\n\n ------------------------------------------------------------------------");
if (Mespr==1) fprintf (Out,"\n MEFEL Time step = %ld, Time %e, Time increment = %e",istep,Mp->time,dt);
if (Mespr==1) fprintf (Out,"\n ------------------------------------------------------------------------\n");
 
// assembling of vectors of prescribed nodal forces
mefel_right_hand_side (lcid,f,fl);
793,7 → 793,19
// istep, Mp->time, Mp->time/86400, Mb->sumcomp[0], Mb->sumcomp[1], Mb->sumcomp[2]);
//fflush(Out);
 
//debug??!!
//long i;
//fprintf(Out,"\n\n");
//for(i=0; i<n; i++)
//fprintf(Out,"\n f[%ld] = %e",i,f[i]);
//fflush(Out);
 
//fprintf(Out,"\n\n");
//for(i=0; i<n; i++)
//fprintf(Out,"\n fl[%ld] = %e",i,fl[i]);
//fflush(Out);
 
// assemble force vector due to removed elements and apply it gradually if required
if (Mp->tprob == growing_mech_structure)
{
803,6 → 815,12
// increments of prescribed internal forces
incr_internal_forces (lcid,fi);
 
//debug??!!
//fprintf(Out,"\n\n");
//for(i=0; i<n; i++)
//fprintf(Out,"\n fi[%ld] = %e",i,fi[i]);
//fflush(Out);
 
// assembling of right hand side
// fb[j]=f[j]-fp[j]+fi[j]
subv(f, fp, fb, n);
/trunk/SIFEL/MEFEL/SRC/newtonraph.cpp
706,7 → 706,8
double gnewton_raphson_one_step(long lcid, nonlinman *nlman, double *fa, double *ra, double *fb, double *dr, double *fi,
double &dtr, long istep, long &j, long li, answertype fusm)
{
long i,n = Ndofm; // number of rows of the matrix or vectors
long i;
long n = Ndofm; // number of rows of the matrix or vectors
long ini; // maximum number of inner iterations
double ierr; // required error of the residual vector
double norf; // norm of residual vector (vector of unbalanced forces)
740,11 → 741,13
// solution of K(r).\Delta r=\Delta F
Mp->ssle->solve_system (Gtm,Smat,dr,fb,Out);
 
/* if (Mp->time >= 5.375400e+05 && Mp->time<= 5.385400e+05){
for (i=0;i<n;i++)
fprintf (Out,"\%le\n",dr[i]);
}
*/
// if (Mp->time >= 5.375400e+05 && Mp->time<= 5.385400e+05){
//fprintf (Out,"\n istep = %ld j = %ld \n",istep,j);
//for (i=0;i<n;i++)
// fprintf (Out,"% .15le\n",dr[i]);
//fflush(Out);
//}
 
// update total displacement vector
// ra[j]+=dr[j];
777,7 → 780,7
//fprintf(Outdm->outf, "\n****** Load step %ld, norf=%le:\n\n", istep+1, norf);
//Outdm->eo.print_out(Outdm->outf, lcid);
 
fprintf (stdout,"\n Initial residual norm norf=%le, norm of load vector norfa=%le",norf,norfa);
fprintf (stdout,"\n Initial residual norm norf=%.15le, norm of load vector norfa=%.15le",norf,norfa);
//fprintf (Out,"\n norf=%e\n",norf);
 
if (norf<ierr)
803,6 → 806,12
// solution of K(r).v=F
Mp->ssle->solve_system(Gtm,Smat,dr,fb,Out);
 
//fprintf (Out,"Inner loop \n istep = %ld j = %ld \n",istep,j);
//for (i=0;i<n;i++)
// fprintf (Out,"% .15le\n",dr[i]);
//fflush(Out);
 
// ra[k]+=dr[k];
addv(ra, dr, n);
831,7 → 840,7
//fprintf(Outdm->outf, "\n****** Internal loop %ld, norf=%le:\n\n", j+1, norf);
//Outdm->eo.print_out(Outdm->outf, lcid);
fprintf (stdout,"\n increment %ld inner loop j %ld norm %le, norfa %le", istep, j, norf, norfa);
fprintf (stdout,"\n increment %ld inner loop j %ld norm %.15le, norfa %.15le", istep, j, norf, norfa);
//fprintf (Out,"\n j=%ld norf=%e",j,norf);
/*
vector pe(ASTCKVEC(1));
/trunk/SIFEL/METR/SRC/bentonitemat.cpp
353,7 → 353,7
long i,j;
// pocet slozek strainu
long ncomp = Cm->ip[ipp].ncompstr;
strastrestate ssst = Cm->ip[ipp].ssst;
//strastrestate ssst = Cm->ip[ipp].ssst;
double aux;
matrix dd_gen(ASTCKMAT(ngstress,ngstrain)), dd(ASTCKMAT(6,6)), ddd(ASTCKMAT(ngstress,ngstrain));
vector statev(ASTCKVEC(nstatev));
/trunk/SIFEL/METR/SRC/consol_hawf3c.cpp
1245,7 → 1245,8
double con_hawf3matc::get_capwu(double pw, double pg, double t,long ipp)
{
double capwu;
double sw,sg,alpha,rhow,rhogw,n,dsr_depsv;
double sw,sg,alpha,rhow,rhogw;
//double n,dsr_depsv;
sw = get_sw(pw,pg,t,ipp);
alpha = get_alpha(pw,pg,t,ipp);
1310,7 → 1311,8
double con_hawf3matc::get_capgu(double pw, double pg, double t,long ipp)
{
double capgu;
double sg,sw,alpha,rhoga,n,dsr_depsv;
double sg,sw,alpha,rhoga;
//double n,dsr_depsv;
sw = get_sw(pw,pg,t,ipp);
alpha = get_alpha(pw,pg,t,ipp);
1427,7 → 1429,8
double con_hawf3matc::get_captu(double pw,double pg,double t,long ipp)
{
double captu;
double dhvap,sw,rhow,alpha,n,dsr_depsv;
double dhvap,sw,rhow,alpha;
//double n,dsr_depsv;
dhvap = get_dhvap(t);
sw = get_sw(pw,pg,t,ipp);
/trunk/SIFEL/METR/SRC/globmatc.cpp
654,13 → 654,14
@param rhs - right hand side
21.3.2004, JK+TKr
09/11/2012 corrected by TKr
09/11/2012 corrected by TKr,
20/04/2023 another correction by TKr
*/
void assemble_init_coup (double *rhs)
{
long i,j,mndofe,tndofe,lcid=0;
double dt;
ivector rcn;
ivector rcn,ccn;
vector r,f,pr;
matrix km,cm;
674,12 → 675,14
reallocv (RSTCKVEC(tndofe,pr));
reallocm (RSTCKMAT(mndofe,tndofe,km));
reallocv (RSTCKIVEC(mndofe, rcn));
reallocv (RSTCKIVEC(tndofe, ccn));
 
upper_cond_coupl_mat (i,lcid,km);
Gtm->give_code_numbers (i,rcn.a);
Gtt->give_code_numbers (i,ccn.a);
//elemvalues (i, r);
prescvalues (r.a,rcn.a,mndofe); //old wrong: prescvalues (r.a,rcn.a,tndofe);
// prescribed values from TRFEL
prescvalues (r.a,ccn.a,tndofe);
 
mxv (km,r,f);
cmulv (-1.0,f);
688,7 → 691,7
 
// contribution from time derivative of prescribed values on boundaries
// prescribed values from the previous time step
prevprescvalues (pr.a,rcn.a,mndofe);//old: prevprescvalues (pr.a,rcn.a,tndofe);
prevprescvalues (pr.a,rcn.a,tndofe);
// the length of time step
dt=Tp->timecont.forwarddt;
// computation of the time derivative of
715,13 → 718,16
reallocv (RSTCKVEC(mndofe,pr));
reallocm (RSTCKMAT(tndofe,mndofe,km));
reallocv (RSTCKIVEC(tndofe, rcn));
reallocv (RSTCKIVEC(mndofe, ccn));
 
lower_cond_coupl_mat (i,lcid,km);
Gtt->give_code_numbers (i,rcn.a);//old:Gtm->give_code_numbers (i,rcn.a);
Gtt->give_code_numbers (i,rcn.a);
Gtm->give_code_numbers (i,ccn.a);
//elemvalues (i, r);
prescvalues (r.a,rcn.a,tndofe);//old: prescvalues (r.a,rcn.a,mndofe);
// prescribed values (displacements) from MEFEL
// prescdispl (r.a,ccn.a,mndofe); // not implemented in MEFEL
elprdispl (lcid,i,r.a);
 
mxv (km,r,f);
cmulv (-1.0,f);
728,9 → 734,9
locglob (rhs,f.a,rcn.a,tndofe);
 
// contribution from time derivative of prescribed values on boundaries
// prescribed values from the previous time step
prevprescvalues (pr.a,rcn.a,tndofe);//old: prevprescvalues (pr.a,rcn.a,mndofe);
// contribution from time derivative of prescribed values on boundaries - displacements
// prevprescdislp (pr.a,rcn.a,mndofe); // not implemented in MEFEL
elprevprdispl (lcid,i,pr.a);
// the length of time step
dt=Tp->timecont.forwarddt;
// computation of the time derivative of
747,7 → 753,7
cmulv (-1.0,f);
// localization of nodal values
locglob (rhs,f.a,rcn.a,tndofe);
locglob (rhs,f.a,ccn.a,tndofe);
}
}
 
2156,8 → 2162,23
char *ips = new char[tnipt];
memset(ips, 0, sizeof(*ips)*tnipt);
 
if (Mesprc == 1)
fprintf(stdout, "\nCalculation of auxiliary int. points TRFEL->MEFEL:\n");
if (Tm->nntq == 0){
fprintf(stdout, "No mechanical quantities are required in TRFEL => no auxiliary points are calculated\n");
for(j=0; j<tnipt; j++){
TMipmap[j].cerr = err*err/10.0;
TMipmap[j].ipp = 0;
TMipmap[j].eid = 0;
}
return;
}
for(i=0; i<nem; i++)
{
if ((Mesprc == 1) && ((i%1000 == 0) || (i == nem-1))){
fprintf(stdout, "Searching aux. points on %ld. element\r", i+1);
fflush(stdout);
}
if(Gtm->leso[i])
{
centroid(i, cg);
2230,6 → 2251,7
}
}
}
fprintf(stdout, "\n");
delete [] ips;
}
 
2268,8 → 2290,24
char *ips = new char[tnipm];
memset(ips, 0, sizeof(*ips)*tnipm);
 
if (Mesprc == 1)
fprintf(stdout, "\nCalculation of auxiliary int. points MEFEL->TRFEL:\n");
if (Mm->nnmq == 0){
fprintf(stdout, "No transport quantities are required in MEFEL => no auxiliary points are calculated\n");
for(j=0; j<tnipm; j++){
MTipmap[j].cerr = err*err/10.0;
MTipmap[j].ipp = 0;
MTipmap[j].eid = 0;
}
return;
}
for(i=0; i<net; i++)
{
if ((Mesprc == 1) && ((i%1000 == 0) || (i == net-1))){
fprintf(stdout, "Searching aux. points on %ld. element\r", i+1);
fflush(stdout);
}
if(Gtt->leso[i])
{
centroidt(i, cg);
2342,6 → 2380,7
}
}
}
fprintf(stdout, "\n");
delete [] ips;
}
 
/trunk/SIFEL/METR/SRC/metrinit.cpp
612,7 → 612,9
if (Cp->tprob!=fully_coupled_material){
switch (Cp->dpt){
case pass_by_closest_ip:
//data are copied directly between int. points, the SAME int. point must be used on both meshes for the first Tt->ne elements
// data are copied directly between nodes,
// the first n-th elements must be defined on both meshes with the SAME node numbers, MEFEL elements may use higher number of nodes,
// but first m nodes on elements must be the SAME
//
// create mapping between TRFEL and MEFEL nodes
TM_nod_map = new long[Tt->nn];
/trunk/SIFEL/METR/SRC/probdescc.cpp
46,7 → 46,7
// the maximum number of itartions in the computation of auxiliary int. point coordinates
aip_ni = 100;
// the maximum distance of two points at which they may be assumed to be identical in the computation of auxiliary int. point coordinates
aip_err = 1.0e-6;
aip_err = 1.0e-5;
 
incr_step=0;
inner_step=0;
/trunk/SIFEL/TRFEL/SRC/C30bazant.cpp
13,6 → 13,7
#include "constrel.h"
#include "C30bazant.h"
#include "globalt.h"
#include "globmatt.h"
 
C30bazmat::C30bazmat()
{
754,3 → 755,27
*/
void C30bazmat::print(FILE *out)
{}
 
 
/**
The function returns ordered dof names of primary unknowns
required by the model.
 
@param dofname - array of uknown name for particular nodal dofs (output)
dofname[i] = name of i-th nodal unknown (for names see aliast.h - enum namevart)
@param ntm - number of transported media = number of nodal dof = length of array dofname
 
Created by Tomas Krejci according to Tomas Koudelka, 11/01/2023
*/
void C30bazmat::give_dof_names(namevart *dofname, long ntm)
{
if (ntm < 1)
{
print_err("the model defines %ld unknowns but number of transported media is %ld",
__FILE__, __LINE__, __func__, 1, ntm);
abort();
}
dofname[0] = trf_capillary_press;
dofname[1] = trf_gas_press;
dofname[2] = trf_temperature;
}
/trunk/SIFEL/TRFEL/SRC/C30bazant.h
1,6 → 1,7
#ifndef C30_BAZANT_H
#define C30_BAZANT_H
 
#include "aliast.h"
#include "genfile.h"
 
class C30bazmat
43,6 → 44,8
void read(XFILE *in);
void print(FILE *out);
 
void give_dof_names(namevart *dofname, long ntm);
 
private:
double mw;
double ma;
/trunk/SIFEL/TRFEL/SRC/C60bazant.h
1,6 → 1,7
#ifndef C60_BAZANT_H
#define C60_BAZANT_H
 
#include "aliast.h"
#include "genfile.h"
 
class C60bazmat
/trunk/SIFEL/TRFEL/SRC/Makefile
39,7 → 39,7
SRCS += glasgowmat.cpp globalt.cpp globmatt.cpp gmultiphase.cpp grunewaldmat.cpp homogt.cpp homogmat.cpp homogtrans.cpp hydrationheat.cpp
SRCS += interfacematt.cpp interfacequadrilat.cpp intpointst.cpp isotherm.cpp isotrmat.cpp
SRCS += kunzel.cpp kunzel2.cpp lhsrhst.cpp lewis_schrefler.cpp linbart.cpp linbart3d.cpp linbartax.cpp lincoupmat.cpp linhext.cpp lintett.cpp
SRCS += loadcaset.cpp loadelt.cpp millymat.cpp moistheat.cpp multiphase.cpp nlisotrmat.cpp npglvec.cpp nnpsolvert.cpp nodet.cpp nonlinmant.cpp
SRCS += loadcaset.cpp loadelt.cpp masin_reten.cpp millymat.cpp moistheat.cpp multiphase.cpp nlisotrmat.cpp npglvec.cpp nnpsolvert.cpp nodet.cpp nonlinmant.cpp
SRCS += npsolvert.cpp nspsolvert.cpp onemedium.cpp outdiagt.cpp outdrivert.cpp o30bazant.cpp pedersen.cpp
SRCS += probdesct.cpp pvalt.cpp potts.cpp quadbart.cpp quadbartax.cpp quadhext.cpp quadlinaxisym.cpp quadlineart.cpp
SRCS += quadquadrilatt.cpp quadquadrilattax.cpp radiationmat.cpp richards.cpp richardscontam.cpp saltmat1.cpp saltmat2.cpp saltmat3.cpp saltmat4.cpp seebeckheat.cpp
/trunk/SIFEL/TRFEL/SRC/aliast.h
118,8 → 118,8
 
 
// aliases for boundary conditions
enum bocontypet {no_bc=0, presc_comp=1, presc_flux=2, det_climcond=3, gen_climcond=5, presc_trmiss=30, presc_trmiss_spec=31,presc_trmiss_isoheat=32,presc_trmiss_computed=50,presc_trmiss_radiation=90, presc_trmiss_free_surface=40,};
const enumstr bocontypetstr[] = {{"no_bc",0}, {"presc_comp",1}, {"presc_flux",2}, {"det_climcond",3}, {"gen_climcond",5}, {"presc_trmiss",30}, {"presc_trmiss_spec",31},{"presc_trmiss_isoheat",32},{"presc_trmiss_computed",50},{"presc_trmiss_radiation",90},{"presc_trmiss_free_surface",40}};
enum bocontypet {no_bc=0, presc_comp=1, presc_flux=2, det_climcond=3, gen_climcond=5, presc_trmiss=30, presc_trmiss_spec=31,presc_trmiss_isoheat=32,presc_trmiss_computed=50,presc_trmiss_salt=51,presc_trmiss_radiation=90, presc_trmiss_free_surface=40,};
const enumstr bocontypetstr[] = {{"no_bc",0}, {"presc_comp",1}, {"presc_flux",2}, {"det_climcond",3}, {"gen_climcond",5}, {"presc_trmiss",30}, {"presc_trmiss_spec",31},{"presc_trmiss_isoheat",32},{"presc_trmiss_computed",50},{"presc_trmiss_salt",51},{"presc_trmiss_radiation",90},{"presc_trmiss_free_surface",40}};
const kwdset bocontype_kwdset(sizeof(bocontypetstr)/sizeof(*bocontypetstr), bocontypetstr);
 
 
188,11 → 188,16
enum sourceloc {nod=1,elem=2};
 
// aliases for models of retention curve type
enum sr_type {lewis_and_schrefler_sr=1,gardner_exponential_sr=2,potts_log_linear_sr=3,van_genuchten_sr=4,van_genuchten2_sr=5,mefel_sr=7,table_sr=8,bazant_sr=9,baroghel_sr=10};
enum sr_type {lewis_and_schrefler_sr=1,gardner_exponential_sr=2,potts_log_linear_sr=3,van_genuchten_sr=4,van_genuchten2_sr=5,mefel_sr=7,table_sr=8,bazant_sr=9,baroghel_sr=10,masin_sr=11};
const enumstr sr_typestr[] = {{"lewis_and_schrefler_sr",1}, {"gardner_exponential_sr",2}, {"potts_log_linear_sr",3}, {"van_genuchten_sr",4},
{"mefel_sr",7},{"table_sr",8},{"bazant_sr",9},{"baroghel_sr",10}};
{"mefel_sr",7},{"table_sr",8},{"bazant_sr",9},{"baroghel_sr",10},{"masin_sr",11}};
const kwdset sr_type_kwdset(sizeof(sr_typestr)/sizeof(*sr_typestr),sr_typestr);
 
// aliases for models of effective stress factor (parameter) type
enum xi_type {biot_xi=1,masin_xi=2,biot_reduced_xi=3,biot_masin_xi=4};
const enumstr xi_typestr[] = {{"biot_xi",1}, {"masin_xi",2},{"biot_reduced_xi",3},{"biot_masin_xi",4}};
const kwdset xi_type_kwdset(sizeof(xi_typestr)/sizeof(*xi_typestr),xi_typestr);
 
 
#endif
 
/trunk/SIFEL/TRFEL/SRC/baroghelB.h
1,6 → 1,7
#ifndef BAROGHELB_H
#define BAROGHELB_H
 
#include "aliast.h"
#include "genfile.h"
 
class baroghelmat
/trunk/SIFEL/TRFEL/SRC/consol_hawf3.cpp
33,11 → 33,13
con_hawf3mat::con_hawf3mat()
{
compress = 0; //compressible grains: 0=no; 1=yes
por_type = 0; //porosity calculation type
kintr_type = 0; //intrinsic permability calculation type
krw_type = 0; //relative permeability calculation type
krg_type = 0; //relative permability calculation type
deff_type = 0; // diffusion calculation type
sr_type = 1; //retention curve calculation type
xi_type = 1; //effective stress parameter type
lambda_type =0; //heat conduction calculation type
cps_type = 0; //specific heat calculation type
betas_type = 0; //thermal expansion calculation type
126,9 → 128,13
sr_dry = 0.0;
sr_wet = 0.0;
tau0 = 0.0;
 
sirr = 0.0;
ssat = 1.0;
 
lambda_krw = 1.9; //parameter for exponential function of relative permeability
beta_krw = 0.0; //parameter for power function of relative permeability
 
bb1 = 0.0;
phi01 = 0.0;
 
160,7 → 166,7
xfscanf (in,"%d", &compress);
 
// common material parameters
xfscanf (in,"%le %le %le %le %le %le %le %d %d %d %d %d %d %d %d", &alpha0, &ks0, &phi0, &rhos0, &pw_bc, &tau0, &kintr0, &kintr_type, &krw_type, &krg_type, &deff_type, &sr_type, &lambda_type, &cps_type, &betas_type);
xfscanf (in,"%le %le %le %le %le %le %d %d %d %d %d %d %d %d %d %d", &alpha0, &ks0, &rhos0, &pw_bc, &tau0, &kintr0, &por_type, &kintr_type, &krw_type, &krg_type, &deff_type, &sr_type, &xi_type, &lambda_type, &cps_type, &betas_type);
 
switch (model_type){
case artificial3:{//artificial isotropic material for non-isotherma air-water flow
181,6 → 187,21
}
 
if(model_type != artificial3){
//porosity calculation:
switch (por_type){
case 0:{//constant
xfscanf (in,"%le",&phi0);
break;
}
case 1:{//dependent on mefel calculation
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
}
}
 
//intrinsic permebility calculation:
switch (kintr_type){
case 0:{//constant
190,6 → 211,10
xfscanf (in,"%le %le", &bb1, &phi01);
break;
}
case 2:{//dependent on porosity - cubic and quadratic
xfscanf (in,"%le", &phi01);
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
210,6 → 235,14
xfscanf (in,"%le", &lambda_krw);
break;
}
case 4:{//liakopoulos
break;
}
case 5:{//double exponential
xfscanf (in,"%le %le", &sirr, &ssat);
xfscanf (in,"%le", &beta_krw);
break;
}
case 9:{//bazant
break;
}
268,6 → 301,10
data.read (in);
break;
}
case masin_sr:{//extended formulation from Brooks and Correy according to Masin
masin_ret.read(in);
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
274,6 → 311,22
}
}
switch (xi_type){
case biot_xi:
break;
case biot_reduced_xi:{//coefficient for effective stress factor reduction
xfscanf (in,"%le %le", &gamma,&lambda0);
break;
}
case masin_xi:
break;
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
}
}
//conductivity calculation:
switch (lambda_type){
case 0:{//constant
525,7 → 578,63
return(deff);
}
 
 
 
/**
function computes effective stress factor xi
@param pw - water pressure
@param t - temperature
 
@retval xi - factor xi
 
04/04/2023, TKr
*/
double con_hawf3mat::get_xi(double pw, double pg, double t, long ipp)
{
double sw=0.0,xi=0.0;
switch (xi_type){
case biot_xi:
sw = get_sw(pw,pg,t,ipp);
break;
case biot_reduced_xi:
//xi = gamma*get_sw(pw,pg,t,ipp);
sw = get_sw(pw,pg,t,ipp);
//xi = pow(sr,(gamma/lambda0));
xi = pow(sw,gamma);
xi = (1-gamma)*xi;
break;
case masin_xi:{
double e=0.0,dpw=0.0,dpg=0.0,dpc=0.0,pc=0.0,por=0.0;
if(Tm->nontransq != NULL){
por = Tm->givenontransq(porosity, ipp);// from mefel
e = por/(1-por);
}
else{
e = phi0/(1-phi0);
}
dpw = Tm->ip[ipp].av[0]-Tm->ip[ipp].pv[0];
dpg = Tm->ip[ipp].av[1]-Tm->ip[ipp].pv[1];
dpc = dpg - dpw;
 
pg = pg - p0;//pore gas pressure without atmospheric pressure
pc = pg - pw;
 
xi = masin_ret.psi(pc,dpc,e,t);//positive value of suction
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
}
}
return(xi);
}
 
 
 
/**
function computes degree of saturation(sorption curve)
@param pw - water pressure
@param pg - air pressure
579,6 → 688,20
//sw = van_genuchten_ret.sw2(pw);
break;
}
case masin_sr:{//extended formulation from Brooks and Correy according to Masin
double e=0.0,dpw=0.0,por=0.0;
if(Tm->nontransq != NULL){
por = Tm->givenontransq(porosity, ipp);// from mefel
e = por/(1-por);
}
else{
e = phi0/(1-phi0);
}
 
dpw = Tm->ip[ipp].av[0]-Tm->ip[ipp].pv[0];
sw = masin_ret.sw(-pw,-dpw,e,t);//positive value of suction
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
634,6 → 757,25
//dsw_dpc = -van_genuchten_ret.dsw_dpw2(pw);
break;
}
case masin_sr:{//extended formulation from Brooks and Correy according to Masin
double e=0.0,dpw=0.0,dpg=0.0,dpc=0.0,pc=0.0,por=0.0;
if(Tm->nontransq != NULL){
por = Tm->givenontransq(porosity, ipp);// from mefel
e = por/(1-por);
}
else{
e = phi0/(1-phi0);
}
 
dpw = Tm->ip[ipp].av[0]-Tm->ip[ipp].pv[0];
dpg = Tm->ip[ipp].av[1]-Tm->ip[ipp].pv[1];
dpc = dpg - dpw;
 
pg = pg - p0;//pore gas pressure without atmospheric pressure
pc = pg - pw;
dsw_dpc = masin_ret.dsw_dpw(pc,dpc,e,t);//positive value of suction
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
688,6 → 830,25
//dsw_dt = van_genuchten_ret.dsw_dt2(pw);
break;
}
case masin_sr:{//extended formulation from Brooks and Correy according to Masin
double e=0.0,dpw=0.0,dpg=0.0,dpc=0.0,pc=0.0,por=0.0;
if(Tm->nontransq != NULL){
por = Tm->givenontransq(porosity, ipp);// from mefel
e = por/(1-por);
}
else{
e = phi0/(1-phi0);
}
dpw = Tm->ip[ipp].av[0]-Tm->ip[ipp].pv[0];
dpg = Tm->ip[ipp].av[1]-Tm->ip[ipp].pv[1];
dpc = dpg - dpw;
 
pg = pg - p0;//pore gas pressure without atmospheric pressure
pc = pg - pw;
 
dsw_dt = masin_ret.dsw_dt(pc,dpc,e,t);//positive value of suction
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
703,28 → 864,31
 
@retval phi - porosity
 
15/04/2021, TKr
04/04/2023, TKr
*/
double con_hawf3mat::give_porosity(long ipp)
{
double por;
switch (model_type){
case lewis_and_schrefler:{//Lewis and Schrefler's book
por = phi0; //constant value
//porosity calculation:
switch (por_type){
case 0:{//constant
por = phi0;
break;
}
case lewis_and_schrefler_mefel:{//Lewis and Schrefler's book
por = Tm->givenontransq(porosity, ipp);// from mefel
case 1:{//dependent on mefel calculation
if(Tm->nontransq != NULL){
por = Tm->givenontransq(porosity, ipp);// from mefel
}
else
por = phi0;//for testing
break;
}
 
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
}
}
 
return(por);
}
 
756,14 → 920,12
kintr = kintr0*exp(bb1*(phi - phi01));
break;
}
case 2:{//not finished
case 2:{//dependent on porosity - cubic and quadratic
//Kozeny's approach for bentonite:
//phi = get_porosity(pw,pg,t,ipp);
//kintr = kintr0*(phi*phi*phi)/(1 - phi)/(1 - phi)*(1 - phi0)*(1 - phi0)/phi0/phi0/phi0;
 
phi = give_porosity(ipp);
kintr = kintr0*phi*phi*phi/(1 - phi01)*(1 - phi01)*(1 - phi)*(1 - phi)/(phi01*phi01*phi01);
break;
}
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
785,7 → 947,7
*/
double con_hawf3mat::get_krw(double pw, double pg, double t, long ipp)
{
double sw,krw;
double sw,sef,krw;
krw = 1.0;
 
switch (krw_type){
808,6 → 970,20
krw = pow(sw,lambda_krw);
break;
}
case 4:{//liakopoulos
sw = get_sw(pw,pg,t,ipp);
krw = 1.0-2.207*pow((1.0-sw),1.0121);
break;
}
case 5:{//double exponential
sw = get_sw(pw,pg,t,ipp);
sef = (sw-sirr)/(ssat-sirr); //effective saturation degree
krw = pow(sef,(1.0/beta_krw));
krw = pow((1.0-krw),beta_krw);
krw = pow((1.0-krw),2.0);
krw = pow(sef,0.5)*krw;
break;
}
case 9:{//bazant
sw = get_sw(pw,pg,t,ipp);
krw = exp(10.0*log(sw));
1811,14 → 1987,12
if((ri == 2) && (ci == 2))
k = get_ktt1(pw,pg,t,ipp);// *scale_t;//scaling
 
//if(Tp->time >= 4.345400e+05)
//fprintf(Outt,"matcond k = %e, ri = %ld, ci = %ld, ipp = %ld\n",k,ri,ci,ipp);
//fflush(Outt);
 
fillm(0.0,d);
d[0][0] = k; d[0][1] = 0.0;
d[1][0] = 0.0; d[1][1] = k;
 
check_math_errel(ipp);
}
 
/**
1907,10 → 2081,6
if((ri == 2) && (ci == 2))
c = get_captt(pw,pg,t,ipp);// *scale_t;//scaling
 
//if(Tp->time >= 4.345400e+05)
//fprintf(Outt,"matcap c = %e, ri = %ld, ci = %ld, ipp = %ld, pw = %e, pg = %e, t = %e\n",c,ri,ci,ipp,pw,pg,t);
//fflush(Outt);
 
check_math_errel(ipp);
}
 
2260,22 → 2430,76
double con_hawf3mat::get_fwu(double pw, double pg, double t, long ipp)
{
double depsv_r,sw,fwu,dsr_depsv,n,sg,rhow,rhogw,alpha;
fwu = 0.0;
switch (model_type){
case artificial3:
case lewis_and_schrefler3:
case lewis_and_schrefler3:{
break;
}
case lewis_and_schrefler3_mefel:{//Lewis and Schrefler's book
if(vol_strain_effect == 1){
n = get_porosity(pw,pg,t,ipp);
n = give_porosity(ipp);
depsv_r = Tm->givenontransq(strain_vol_rate, ipp); //actual rate of volumetric strain from MEFEL
Tm->ip[ipp].eqother[0] = depsv_r;
if (sr_type == mefel_sr){
Tm->ip[ipp].eqother[0] = depsv_r; //this is not necessary
/*
if (sr_type == mefel_sr){
dsr_depsv = Tm->givenontransq(der_saturation_deg_depsv, ipp); //actual derivative of saturation degree with respect to volumetric strain
Tm->ip[ipp].eqother[1] = dsr_depsv;
Tm->ip[ipp].eqother[1] = dsr_depsv; //this is not necessary
}
*/
switch (sr_type){
case lewis_and_schrefler_sr:{//Lewis and Schrefler's book
dsr_depsv = 0.0;
break;
}
case gardner_exponential_sr:{//dependent on saturation degree:
dsr_depsv = 0.0;
break;
}
case potts_log_linear_sr:{//exponential
dsr_depsv = 0.0;
break;
}
case van_genuchten_sr:{//partially saturated medium =Van Genuchten model
dsr_depsv = 0.0;
break;
}
case van_genuchten2_sr:{//partially saturated medium =Van Genuchten model
dsr_depsv = 0.0;
break;
}
case mefel_sr:{//from MEFEL
dsr_depsv = Tm->givenontransq(der_saturation_deg_depsv, ipp); //actual derivative of saturation degree with respect to volumetric strain
break;
}
case table_sr:{//from table
dsr_depsv = 0.0;
break;
}
case masin_sr:{//extended formulation from Brooks and Correy according to Masin
double e=0.0,dpw=0.0,por=0.0;
if(Tm->nontransq != NULL){
por = Tm->givenontransq(porosity, ipp);// from mefel
e = por/(1-por);
}
else{
e = phi0/(1-phi0);
}
dpw = Tm->ip[ipp].av[0]-Tm->ip[ipp].pv[0];
dsr_depsv = masin_ret.dsw_depsv(-pw,-dpw,e,t);//positive value of suction
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
}
}
 
sw = get_sw(pw,pg,t,ipp);
sg = 1.0 - sw;
2285,9 → 2509,7
fwu = -1.0*(sg*rhogw + sw*rhow)*alpha*depsv_r;//volumetric strain effect
if (sr_type == mefel_sr){
fwu = -n*(rhow - rhogw)*dsr_depsv*depsv_r;//volumetric strain effect
}
fwu = fwu - n*(rhow - rhogw)*dsr_depsv*depsv_r;//volumetric strain effect
}
break;
}
2320,17 → 2542,71
switch (model_type){
case artificial3:
case lewis_and_schrefler3:
case lewis_and_schrefler3:{
break;
}
case lewis_and_schrefler3_mefel:{//Lewis and Schrefler's book
if(vol_strain_effect == 1){
n = give_porosity(ipp);
depsv_r = Tm->givenontransq(strain_vol_rate, ipp); //actual rate of volumetric strain from MEFEL
Tm->ip[ipp].eqother[0] = depsv_r; //this is not necessary
if (sr_type == mefel_sr){
/*
if (sr_type == mefel_sr){
dsr_depsv = Tm->givenontransq(der_saturation_deg_depsv, ipp); //actual derivative of saturation degree with respect to volumetric strain
Tm->ip[ipp].eqother[1] = dsr_depsv; //this is not necessary
}
*/
switch (sr_type){
case lewis_and_schrefler_sr:{//Lewis and Schrefler's book
dsr_depsv = 0.0;
break;
}
n = get_porosity(pw,pg,t,ipp);
case gardner_exponential_sr:{//dependent on saturation degree:
dsr_depsv = 0.0;
break;
}
case potts_log_linear_sr:{//exponential
dsr_depsv = 0.0;
break;
}
case van_genuchten_sr:{//partially saturated medium =Van Genuchten model
dsr_depsv = 0.0;
break;
}
case van_genuchten2_sr:{//partially saturated medium =Van Genuchten model
dsr_depsv = 0.0;
break;
}
case mefel_sr:{//from MEFEL
dsr_depsv = Tm->givenontransq(der_saturation_deg_depsv, ipp); //actual derivative of saturation degree with respect to volumetric strain
break;
}
case table_sr:{//from table
dsr_depsv = 0.0;
break;
}
case masin_sr:{//extended formulation from Brooks and Correy according to Masin
double e=0.0,dpw=0.0,por=0.0;
if(Tm->nontransq != NULL){
por = Tm->givenontransq(porosity, ipp);// from mefel
e = por/(1-por);
}
else{
e = phi0/(1-phi0);
}
dpw = Tm->ip[ipp].av[0]-Tm->ip[ipp].pv[0];
dsr_depsv = masin_ret.dsw_depsv(-pw,-dpw,e,t);//positive value of suction
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
}
}
 
sw = get_sw(pw,pg,t,ipp);
sg = 1.0 - sw;
rhoga = get_rhoga(pw,pg,t);
2337,9 → 2613,7
alpha = get_alpha(pw,pg,t,ipp);
fgu = -alpha*sg*rhoga*depsv_r;
if (sr_type == mefel_sr){
fgu = fgu + n*rhoga*dsr_depsv*depsv_r;//volumetric strain rate effect
}
fgu = fgu + n*rhoga*dsr_depsv*depsv_r;//volumetric strain rate effect
}
break;
}
2370,17 → 2644,74
ftu = 0.0;
switch (model_type){
case artificial3:
case lewis_and_schrefler3:
case lewis_and_schrefler3:{
break;
}
case lewis_and_schrefler3_mefel:{//Lewis and Schrefler's book
if(vol_strain_effect == 1){
n = give_porosity(ipp);
depsv_r = Tm->givenontransq(strain_vol_rate, ipp); //actual rate of volumetric strain from MEFEL
if (sr_type == mefel_sr){
Tm->ip[ipp].eqother[0] = depsv_r; //this is not necessary
/*
if (sr_type == mefel_sr){
dsr_depsv = Tm->givenontransq(der_saturation_deg_depsv, ipp); //actual derivative of saturation degree with respect to volumetric strain
Tm->ip[ipp].eqother[1] = dsr_depsv; //this is not necessary
}
*/
switch (sr_type){
case lewis_and_schrefler_sr:{//Lewis and Schrefler's book
dsr_depsv = 0.0;
break;
}
n = get_porosity(pw,pg,t,ipp);
case gardner_exponential_sr:{//dependent on saturation degree:
dsr_depsv = 0.0;
break;
}
case potts_log_linear_sr:{//exponential
dsr_depsv = 0.0;
break;
}
case van_genuchten_sr:{//partially saturated medium =Van Genuchten model
dsr_depsv = 0.0;
break;
}
case van_genuchten2_sr:{//partially saturated medium =Van Genuchten model
dsr_depsv = 0.0;
break;
}
case mefel_sr:{//from MEFEL
dsr_depsv = Tm->givenontransq(der_saturation_deg_depsv, ipp); //actual derivative of saturation degree with respect to volumetric strain
break;
}
case table_sr:{//from table
dsr_depsv = 0.0;
break;
}
case masin_sr:{//extended formulation from Brooks and Correy according to Masin
double e=0.0,dpw=0.0,por=0.0;
if(Tm->nontransq != NULL){
por = Tm->givenontransq(porosity, ipp);// from mefel
e = por/(1-por);
}
else{
e = phi0/(1-phi0);
}
dpw = Tm->ip[ipp].av[0]-Tm->ip[ipp].pv[0];
dsr_depsv = masin_ret.dsw_depsv(-pw,-dpw,e,t);//positive value of suction
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
}
}
 
sw = get_sw(pw,pg,t,ipp);
rhow = get_rhow(t);
dhvap = get_dhvap(t);
2388,9 → 2719,7
ftu = dhvap*sw*rhow*alpha*depsv_r;
if (sr_type == mefel_sr){
ftu = ftu + dhvap*rhow*n*dsr_depsv*depsv_r;//volumetric strain rate effect
}
ftu = ftu + dhvap*rhow*n*dsr_depsv*depsv_r;//volumetric strain rate effect
}
break;
}
4162,7 → 4491,6
 
/**
This function initializes material model data
with respect of consistency parameter gamma.
 
@param ipp - integration point number
 
4218,6 → 4546,53
 
 
/**
function returns effective pore pressure (pressure has negative sign - mechanical convention)
 
@param ipp - integration point number
 
@retval pw - pore water pressure
*/
double con_hawf3mat::give_effective_pore_pressure(long ipp)
{
double ps,pw,pg,t,xi=1.0;
 
pw = Tm->ip[ipp].av[0];
pg = Tm->ip[ipp].av[1];
t = Tm->ip[ipp].av[2];
 
 
//needs to be corrected??!!
switch (model_type){
case lewis_and_schrefler3:{//Lewis and Schrefler's book
xi = get_xi(pw,pg,t,ipp);//effective stress factor
 
pg = pg - p0;//pore gas pressure without atmospheric pressure
ps = xi*pw + (1.0 - xi)*pg;
ps = -ps;//returns effective pore pressure
break;
}
case lewis_and_schrefler3_mefel:{//Lewis and Schrefler's book, saturation degree ind its derivative are obtained from mefel;
 
xi = get_xi(pw,pg,t,ipp); //effective stress factor
 
pg = pg - p0;//pore gas pressure without atmospheric pressure
ps = xi*pw + (1.0 - xi)*pg;
ps = -ps/mefel_units;//returns effective pore pressure //corrected units for mefel //basic units = Pa
//debug???!!!
//pw = -pw/mefel_units;//returns effective pore pressure //corrected units for mefel //basic units = Pa
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
}
}
return(ps);
}
 
 
/**
function returns water pressure
 
@param ipp - integration point number
4431,21 → 4806,18
case lewis_and_schrefler3:{//Lewis and Schrefler's book
break;
}
case van_genuchten3:{//partially saturated medium = Van Genuchten model
break;
}
case lewis_and_schrefler3_mefel:{//Lewis and Schrefler's book, saturation degree ind its derivative are obtained from mefel;
antq[saturation_deg-1] = 1;
antq[der_saturation_deg-1] = 1;
antq[der_saturation_deg_depsv-1] = 1;
antq[porosity-1] = 1;
antq[der_saturation_deg_dtemp-1] = 1;
antq[strain_vol_rate-1] = 1;
if (sr_type == mefel_sr){
antq[saturation_deg-1] = 1;
antq[der_saturation_deg-1] = 1;
antq[der_saturation_deg_depsv-1] = 1;
antq[der_saturation_deg_dtemp-1] = 1;
}
if(vol_strain_effect == 1)
antq[strain_vol_rate-1] = 1;
break;
}
case lewis_and_schrefler3_2:{//Lewis and Schrefler's book p. 381
break;
}
default:{
print_err("unknown model type is required", __FILE__, __LINE__, __func__);
}
/trunk/SIFEL/TRFEL/SRC/consol_hawf3.h
7,6 → 7,7
#include "bazant_reten.h"
#include "lewis_schrefler.h"
#include "van_genuchten.h"
#include "masin_reten.h"
 
class con_hawf3mat
{
22,6 → 23,7
double get_rhos(double t);
double get_cdiff(double pw,double pg,double t);
double get_dg(double pc,double pg,double t,long ipp);
double get_xi(double pw, double pg, double t, long ipp);
double get_sw(double pw, double pg, double t, long ipp);
double get_ds_dpc(double pw, double pg, double t, long ipp);
double get_ds_dt(double pw, double pg, double t, long ipp);
148,6 → 150,7
double give_temperature(long ipp);
double give_water_pressure(long ipp);
double give_gas_pressure(long ipp);
double give_effective_pore_pressure(long ipp);
double give_pore_pressure(long ipp);
double give_suction(long ipp);
double give_saturation_degree(long ipp);
164,7 → 167,8
lewis_reten lewis_ret;
/// van Genuchten's retention curve:
van_genuchten_reten van_genuchten_ret;
/// Masin's retention curve for bentonite
masin_reten masin_ret;
/// general function for retention curve given by set of data
gfunct data;
 
172,7 → 176,7
heatairwaterflowtype model_type;
int compress;
int vol_strain_effect,kintr_type,krw_type,krg_type,sr_type,lambda_type,cps_type,betas_type,deff_type;
int vol_strain_effect,por_type,kintr_type,krw_type,krg_type,sr_type,xi_type,lambda_type,cps_type,betas_type,deff_type;
double ma;//molar mass of dry air
double mw;//molar mass of water
double gasr;//universal gas constant
234,12 → 238,13
double pw_bc;
double scale_pw,scale_pg,scale_t;
int rel_gas_press; //relative gas pressure according to ambient air; yes=1=relative pg, no=0=absolute pg
double sirr,ssat,lambda_krw;
double sirr,ssat,lambda_krw,beta_krw;
double bb1,phi01; //permeability parameters
 
//parameters for the arificial material:
double kww0,kwg0,kwt0,kgw0,kgg0,kgt0,ktw0,ktg0,ktt0;
double capww0,capwg0,capwt0,capgw0,capgg0,capgt0,captw0,captg0,captt0;
double gamma;
};
 
#endif
/trunk/SIFEL/TRFEL/SRC/consol_hwf2.cpp
31,6 → 31,7
kintr_type = 0; //intrinsic permability calculation type
krw_type = 0; //relative permeability calculation type
sr_type = 1; //retention curve calculation type
xi_type = 1; //effective stress parameter type
lambda_type =0; //heat conduction calculation type
cps_type = 0; //specific heat calculation type
betas_type = 0; //thermal expansion calculation type
52,8 → 53,11
lambda_wet = 0.0;
sr_dry = 0.0;
sr_wet = 0.0;
 
sirr = 0.0;
ssat = 1.0;
lambda_krw = 1.9; //parameter for exponential function of relative permeability
beta_krw = 0.0; //parameter for power function of relative permeability
 
bb1 = 0.0;
phi01 = 0.0;
85,7 → 89,7
xfscanf (in,"%d", &compress);
 
// common material parameters
xfscanf (in,"%le %le %le %le %le %le %d %d %d %d %d %d", &alpha0, &ks0, &phi0, &rhos0, &pw_bc, &kintr0, &kintr_type, &krw_type, &sr_type, &lambda_type, &cps_type, &betas_type);
xfscanf (in,"%le %le %le %le %le %d %d %d %d %d %d %d %d", &alpha0, &ks0, &rhos0, &pw_bc, &kintr0, &por_type, &kintr_type, &krw_type, &sr_type, &xi_type, &lambda_type, &cps_type, &betas_type);
 
switch (model_type){
case lewis_and_schrefler2hw:{//Lewis and Schrefler's model
101,6 → 105,23
}
}
 
 
//porosity calculation:
switch (por_type){
case 0:{//constant
xfscanf (in,"%le",&phi0);
break;
}
case 1:{//dependent on mefel calculation
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
}
}
 
 
//intrinsic permebility calculation:
switch (kintr_type){
case 0:{//constant
110,6 → 131,10
xfscanf (in,"%le %le", &bb1, &phi01);
break;
}
case 2:{//dependent on porosity - cubic and quadratic
xfscanf (in,"%le", &phi01);
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
130,6 → 155,14
xfscanf (in,"%le", &lambda_krw);
break;
}
case 4:{//liakopoulos
break;
}
case 5:{//double exponential
xfscanf (in,"%le %le", &sirr, &ssat);
xfscanf (in,"%le", &beta_krw);
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
158,6 → 191,10
data.read (in);
break;
}
case masin_sr:{//extended formulation from Brooks and Correy according to Masin
masin_ret.read(in);
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
333,7 → 370,49
}
 
 
 
/**
function computes effective stress factor xi
@param pw - water pressure
@param t - temperature
 
@retval xi - factor xi
 
03/04/2023, TKr
*/
double con_hwf2mat::get_xi(double pw, double t, long ipp)
{
double xi=0.0;
switch (xi_type){
case biot_xi:
xi = get_sw(pw,t,ipp);
break;
case masin_xi:{
double e=0.0,dpw=0.0,por=0.0;
if(Tm->nontransq != NULL){
por = Tm->givenontransq(porosity, ipp);// from mefel
e = por/(1-por);
}
else{
e = phi0/(1-phi0);
}
dpw = Tm->ip[ipp].av[0]-Tm->ip[ipp].pv[0];
xi = masin_ret.psi(-pw,-dpw,e,t);//positive value of suction
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
}
}
return(xi);
}
 
 
 
/**
function computes degree of saturation(sorption curve)
@param pw - water pressure
@param t - temperature
388,6 → 467,20
//sw = van_genuchten_ret.sw2(pw);
break;
}
case masin_sr:{//extended formulation from Brooks and Correy according to Masin
double e=0.0,dpw=0.0,por=0.0;
if(Tm->nontransq != NULL){
por = Tm->givenontransq(porosity, ipp);// from mefel
e = por/(1-por);
}
else{
e = phi0/(1-phi0);
}
 
dpw = Tm->ip[ipp].av[0]-Tm->ip[ipp].pv[0];
sw = masin_ret.sw(-pw,-dpw,e,t);//positive value of suction
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
445,6 → 538,20
//dsw_dpw = van_genuchten_ret.dsw_dpw2(pw);
break;
}
case masin_sr:{//extended formulation from Brooks and Correy according to Masin
double e=0.0,dpw=0.0,por=0.0;
if(Tm->nontransq != NULL){
por = Tm->givenontransq(porosity, ipp);// from mefel
e = por/(1-por);
}
else{
e = phi0/(1-phi0);
}
dpw = Tm->ip[ipp].av[0]-Tm->ip[ipp].pv[0];
dsw_dpw = -masin_ret.dsw_dpw(-pw,-dpw,e,t);//positive value of suction
//dsw_dpw = dsw_dpw/mefel_units; //basic units = Pa
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
502,6 → 609,19
//dsw_dt = van_genuchten_ret.dsw_dt2(pw);
break;
}
case masin_sr:{//extended formulation from Brooks and Correy according to Masin
double e=0.0,dpw=0.0,por=0.0;
if(Tm->nontransq != NULL){
por = Tm->givenontransq(porosity, ipp);// from mefel
e = por/(1-por);
}
else{
e = phi0/(1-phi0);
}
dpw = Tm->ip[ipp].av[0]-Tm->ip[ipp].pv[0];
dsw_dt = masin_ret.dsw_dt(-pw,-dpw,e,t);//positive value of suction
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
535,6 → 655,11
kintr = kintr0*exp(bb1*(phi - phi01));
break;
}
case 2:{//dependent on porosity - cubic and quadratic
phi = give_porosity(ipp);
kintr = kintr0*phi*phi*phi/(1 - phi01)*(1 - phi01)*(1 - phi)*(1 - phi)/(phi01*phi01*phi01);
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
555,7 → 680,7
*/
double con_hwf2mat::get_krw(double pw, double t, long ipp)
{
double sw,krw;
double sw,krw,sef=0.0;
switch (krw_type){
case 0:{//constant
582,6 → 707,15
krw = 1.0-2.207*pow((1.0-sw),1.0121);
break;
}
case 5:{//double exponential
sw = get_sw(pw,t,ipp);
sef = (sw-sirr)/(ssat-sirr); //effective saturation degree
krw = pow(sef,(1.0/beta_krw));
krw = pow((1.0-krw),beta_krw);
krw = pow((1.0-krw),2.0);
krw = pow(sef,0.5)*krw;
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
592,7 → 726,42
}
 
 
/**
function returns porosity
 
@retval phi - porosity
 
03/04/2023, TKr
*/
double con_hwf2mat::give_porosity(long ipp)
{
double por;
//porosity calculation:
switch (por_type){
case 0:{//constant
por = phi0;
break;
}
case 1:{//dependent on mefel calculation
if(Tm->nontransq != NULL){
por = Tm->givenontransq(porosity, ipp);// from mefel
}
else
por = phi0;//for testing
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
}
}
return(por);
}
 
 
 
/**
function computes Biot's constant
@param pw - pore water pressure
805,6 → 974,7
break;
}
case 3:{//
sw = get_sw(pw,t,ipp);
lambdaeff = pow(lambda_wet,sw)*pow(lambda_dry,(1-sw)); //this is from Patek's thesis p. 18, but it seems to be strange
break;
}
1773,25 → 1943,78
fwu = 0.0;
switch (model_type){
case lewis_and_schrefler2hw:{
case lewis_and_schrefler:{
break;
}
case lewis_and_schrefler2hw_mefel:{//Lewis and Schrefler's book
case lewis_and_schrefler_mefel:{//Lewis and Schrefler's book
if(vol_strain_effect == 1){
n = get_porosity(pw,t,ipp);
n = give_porosity(ipp);
depsv_r = Tm->givenontransq(strain_vol_rate, ipp); //actual rate of volumetric strain from MEFEL
Tm->ip[ipp].eqother[0] = depsv_r; //this is not necessary
if (sr_type == mefel_sr){
/*
if (sr_type == mefel_sr){
dsr_depsv = Tm->givenontransq(der_saturation_deg_depsv, ipp); //actual derivative of saturation degree with respect to volumetric strain
Tm->ip[ipp].eqother[1] = dsr_depsv; //this is not necessary
}
*/
switch (sr_type){
case lewis_and_schrefler_sr:{//Lewis and Schrefler's book
dsr_depsv = 0.0;
break;
}
case gardner_exponential_sr:{//dependent on saturation degree:
dsr_depsv = 0.0;
break;
}
case potts_log_linear_sr:{//exponential
dsr_depsv = 0.0;
break;
}
case van_genuchten_sr:{//partially saturated medium =Van Genuchten model
dsr_depsv = 0.0;
break;
}
case van_genuchten2_sr:{//partially saturated medium =Van Genuchten model
dsr_depsv = 0.0;
break;
}
case mefel_sr:{//from MEFEL
dsr_depsv = Tm->givenontransq(der_saturation_deg_depsv, ipp); //actual derivative of saturation degree with respect to volumetric strain
break;
}
case table_sr:{//from table
dsr_depsv = 0.0;
break;
}
case masin_sr:{//extended formulation from Brooks and Correy according to Masin
double e=0.0,dpw=0.0,por=0.0;
if(Tm->nontransq != NULL){
por = Tm->givenontransq(porosity, ipp);// from mefel
e = por/(1-por);
}
else{
e = phi0/(1-phi0);
}
dpw = Tm->ip[ipp].av[0]-Tm->ip[ipp].pv[0];
dsr_depsv = masin_ret.dsw_depsv(-pw,-dpw,e,t);//positive value of suction
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
}
}
 
Tm->ip[ipp].eqother[1] = dsr_depsv; //this is not necessary
 
sw = get_sw(pw,t,ipp);
rhow = get_rhow(t);
alpha = get_alpha(pw,t,ipp);
fwu = -alpha*sw*rhow*depsv_r;//volumetric strain effect
if (sr_type == mefel_sr){
fwu = fwu - n*rhow*dsr_depsv*depsv_r;//volumetric strain effect on retention curve
}
fwu = fwu - n*rhow*dsr_depsv*depsv_r;//volumetric strain effect on retention curve
}
break;
}
2253,6 → 2476,61
 
 
/**
function returns effective pore pressure (pressure has negative sign - mechanical convention)
 
@param ipp - integration point number
 
@retval pw - pore water pressure
*/
double con_hwf2mat::give_effective_pore_pressure(long ipp)
{
double pw,t,xi=1.0;
 
switch (model_type){
case lewis_and_schrefler:{//Lewis and Schrefler's book
pw = Tm->ip[ipp].av[0];
t = Tm->ip[ipp].av[1];
xi = get_xi(pw,t,ipp);
pw = -xi*pw;//returns effective pore pressure
break;
}
case lewis_and_schrefler_mefel:{//Lewis and Schrefler's book, saturation degree ind its derivative are obtained from mefel;
 
//debug??!!
/* double chi,sw,gama,lambdap,se;
pw = Tm->ip[ipp].av[0];
sw = get_sw(pw,ipp);
//lambdap = 0.2;
gama = 0.55;
se = -2700.0e3;
//chi = pow(sw,(gama/lambdap));
if(pw > se)
chi = 1.0;
else
chi = pow((se/pw),gama);
sw = (1-gama)*chi;
pw = -sw*pw/mefel_units;//returns effective pore pressure //corrected units for mefel //basic units = Pa
*/
pw = Tm->ip[ipp].av[0];
t = Tm->ip[ipp].av[1];
xi = get_xi(pw,t,ipp); //effective stress factor
pw = -xi*pw/mefel_units;//returns effective pore pressure //corrected units for mefel //basic units = Pa
//debug???!!!
//pw = -pw/mefel_units;//returns effective pore pressure //corrected units for mefel //basic units = Pa
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
}
}
return(pw);
}
 
 
/**
function returns water pressure
 
@param ipp - integration point number
2459,19 → 2737,20
break;
}
case lewis_and_schrefler2hw_mefel:{//Lewis and Schrefler's book, saturation degree ind its derivative are obtained from mefel;
antq[saturation_deg-1] = 1;
antq[der_saturation_deg-1] = 1;
antq[der_saturation_deg_depsv-1] = 1;
antq[porosity-1] = 1;
antq[der_saturation_deg_dtemp-1] = 1;
antq[strain_vol_rate-1] = 1;
if (sr_type == mefel_sr){
antq[saturation_deg-1] = 1;
antq[der_saturation_deg-1] = 1;
antq[der_saturation_deg_depsv-1] = 1;
antq[der_saturation_deg_dtemp-1] = 1;
}
if(vol_strain_effect == 1)
antq[strain_vol_rate-1] = 1;
break;
}
case van_genuchten2hw:{//partially saturated medium = Van Genuchten model
break;
}
default:{
print_err("unknown model type is required", __FILE__, __LINE__, __func__);
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
}
}
}
/trunk/SIFEL/TRFEL/SRC/consol_hwf2.h
7,6 → 7,7
#include "gardner.h"
#include "potts.h"
#include "van_genuchten.h"
#include "masin_reten.h"
 
class con_hwf2mat
{
19,11 → 20,13
double get_betas(long ipp);
double get_cps(double pw, double t, long ipp);
double get_rhos(double t);
double get_xi(double pw, double t, long ipp);
double get_sw(double pw, double t, long ipp);
double get_dsw_dpw(double pw, double t, long ipp);
double get_dsw_dt(double pw, double t, long ipp);
double get_kintr(double pw, double t, long ipp);
double get_krw(double pw, double t, long ipp);
double give_porosity(long ipp);
 
double get_alpha(double pw, double t,long ipp);
double get_porosity(double pw,double t,long ipp);
103,6 → 106,7
 
double give_temperature(long ipp);
double give_water_pressure(long ipp);
double give_effective_pore_pressure(long ipp);
double give_pore_pressure(long ipp);
double give_suction(long ipp);
double give_saturation_degree(long ipp);
120,7 → 124,8
potts_reten potts_ret;
/// van Genuchten's retention curve:
van_genuchten_reten van_genuchten_ret;
/// Masin's retention curve for bentonite
masin_reten masin_ret;
/// general function for retention curve given by set of data
gfunct data;
 
128,7 → 133,7
heatwaterflowtype model_type;
int compress;
int vol_strain_effect,kintr_type,krw_type,sr_type,lambda_type,cps_type,betas_type;
int vol_strain_effect,por_type,kintr_type,krw_type,sr_type,xi_type,lambda_type,cps_type,betas_type;
 
double alpha0; //initial Boit's constant
double ks0; //inital bulk modulus of solid phase
152,7 → 157,7
 
double pw_bc;
double mefel_units; //basic units for pressures = Pa (Pascals)
double sirr,ssat,lambda_krw;
double sirr,ssat,lambda_krw,beta_krw;
double bb1,phi01; //permeability parameters
 
};
/trunk/SIFEL/TRFEL/SRC/consol_wf1.cpp
22,6 → 22,7
krw_type = 0; //relative permeability calculation type
kintr_type = 0; //intrinsic permability calculation type
sr_type = 1; //retention curve calculation type
xi_type = 1; //effective stress parameter type
 
mefel_units = 1.0; //basic units for pressures = Pa (Pascals) in MEFEL part
vol_strain_effect = 0; //volumetric strain rate influence: 0=no; 1=yes
40,9 → 41,14
sirr = 0.0; //lower saturation degree
ssat = 1.0; //fully saturation degree
lambda_krw = 1.9; //parameter for exponential function of relative permeability
beta_krw = 0.0; //parameter for power function of relative permeability
 
b1 = 9.91; //material parameter of the intrinsic permeability
phi01 = 0.047; //reference porosity associated with kintr0
 
gamma = 0.0;
lambda0 = 0.0;
s_entry = 0.0;
}
 
con_wf1mat::~con_wf1mat()
166,6 → 172,11
pw = Tm->ip[ipp].av[0];
cc = get_capww(pw,ipp);
 
//fprintf (Outt,"cc = %lf pw = %e ipp = %ld\n",cc,pw,ipp);
//fflush(Outt);
 
check_math_errel(Tm->elip[ipp]);
}
 
/**
181,7 → 192,7
xfscanf (in,"%k%m","waterflowtype",&waterflowtype_kwdset, &model_type); //water flow model type
xfscanf (in,"%d", &compress); //compressibility of grains
// common material parameters
xfscanf (in,"%le %le %le %le %le %d %d %d %d", &alpha, &ks, &rhos0, &pw_bc, &kintr0, &por_type, &kintr_type, &krw_type, &sr_type);
xfscanf (in,"%le %le %le %le %le %d %d %d %d %d", &alpha, &ks, &rhos0, &pw_bc, &kintr0, &por_type, &kintr_type, &krw_type, &sr_type, &xi_type);
 
switch (model_type){
case lewis_and_schrefler:{//Lewis and Schrefler's model approach
222,6 → 233,10
xfscanf (in,"%le %le", &b1, &phi01);
break;
}
case 2:{//dependent on porosity - cubic and quadratic
xfscanf (in,"%le", &phi01);
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
245,6 → 260,11
case 4:{//liakopoulos
break;
}
case 5:{//double exponential
xfscanf (in,"%le %le", &sirr, &ssat);
xfscanf (in,"%le", &beta_krw);
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
281,6 → 301,10
data.read (in);
break;
}
case masin_sr:{//extended formulation from Brooks and Correy according to Masin
masin_ret.read(in);
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
287,6 → 311,26
}
}
 
switch (xi_type){
case biot_xi:
break;
case biot_reduced_xi:{//coefficient for effective stress factor reduction
xfscanf (in,"%le %le", &gamma,&lambda0);
break;
}
case biot_masin_xi:{
xfscanf (in,"%le %le", &gamma,&s_entry);
break;
}
case masin_xi:
break;
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
}
}
 
}
 
 
471,6 → 515,66
 
 
/**
function computes effective stress factor xi
@param pw - water pressure
 
@retval xi - factor xi
 
15/03/2023, TKr
*/
double con_wf1mat::get_xi(double pw, long ipp)
{
double suc=0.0,sr=0.0,xi=0.0,temp=294.0;
switch (xi_type){
case biot_xi:
xi = get_sw(pw,ipp);
break;
case biot_reduced_xi:
//xi = gamma*get_sw(pw,ipp);
sr = get_sw(pw,ipp);
//xi = pow(sr,(gamma/lambda0));
xi = pow(sr,gamma);
xi = (1-gamma)*xi;
break;
case biot_masin_xi:{//according to masin for testing
sr = get_sw(pw,ipp);
suc = -pw;
if (suc>=s_entry)
xi = pow((s_entry/suc),gamma);
else
xi = 1.0;
if (suc>=s_entry)
xi = (1-gamma)*xi;
else
xi = 1.0;
break;
}
case masin_xi:{
double e=0.0,dpw=0.0,por=0.0;
if(Tm->nontransq != NULL){
por = Tm->givenontransq(porosity, ipp);// from mefel
e = por/(1-por);
}
else{
e = phi0/(1-phi0);
}
dpw = Tm->ip[ipp].av[0]-Tm->ip[ipp].pv[0];
xi = masin_ret.psi(-pw,-dpw,e,temp);//positive value of suction
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
}
}
return(xi);
}
 
 
 
/**
function computes degree of saturation(sorption curve)
@param pw - water pressure
 
480,7 → 584,7
*/
double con_wf1mat::get_sw(double pw, long ipp)
{
double sw;
double sw,temp=294.0;
sw = 0.0;
switch (sr_type){
524,6 → 628,20
//sw = van_genuchten_ret.sw2(pw);
break;
}
case masin_sr:{//extended formulation from Brooks and Correy according to Masin
double e=0.0,dpw=0.0,por=0.0;
if(Tm->nontransq != NULL){
por = Tm->givenontransq(porosity, ipp);// from mefel
e = por/(1-por);
}
else{
e = phi0/(1-phi0);
}
 
dpw = Tm->ip[ipp].av[0]-Tm->ip[ipp].pv[0];
sw = masin_ret.sw(-pw,-dpw,e,temp);//positive value of suction
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
543,7 → 661,7
*/
double con_wf1mat::get_dsw_dpw(double pw, long ipp)
{
double dsw_dpw;
double dsw_dpw,temp=294.0;
dsw_dpw = 0.0;
 
switch (sr_type){
578,11 → 696,28
//dsw_dpw = van_genuchten_ret.dsw_dpw2(pw);
break;
}
case masin_sr:{//extended formulation from Brooks and Correy according to Masin
double e=0.0,dpw=0.0,por=0.0;
if(Tm->nontransq != NULL){
por = Tm->givenontransq(porosity, ipp);// from mefel
e = por/(1-por);
}
else{
e = phi0/(1-phi0);
}
dpw = Tm->ip[ipp].av[0]-Tm->ip[ipp].pv[0];
dsw_dpw = -masin_ret.dsw_dpw(-pw,-dpw,e,temp);//positive value of suction
//dsw_dpw = dsw_dpw/mefel_units; //basic units = Pa
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
}
}
 
check_math_errel(Tm->elip[ipp]);
 
return(dsw_dpw);
}
 
597,7 → 732,7
*/
double con_wf1mat::get_krw(double pw, long ipp)
{
double sw,krw;
double sw,krw,sef=0.0;
switch (krw_type){
case 0:{//constant
617,6 → 752,8
case 3:{//exponential
sw = get_sw(pw,ipp);
krw = pow(sw,lambda_krw);
//sef = (sw-sirr)/(ssat-sirr); //effective saturaion degree
//krw = pow(sef,lambda_krw);
break;
}
case 4:{//liakopoulos
624,6 → 761,15
krw = 1.0-2.207*pow((1.0-sw),1.0121);
break;
}
case 5:{//double exponential
sw = get_sw(pw,ipp);
sef = (sw-sirr)/(ssat-sirr); //effective saturation degree
krw = pow(sef,(1.0/beta_krw));
krw = pow((1.0-krw),beta_krw);
krw = pow((1.0-krw),2.0);
krw = pow(sef,0.5)*krw;
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
689,6 → 835,11
kintr = kintr0*exp(b1*(phi - phi01));
break;
}
case 2:{//dependent on porosity - cubic and quadratic
phi = give_porosity(ipp);
kintr = kintr0*phi*phi*phi/(1 - phi01)*(1 - phi01)*(1 - phi)*(1 - phi)/(phi01*phi01*phi01);
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
813,7 → 964,7
*/
double con_wf1mat::get_fwu(double pw, long ipp)
{
double sw,fwu,depsv_r, dsr_depsv,n;
double sw,fwu,depsv_r=0.0,dsr_depsv=0.0,n,temp=294.0;
fwu = 0.0;
826,16 → 977,70
n = give_porosity(ipp);
depsv_r = Tm->givenontransq(strain_vol_rate, ipp); //actual rate of volumetric strain from MEFEL
Tm->ip[ipp].eqother[0] = depsv_r; //this is not necessary
if (sr_type == mefel_sr){
/*
if (sr_type == mefel_sr){
dsr_depsv = Tm->givenontransq(der_saturation_deg_depsv, ipp); //actual derivative of saturation degree with respect to volumetric strain
Tm->ip[ipp].eqother[1] = dsr_depsv; //this is not necessary
}
*/
switch (sr_type){
case lewis_and_schrefler_sr:{//Lewis and Schrefler's book
dsr_depsv = 0.0;
break;
}
case gardner_exponential_sr:{//dependent on saturation degree:
dsr_depsv = 0.0;
break;
}
case potts_log_linear_sr:{//exponential
dsr_depsv = 0.0;
break;
}
case van_genuchten_sr:{//partially saturated medium =Van Genuchten model
dsr_depsv = 0.0;
break;
}
case van_genuchten2_sr:{//partially saturated medium =Van Genuchten model
dsr_depsv = 0.0;
break;
}
case mefel_sr:{//from MEFEL
dsr_depsv = Tm->givenontransq(der_saturation_deg_depsv, ipp); //actual derivative of saturation degree with respect to volumetric strain
break;
}
case table_sr:{//from table
dsr_depsv = 0.0;
break;
}
case masin_sr:{//extended formulation from Brooks and Correy according to Masin
double e=0.0,dpw=0.0,por=0.0;
if(Tm->nontransq != NULL){
por = Tm->givenontransq(porosity, ipp);// from mefel
e = por/(1-por);
}
else{
e = phi0/(1-phi0);
}
dpw = Tm->ip[ipp].av[0]-Tm->ip[ipp].pv[0];
dsr_depsv = masin_ret.dsw_depsv(-pw,-dpw,e,temp);//positive value of suction
break;
}
default:{
print_err ("unknown model type is required", __FILE__, __LINE__, __func__);
abort();
}
}
 
Tm->ip[ipp].eqother[1] = dsr_depsv; //this is not necessary
 
sw = get_sw(pw,ipp);
fwu = -alpha*sw*depsv_r;//volumetric strain effect
if (sr_type == mefel_sr){
fwu = fwu -n*dsr_depsv*depsv_r;//volumetric strain effect on retention curve
}
//if (sr_type == mefel_sr){
fwu = fwu - n*dsr_depsv*depsv_r;//volumetric strain effect on retention curve
//}
}
break;
}
1310,19 → 1515,39
*/
double con_wf1mat::give_effective_pore_pressure(long ipp)
{
double pw,sw=1.0;
double pw,xi=1.0;
 
switch (model_type){
case lewis_and_schrefler:{//Lewis and Schrefler's book
pw = Tm->ip[ipp].av[0];
sw = get_sw(pw,ipp);
pw = -sw*pw;//returns effective pore pressure
xi = get_xi(pw,ipp);
pw = -xi*pw;//returns effective pore pressure
break;
}
case lewis_and_schrefler_mefel:{//Lewis and Schrefler's book, saturation degree ind its derivative are obtained from mefel;
 
//debug??!!
/* double chi,sw,gama,lambdap,se;
pw = Tm->ip[ipp].av[0];
sw = get_sw(pw,ipp);
//lambdap = 0.2;
gama = 0.55;
se = -2700.0e3;
//chi = pow(sw,(gama/lambdap));
if(pw > se)
chi = 1.0;
else
chi = pow((se/pw),gama);
sw = (1-gama)*chi;
pw = -sw*pw/mefel_units;//returns effective pore pressure //corrected units for mefel //basic units = Pa
*/
pw = Tm->ip[ipp].av[0];
sw = get_sw(pw,ipp);
pw = -sw*pw/mefel_units;//returns effective pore pressure //corrected units for mefel //basic units = Pa
xi = get_xi(pw,ipp); //effective stress factor
pw = -xi*pw/mefel_units;//returns effective pore pressure //corrected units for mefel //basic units = Pa
//debug???!!!
//pw = -pw/mefel_units;//returns effective pore pressure //corrected units for mefel //basic units = Pa
break;
}
default:{
/trunk/SIFEL/TRFEL/SRC/consol_wf1.h
7,8 → 7,8
#include "gardner.h"
#include "potts.h"
#include "van_genuchten.h"
#include "masin_reten.h"
 
 
/**
This class defines model for water flow in soils.
*/
35,6 → 35,7
void rhs2d1 (matrix &d,long ri,long ci,long ipp);
void rhs3d1 (matrix &d,long ri,long ci,long ipp);
 
double get_xi(double pw, long ipp);
double get_sw(double pw, long ipp);
double get_dsw_dpw(double pw, long ipp);
double get_krw(double pw, long ipp);
91,7 → 92,8
potts_reten potts_ret;
/// van Genuchten's retention curve:
van_genuchten_reten van_genuchten_ret;
/// Masin's retention curve for bentonite
masin_reten masin_ret;
/// general function for retention curve given by set of data
gfunct data;
 
99,14 → 101,15
waterflowtype model_type;
int compress;
int vol_strain_effect,por_type,kintr_type,krw_type,sr_type;
int vol_strain_effect,por_type,kintr_type,krw_type,sr_type,xi_type;
double mefel_units; //basic units for pressures = Pa (Pascals)
double alpha,phi0,ks;
double kw,rhow0,muw0;
double kintr0,rhos0;
double sirr,ssat,lambda_krw;
double sirr,ssat,lambda_krw,beta_krw;
double b1,phi01;
double pw_bc;
double gamma,lambda0,s_entry;
};
 
#endif
/trunk/SIFEL/TRFEL/SRC/elementt.cpp
82,7 → 82,8
get=linbar;
if (Lbt==NULL)
Lbt = new linbart;
Tp->gdim=1;
if (Tp->gdim < 1)
Tp->gdim=1;
break;
}
case barlint3d:{
89,7 → 90,8
get=linbar;
if (Lbt3d==NULL)
Lbt3d = new linbart3d;
Tp->gdim=1;
if (Tp->gdim < 1)
Tp->gdim=1;
break;
}
case barlintax:{
96,7 → 98,8
get=linbar;
if (Lbt==NULL)
Lbat = new linbartax;
Tp->gdim=1;
if (Tp->gdim < 1)
Tp->gdim=1;
break;
}
case barquadt:{
103,7 → 106,8
get=quadbar;
if (Qbt==NULL)
Qbt = new quadbart;
Tp->gdim=1;
if (Tp->gdim < 1)
Tp->gdim=1;
break;
}
case barquadtax:{
110,7 → 114,8
get=quadbar;
if (Qbat==NULL)
Qbat = new quadbartax;
Tp->gdim=1;
if (Tp->gdim < 1)
Tp->gdim=1;
break;
}
case trlint:{
117,7 → 122,8
get=lintriag;
if (Ltt==NULL)
Ltt = new trlineart;
Tp->gdim=2;
if (Tp->gdim < 2)
Tp->gdim=2;
break;
}
case trlaxisym:{
124,7 → 130,8
get=lintriag;
if (Ltat==NULL)
Ltat = new trlinaxisym;
Tp->gdim=2;
if (Tp->gdim < 2)
Tp->gdim=2;
break;
}
case quadlint:{
131,7 → 138,8
get=linquad;
if (Lqt==NULL)
Lqt = new quadlineart;
Tp->gdim=2;
if (Tp->gdim < 2)
Tp->gdim=2;
break;
}
case quadquadt:{
138,7 → 146,8
get=quadquad;
if (Qqt==NULL)
Qqt = new quadquadrilatt;
Tp->gdim=2;
if (Tp->gdim < 2)
Tp->gdim=2;
break;
}
case quadquadtax:{
145,7 → 154,8
get=quadquad;
if (Qqat==NULL)
Qqat = new quadquadrilattax;
Tp->gdim=2;
if (Tp->gdim < 2)
Tp->gdim=2;
break;
}
case quadlaxisym:{
152,7 → 162,8
get=linquad;
if (Lqat==NULL)
Lqat = new quadlinaxisym;
Tp->gdim=2;
if (Tp->gdim < 2)
Tp->gdim=2;
break;
}
case ifacequadel:{
159,7 → 170,8
get=linquad;
if (Ifcquadt==NULL)
Ifcquadt = new interfacequadrilat;
Tp->gdim=2;
if (Tp->gdim < 2)
Tp->gdim=2;
break;
}
case lineartett:{
185,10 → 197,11
}
case gen2del:{
get=gen2d;
 
if (G2d==NULL)
G2d = new gen2delem;
Tp->gdim=2;
if (Tp->gdim < 2)
Tp->gdim=2;
break;
}
default:{
/trunk/SIFEL/TRFEL/SRC/elemswitcht.cpp
1088,7 → 1088,7
#ifdef INC_OPENMP
#pragma omp parallel num_threads(4)
{
#pragma omp for nowait
#pragma omp for
#endif
for (long i=0;i<ne;i++){
if (Gtt->leso[i]==1){
1233,7 → 1233,7
#ifdef INC_OPENMP
#pragma omp parallel num_threads(4)
{
#pragma omp for nowait
#pragma omp for
#endif
// loop over all elements
for (long i=0; i<ne; i++)
1264,7 → 1264,7
#ifdef INC_OPENMP
#pragma omp parallel num_threads(4)
{
#pragma omp for nowait
#pragma omp for
#endif
for (long i=0;i<ne;i++){
if (Gtt->leso[i]==1){
1296,7 → 1296,7
#ifdef INC_OPENMP
#pragma omp parallel num_threads(4)
{
#pragma omp for nowait
#pragma omp for
#endif
for (long i=0;i<ne;i++){
if (Gtt->leso[i]==1){
2798,6 → 2798,10
case ifacequadel:
Ifcquadt->transq_nodval(eid, nodval, nmq);
break;
case lineartett:{
Ltett->transq_nodval(eid, nodval, nmq);
break;
}
default:{
print_err("unknown element type is required", __FILE__, __LINE__, __func__);
}
2842,6 → 2846,10
Lqat->transq_init_nodval(eid, nodval, nmq);
break;
}
case lineartett:{
Ltett->transq_init_nodval(eid, nodval, nmq);
break;
}
default:{
print_err("unknown element type is required", __FILE__, __LINE__, __func__);
}
2888,6 → 2896,10
Lqat->transq_nodval_comp (eid, nodval, ncne, nq, qt);
break;
}
case lineartett:{
Ltett->transq_nodval_comp (eid, nodval, ncne, nq, qt);
break;
}
default:{
print_err("unknown element type is required", __FILE__, __LINE__, __func__);
}
2934,6 → 2946,10
Lqat->transq_init_nodval_comp (eid, nodval, ncne, nq, qt);
break;
}
case lineartett:{
Ltett->transq_init_nodval_comp (eid, nodval, ncne, nq, qt);
break;
}
default:{
print_err("unknown element type is required", __FILE__, __LINE__, __func__);
}
/trunk/SIFEL/TRFEL/SRC/globmatt.cpp
1782,10 → 1782,13
// caused by initial conditions and prescribed values
assemble_init (rhs);
//if(Tp->time >= 5.342000e+04){
//for (long ijk=0;ijk<n;ijk++){
//fprintf (Outt,"\n assemble init %ld %le",ijk,rhs[ijk]);
// fprintf (Outt,"\n assemble init %ld %le",ijk,rhs[ijk]);
//}
//fflush(Outt);
//}
 
//contribution of gradients for homogenization
if(Tp->homogt == 1){
nullv (av,n);
/trunk/SIFEL/TRFEL/SRC/isotrmat.cpp
205,6 → 205,10
new_trc=1.0;
break;
}
case 51:{//heat transmission - boundary condition computed from the actual boundary flux
new_trc=1.0;
break;
}
case 90:{//radiation
new_trc=1.0;
break;
256,6 → 260,14
new_trc=1.0;
break;
}
case 51:{//heat transmission => heat flux - this boundary condition is created provisionally for salt diffusion problem
// the flux of salt ions is calculated for inflow flux from external and interal values of concentration
if(flag == 1)//for rhs vector
new_trc=1.0;
else
new_trc=0.0;//for matrix
break;
}
case 90:{//radiation
if(flag == 1)//for rhs vector
new_trc=1.0;
291,7 → 303,10
{
long k;
double dt=0.0,new_nodval=0.0,t;
//provisionally for salt diffusion:
double por,rhoc,rhow,ecl,c0,kcl;
 
 
k=Gtt->give_dof(nn,0);
if (k>0) {t = Lsrst->lhs[k-1]+Lsrst->lhsi[k-1];}
if (k==0) {t = 0.0;}
319,6 → 334,20
new_nodval=Tm->ip[ipp].av[0] + Tb->fluxes[0]*nodval*dt;//cumulated value from the first integration point of the element
break;
}
case 51:{//heat transmission => heat flux - this boundary condition is created provisionally for salt diffusion problem
// the flux of salt ions is calculated for inflow flux from external and interal values of concentration
por = 0.122;
rhoc = 2233.0;
rhow = 998;
//ecl = 1.16e-12;
ecl = 1.0e-7;
c0 = 0.51;
//kcl = 1.74e-12;
kcl = 1.5e-7;
new_nodval = -0.035453*(ecl*(1/por*rhoc/rhow*Tm->ip[ipp].av[0] - nodval)+kcl*(1/por*rhoc/rhow*Tm->ip[ipp].av[0]/c0)*
(1/por*rhoc/rhow*Tm->ip[ipp].av[0]/c0)*exp(-1.15/por*rhoc/rhow*Tm->ip[ipp].av[0]));
break;
}
case 90:{//radiation
//new_nodval = (nodval - t) + trc2*(nodval*nodval*nodval*nodval - t*t*t*t);//inverse eq. (trc2 = e_sigma0/trc)
new_nodval = trc2*(nodval*nodval*nodval*nodval - t*t*t*t);//inverse eq. (trc2 = e_sigma0/trc)
351,7 → 380,9
{
long k;
double dt=0.0,flux=0.0,t;
//provisionally for salt diffusion:
double por,rhoc,rhow,ecl,c0,kcl;
 
k=Gtt->give_dof(nn,0);
if (k>0) {t = Lsrst->lhs[k-1]+Lsrst->lhsi[k-1];}
if (k==0) {t = 0.0;}
371,6 → 402,20
flux = (Tm->ip[ipp].av[0] + Tb->fluxes[0]*nodval*dt - t);//cumulated value from the first integration point of the element
break;
}
case 51:{//heat transmission => heat flux - this boundary condition is created provisionally for salt diffusion problem
// the flux of salt ions is calculated for inflow flux from external and interal values of concentration
por = 0.122;
rhoc = 2233.0;
rhow = 998;
//ecl = 1.16e-12;
ecl = 1.0e-7;
c0 = 0.51;
//kcl = 1.74e-12;
kcl = 1.5e-7;
flux = -0.035453*(ecl*(1/por*rhoc/rhow*Tm->ip[ipp].av[0] - nodval)+kcl*(1/por*rhoc/rhow*Tm->ip[ipp].av[0]/c0)*
(1/por*rhoc/rhow*Tm->ip[ipp].av[0]/c0)*exp(-1.15/por*rhoc/rhow*Tm->ip[ipp].av[0]));
break;
}
case 90:{//radiation
//flux = (nodval - t) + trc2*(nodval*nodval*nodval*nodval - t*t*t*t);//inverse eq. (trc2 = e_sigma0/trc)
flux = trc2*(nodval*nodval*nodval*nodval - t*t*t*t);//inverse eq. (trc2 = e_sigma0/trc)
/trunk/SIFEL/TRFEL/SRC/lintett.cpp
2554,3 → 2554,223
}
 
}
 
 
 
/**
Function returns transport (non-mechanical) quantities at nodes of element.
The values of selected quantity is copied from the closest integration points
to element nodes.
 
@param eid - element id
@param nodval - %vector of nodal values
@param ntq - type of non-mechanical quantity
@return The function does not return anything.
Created by TKo, 3.2.2014
*/
void lintett::transq_nodval (long eid,vector &nodval,nonmechquant nmq)
{
long i,ipid;
ivector ipnum(ASTCKIVEC(nne));
// numbers of integration points closest to nodes
// (function is from the file GEFEL/ordering.cpp)
ipid=Tt->elements[eid].ipp[0][0];
nodip_planelq (ipid,intordkm[0][0], ipnum);
 
for (i=0;i<nne;i++)
{
//copy transport (non-mechanical) quantity from closest int. point
nodval[i] = Tm->givetransq(nmq, ipnum[i]);
}
}
 
 
 
/**
Function computes transport (non-mechanical) quantities at nodes of element.
 
@param eid - element id
@param nodval - %vector of nodal values of all required quantities, i.e.,
nodal value of i-th quantity in j-th node is given by nodval[i*ncnv+j] where ncnv
is the number of calculated nodes on eid-th element.
@param ncne - number of computed nodes on element (only first ncne of nodes is calculated)
@param nq - number of required transport quantities
@param qt - array of types of required non-mechanical, i.e. transport quantities
@return The function does not return anything.
Modified by TKo, 31.1.2014
Created by 26/09/2012 TKr
*/
void lintett::transq_nodval_comp (long eid,vector &nodval, long ncne, long nq, nonmechquant *qt)
{
long i,j,ipid,ncompo;
ivector ipnum(ASTCKIVEC(nne)), enod(ASTCKIVEC(nne));
intpointst ipb; // backup of the first integration point of element
vector ipav;
// numbers of integration points closest to nodes
// (function is from the file GEFEL/ordering.cpp)
ipid=Tt->elements[eid].ipp[0][0];
 
// element nodes
Tt->give_elemnodes(eid, enod);
 
// numbers of integration points closest to element nodes
// (function is from the file GEFEL/ordering.cpp)
nodip_planelq (ipid,intordkm[0][0], ipnum);
 
// store original content of the first integration point on element because
// it becomes working int. point for nodal values calculations on the given element
ipb.copy(Tm->ip[ipid], ntm, 1);
 
// The first integration point will be used for computation of nodal values temporarily
// then the original content of the first integration point will be restored
for (i=0;i<ncne;i++)
{
makerefv(ipav, Tm->ip[ipid].av, Tp->ntm);
// store nodal values to the first (working) integration point
nodalval (enod[i], ipav);
// store gradients to the first (working) integration point
// for(j=0; j<ntm; j++)
// Tm->ip[ipid].storegrad(j, Tt->nodes[enod[i]].gradient[j]);
 
ncompo = Tm->ip[ipnum[i]].ncompeqother;
if (ncompo){
// take eqother values for the given node from the closest integration point
Tm->storeeqother(ipid, 0, ncompo, Tm->ip[ipnum[i]].eqother);
}
ncompo = Tm->ip[ipnum[i]].ncompother;
if (ncompo){
// take eqother values for the given node from the closest integration point
Tm->storeother(ipid, 0, ncompo, Tm->ip[ipnum[i]].other);
}
Tm->mat_aux_values(ipid);
 
//give calculated transport quantity from the first int. point
for (j=0; j<nq; j++)
nodval[j*ncne+i] = Tm->givetransq(qt[j], ipid);
}
// restore original integration point content of other/eqother arrays
Tm->ip[ipid].copy(ipb, ntm, 0);
}
 
 
 
/**
Function returns initial values of transport (non-mechanical) quantities at nodes of element.
The values of selected quantity is copied from the closest integration points
to element nodes.
 
@param eid - element id
@param nodval - %vector of nodal values
@param ntq - type of non-mechanical quantity
@return The function does not return anything.
12/06/2012 TKr
Modified by TKo, 10.10.2013
*/
void lintett::transq_init_nodval (long eid,vector &nodval,nonmechquant nmq)
{
long i,ipid;
ivector ipnum(ASTCKIVEC(nne)), enod(ASTCKIVEC(nne));
vector ipav;
// numbers of integration points closest to nodes
// (function is from the file GEFEL/ordering.cpp)
ipid=Tt->elements[eid].ipp[0][0];
nodip_planelq (ipid,intordkm[0][0], ipnum);
// element nodes
Tt->give_elemnodes(eid, enod);
 
for (i=0;i<nne;i++)
{
// create reference vector to the int. point av array
makerefv(ipav, Tm->ip[ipnum[i]].av, Tp->ntm);
// store initial nodal values to the integration point
initnodval2(enod[i], ipav);
//copy transport (non-mechanical) quantity from closest int. point
nodval[i] = Tm->givetransq(nmq, ipnum[i]);
}
}
 
 
 
/**
Function computes initial transport (non-mechanical) quantities at nodes of element.
 
@param eid - element id
@param nodval - %vector of initial nodal values of all required quantities, i.e.,
nodal value of i-th quantity in j-th node is given by nodval[i*ncnv+j] where ncnv
is the number of calculated nodes on eid-th element.
@param ncne - number of computed nodes on element (only first ncne of nodes is calculated)
@param nq - number of required transport quantities
@param qt - array of types of required non-mechanical, i.e. transport quantities
@return The function does not return anything.
Modified by TKo, 31.1.2014
Created by 26/09/2012 TKr
*/
void lintett::transq_init_nodval_comp (long eid,vector &nodval, long ncne, long nq, nonmechquant *qt)
{
long i,j,ipid,ncompo;
ivector ipnum(ASTCKIVEC(nne)), enod(ASTCKIVEC(nne));
vector ipav;
intpointst ipb; // backup of the first integration point of element
// numbers of integration points closest to nodes
// (function is from the file GEFEL/ordering.cpp)
ipid=Tt->elements[eid].ipp[0][0];
 
// element nodes
Tt->give_elemnodes(eid, enod);
 
// numbers of integration points closest to element nodes
// (function is from the file GEFEL/ordering.cpp)
nodip_planelq (ipid,intordkm[0][0], ipnum);
 
// store original content of the first integration point on element because
// it becomes working int. point for nodal values calculations on the given element
ipb.copy(Tm->ip[ipid], ntm, 1);
 
// The first integration point will be used for computation of nodal values temporarily
// then the original content of the first integration point will be restored
for (i=0;i<ncne;i++)
{
// create reference vector to the int. point av array
makerefv(ipav, Tm->ip[ipid].av, Tp->ntm);
// store initial nodal values to the first (working) integration point
initnodval2 (enod[i], ipav);
// store gradients to the first (working) integration point
// for(j=0; j<ntm; j++)
// Tm->ip[ipid].storegrad(j, Tt->nodes[enod[i]].gradient[j]);
 
ncompo = Tm->ip[ipnum[i]].ncompeqother;
if (ncompo){
// take eqother values for the given node from the closest integration point
Tm->storeeqother(ipid, 0, ncompo, Tm->ip[ipnum[i]].eqother);
}
ncompo = Tm->ip[ipnum[i]].ncompother;
if (ncompo){
// take eqother values for the given node from the closest integration point
Tm->storeother(ipid, 0, ncompo, Tm->ip[ipnum[i]].other);
}
Tm->mat_aux_values(ipid);
 
//give calculated transport quantity from the first int. point
for (j=0; j<nq; j++)
nodval[j*ncne+i] = Tm->givetransq(qt[j], ipid);
}
// restore original integration point content of other/eqother arrays
Tm->ip[ipid].copy(ipb, ntm, 0);
}
 
/trunk/SIFEL/TRFEL/SRC/lintett.h
69,6 → 69,11
long ipcoord (long eid, long ipp, long ri, long ci, vector &coord);
/// function returns natural coordinates of the given integration point
long ipncoord (long eid, long ipp, vector &ncoord);
 
void transq_nodval (long eid,vector &nodval,nonmechquant nmq);
void transq_nodval_comp (long eid,vector &nodval, long ncne, long nq, nonmechquant *qt);
void transq_init_nodval (long eid,vector &nodval,nonmechquant nmq);
void transq_init_nodval_comp (long eid,vector &nodval, long ncne, long nq, nonmechquant *qt);
/// number of transported matter
long ntm;
/trunk/SIFEL/TRFEL/SRC/masin_reten.cpp
0,0 → 1,354
/*
File: masin_reten.cpp
Author: Tomas Krejci, 28/02/2023
Purpose: retention curve - extended formulation from Brooks and Correy according to Masin
sources:
sr_type: 1 Masin, D. (2010), Predicting the dependency of a degree of saturation on void ratio and suction using effective stress principle for unsaturated soils. Int. J. Numer. Anal. Meth. Geomech., 34: 73-90. https://doi.org/10.1002/nag.808
sr_type: 2 Masin, D, (2013), Double structure hydromechanical coupling formalism and a model for unsaturated expansive clays, Engineering Geology, 165, 73-88, ISSN 0013-7952, https://doi.org/10.1016/j.enggeo.2013.05.026.
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "globalt.h"
#include "masin_reten.h"
 
masin_reten::masin_reten()
{
sr_type = 1;
 
se0 = 2700.0;
e0 = 0.5;
tref = 294.0;
lambdap0 = 0.15;
at = 0.118;
bt = -0.000154;
gamma0 = 0.55;
ae = 1.0;
}
 
masin_reten::~masin_reten()
{}
 
/**
function reads parameters
@param in - input file
 
TKr 28/02/2023
*/
void masin_reten::read(XFILE *in)
{
xfscanf (in,"%ld %lf %lf %lf %lf %lf %lf %lf %lf", &sr_type, &se0,&e0,&ae,&lambdap0,&at,&bt,&tref,&gamma0);
}
 
/**
function reads parameters
@param in - input file
 
TKr 28/02/2023
*/
void masin_reten::print(FILE *out)
{
fprintf (out,"\n%ld %lf %lf %lf %lf %lf %lf %lf %lf\n", sr_type,se0,e0,ae,lambdap0,at,bt,tref,gamma0);
}
 
/**
function computes effective stress factor psi
 
@param pw - pore water pressure
@retval sw - saturation degree
TKr 28/02/2023
*/
double masin_reten::psi(double suction, double dsuc, double e, double temp)
{
double psi,se,sr,lambdap,chi;
if(e == 0.0)//intial porosity
e = e0;
 
se = get_se(suction,dsuc,e,temp);
sr = sw(suction,dsuc,e,temp);
 
switch (sr_type){
case 0:
case 1:{
if(suction < se)
psi = 1.0-gamma0;
else{
lambdap = get_lambdap(suction,dsuc,e,temp);
chi = pow(sr,(gamma0/lambdap));
psi = (1-gamma0)*chi;
}
break;
}
case 2:{
if(suction < se)
psi = 1.0;
else{
psi = sr;
}
break;
}
default:{
print_err("Unknown WRC type is required",__FILE__,__LINE__,__func__);
}
}
 
check_math_errel(0);
 
return(psi);
}
 
 
/**
function computes parameter se - suction air-entry value
 
@param pw - pore water pressure
@retval sw - saturation degree
TKr 28/02/2023
*/
double masin_reten::get_se(double suction, double dsuc, double e, double temp)
{
double se;
 
switch (sr_type){
case 0:{
se = se0;
break;
}
case 1:{
se = se0*e0/e;
break;
}
case 2:{
se = se0*e0/e;//drying branch
if(dsuc >= 0.0)
se = ae*se;//wetting branch
break;
}
default:{
print_err("Unknown WRC type is required",__FILE__,__LINE__,__func__);
}
}
 
return(se);
}
 
 
/**
function computes derivative of parameter se with repsect to e prosity
 
@param pw - pore water pressure
@retval sw - saturation degree
TKr 28/02/2023
*/
double masin_reten::get_dse_de(double suction, double dsuc, double e, double temp)
{
double dse_de;
 
switch (sr_type){
case 0:{
dse_de = 0.0;
break;
}
case 1:{
dse_de = -se0*e0/e/e;
break;
}
case 2:{
dse_de = -se0*e0/e/e;//drying branch
if(dsuc >= 0.0)
dse_de = ae;//wetting branch
break;
}
default:{
print_err("Unknown WRC type is required",__FILE__,__LINE__,__func__);
}
}
 
return(dse_de);
}
 
 
/**
function computes parameter lambdap
 
@param pw - pore water pressure
@retval sw - saturation degree
TKr 28/02/2023
*/
double masin_reten::get_lambdap(double suction, double dsuc, double e, double temp)
{
double lambdap,chi0;
chi0 = pow((se0/suction),gamma0);
 
lambdap = gamma0/log(chi0)*log((pow(chi0,(lambdap0/gamma0)) - chi0)*pow((e/e0),(gamma0-1)) + chi0);
 
return(lambdap);
}
 
 
 
 
/**
function computes saturation degree
 
@param pw - pore water pressure
@retval sw - saturation degree
TKr 28/02/2023
*/
double masin_reten::sw(double suction, double dsuc, double e, double temp)
{
double sr,se,gamma,lambdap;
if(e == 0.0)//intial porosity
e = e0;
se = get_se(suction,dsuc,e,temp);
if(suction < se)
sr = 1.0;
else{
switch (sr_type){
case 0:
case 1:{
lambdap = get_lambdap(suction,dsuc,e,temp);
gamma = lambdap;
break;
}
case 2:{
gamma = gamma0;
break;
}
default:{
print_err("Unknown WRC type is required",__FILE__,__LINE__,__func__);
}
}
sr = pow((se/suction),gamma);
}
check_math_errel(0);
return(sr);
}
 
 
/**
function computes partial derivative of degree of saturation with respect to pw, specific water content
 
@param pw - water pressure
@retval dsw_dpw - partial derivative of degree of saturation with respect to pw
 
TKr 28/02/2023
*/
double masin_reten::dsw_dpw(double suction, double dsuc, double e, double temp)
{
double dsr_ds,se,lambdap,gamma;
if(e == 0.0)//intial porosity
e = e0;
 
se = get_se(suction,dsuc,e,temp);
 
if(suction < se)
dsr_ds = 0.0;
else{
switch (sr_type){
case 0:
case 1:{
lambdap = get_lambdap(suction,dsuc,e,temp);
gamma = lambdap;
break;
}
case 2:{
gamma = gamma0;
break;
}
default:{
print_err("Unknown WRC type is required",__FILE__,__LINE__,__func__);
}
}
dsr_ds = pow((se/suction),gamma-1)*(-se)/(suction*suction);//not completed??!!, derivative of lambdap must be added
}
check_math_errel(0);
 
return(dsr_ds);
}
 
 
/**
function computes partial derivative of degree of saturation with respect to t
 
@param pw - water pressure
@retval dsw_dt - partial derivative of degree of saturation with respect to t
 
TKr 28/02/2023
*/
double masin_reten::dsw_dt(double suction, double dsuc, double e, double temp)
{
double dsr_dt;
dsr_dt = 0.0;//p. 167
return(dsr_dt);
}
 
 
/**
function computes partial derivative of degree of saturation with respect to epsv, volumetric strain
 
@param pw - water pressure
@retval dsw_depsv - partial derivative of degree of saturation with respect to pw
 
TKr 28/02/2023
*/
double masin_reten::dsw_depsv(double suction, double dsuc, double e, double temp)
{
double dsr_depsv,dsr_de,dsr_dse,se,dse_de,lambdap,gamma;
se = get_se(suction,dsuc,e,temp);
 
if(suction < se)
dsr_depsv = 0.0;
else{
if(e == 0.0)//intial porosity
e = e0;
dse_de = get_dse_de(suction,dsuc,e,temp);
switch (sr_type){
case 0:
case 1:{
lambdap = get_lambdap(suction,dsuc,e,temp);
gamma = lambdap;
break;
}
case 2:{
gamma = gamma0;
break;
}
default:{
print_err("Unknown WRC type is required",__FILE__,__LINE__,__func__);
}
}
dsr_dse = gamma*pow((se/suction),(gamma-1))/suction;
dsr_de = dsr_dse*dse_de;
dsr_depsv = dsr_de*(1+e0);//not completed??!!, derivative of lambdap must be added
}
 
check_math_errel(0);
 
return(dsr_depsv);
}
/trunk/SIFEL/TRFEL/SRC/masin_reten.h
0,0 → 1,35
#ifndef MASIN_RETEN_H
#define MASIN_RETEN_H
 
#include "genfile.h"
 
/**
This class defines retention curve of Masin and Schrefler's model
*/
 
class masin_reten
{
public:
masin_reten(); //constructor
~masin_reten(); //destructor
 
void read(XFILE *in);
void print(FILE *out);
 
double psi(double suction, double dsuc, double e, double temp);
double get_lambdap(double suction, double dsuc, double e, double temp);
double get_se(double suction, double dsuc, double e, double temp);
double get_dse_de(double suction, double dsuc, double e, double temp);
double sw(double suction, double dsuc, double e, double temp);
double dsw_dpw(double suction, double dsuc, double e, double temp);
double dsw_dt(double suction, double dsuc, double e, double temp);
double dsw_depsv(double suction, double dsuc, double e, double temp);
 
private:
long sr_type; /// type of retention curve and effective stress factor
double se0; /// the air entry value of suction for the reference macrostructural void ratio e0
double e0; /// reference void ratio
double ae,lambdap0,at,bt,tref,gamma0; ///parameters
};
 
#endif
/trunk/SIFEL/TRFEL/SRC/nnpsolvert.cpp
1769,7 → 1769,7
else
stop=0; // norm is not in the given tolerance
if (Mesprt==1) fprintf (stdout,"\n norm of residuum %e, required error %e",norf,err[0]);
if (Mesprt==1) fprintf (stdout,"\n norm of residuum %.15e, required error %e",norf,err[0]);
}
if (sc==1){
1786,7 → 1786,7
else
stop=0; // norm is not in the given tolerance
norfb /= norrhs;
if (Mesprt==1) fprintf (stdout,"\n norm of residuum %e, norm of rhs %e, error %e, required error %e",norf,norrhs,norf/norrhs,err[0]);
if (Mesprt==1) fprintf (stdout,"\n norm of residuum %.15e, norm of rhs %.15e, error %e, required error %e",norf,norrhs,norf/norrhs,err[0]);
}
else{
if (norf<err[0])
1793,7 → 1793,7
stop=1; // norm is in the given tolerance
else
stop=0; // norm is not in the given tolerance
if (Mesprt==1) fprintf (stdout,"\n norm of residuum %e, norm of rhs %e, required error %e",norf,norrhs,err[0]);
if (Mesprt==1) fprintf (stdout,"\n norm of residuum %.15e, norm of rhs %.15e, required error %e",norf,norrhs,err[0]);
}
}
}
1830,7 → 1830,7
norfb += sqr(norf);
if (Mesprt==1) fprintf (stdout,"\n phase %ld, norm of residuum %e, required error %e",i+1,norf,err[i]);
if (Mesprt==1) fprintf (stdout,"\n phase %ld, norm of residuum %.15e, required error %e",i+1,norf,err[i]);
}
if (sc==1){
1839,13 → 1839,13
if (norf/norrhs<err[i])
pstop++;
norfb += sqr(norf)/sqr(norrhs);
if (Mesprt==1) fprintf (stdout,"\n phase %ld, norm of residuum %e, norm of rhs %e, error %e, required error %e",i+1,norf,norrhs,norf/norrhs,err[i]);
if (Mesprt==1) fprintf (stdout,"\n phase %ld, norm of residuum %.15e, norm of rhs %.15e, error %e, required error %e",i+1,norf,norrhs,norf/norrhs,err[i]);
}
else{
if (norf<err[i])
pstop++;
norfb += sqr(norf);
if (Mesprt==1) fprintf (stdout,"\n phase %ld, norm of residuum %e, norm of rhs %e, required error %e",i+1,norf,norrhs,err[i]);
if (Mesprt==1) fprintf (stdout,"\n phase %ld, norm of residuum %.15e, norm of rhs %.15e, required error %e",i+1,norf,norrhs,err[i]);
}
}
//fprintf (stdout,"\n phase %ld, pstop %ld",i+1,pstop);
/trunk/SIFEL/TRFEL/SRC/npsolvert.cpp
597,12 → 597,14
for (j=0;j<n;j++){
f[j] = rhs[j] - p[j];
}
 
//if(Tp->time >= 5.342000e+04){
//fprintf(Outt, "\nF vector:\n");
//for (j=0;j<n;j++){
//fprintf(Outt, "%e\n",f[j]);
// fprintf(Outt, "%e\n",f[j]);
//}
//fflush(Outt);
//}
 
// solution of the system of algebraic equations
// (C + alpha dt K) v_{n+1} = f_{n+1} - K dd
609,6 → 611,14
// time derivatives v_{n+1} are solved
Tp->ssle->solve_system (Gtt,Cmat,tdlhs,f,Outt);
//if(Tp->time >= 5.342000e+04){
//fprintf(Outt, "\n tdlhs vector:\n");
//for (j=0;j<n;j++){
// fprintf(Outt, "%e\n",tdlhs[j]);
//}
//fflush(Outt);
//}
 
// nodal values computed from nodal derivatives
// d_{n+1} = dd + alpha dt v_{n+1}
for (j=0;j<n;j++){
615,6 → 625,14
lhs[j] = d[j] + alpha*dt*tdlhs[j];
}
 
//if(Tp->time >= 5.342000e+04){
//fprintf(Outt, "\n lhs vector:\n");
//for (j=0;j<n;j++){
// fprintf(Outt, "%e\n",lhs[j]);
//}
//fflush(Outt);
//}
 
// physically corrected solution
solution_correction ();
 
684,7 → 702,7
stop = norm_computation_vec (fb,rhs,err,thresh,2,1,norfb);
if (stop) break;
if (Mesprt==1) fprintf (stdout,"\n inner iteration %ld error %e", j, norfb);
if (Mesprt==1) fprintf (stdout,"\n inner iteration %ld error %.15le", j, norfb);
 
Tp->ssle->solve_system (Gtt,Cmat,fi,fb,Outt);//fi is output now
/trunk/SIFEL/TRFEL/SRC/onemedium.cpp
502,7 → 502,7
switch (Tm->ip[ipp].tm){
case isotransmat:{
new_trc = Tm->itrm[i].transmission_transcoeff(trc,ri,ci,nn,bc,ipp);
new_trc = Tm->itrm[i].transmission_transcoeff(trc,ri,ci,nn,bc,ipp,flag);
break;
}
case consolawf1:{
/trunk/SIFEL/TRFEL/SRC/threemedia.cpp
44,6 → 44,7
case C60baroghelB:
case C30baroghelB:
case o30bazantB:
case C30bazantB:
case C60bazantB:{
multiph mtph;
mtph.matcond(d,ri,ci,ipp);
105,6 → 106,7
case C60baroghelB:
case C30baroghelB:
case o30bazantB:
case C30bazantB:
case C60bazantB:{
multiph mtph;
mtph.matcond2(d,ri,ci,ipp);
161,6 → 163,7
case C60baroghelB:
case C30baroghelB:
case o30bazantB:
case C30bazantB:
case C60bazantB:{
multiph mtph;
mtph.matcap(c,ri,ci,ipp);
220,6 → 223,7
case C60baroghelB:
case C30baroghelB:
case o30bazantB:
case C30bazantB:
case C60bazantB:{
multiph mtph;
279,6 → 283,7
case C60baroghelB:
case C30baroghelB:
case o30bazantB:
case C30bazantB:
case C60bazantB:{
//multiph mtph;
 
323,6 → 328,7
case C60baroghelB:
case C30baroghelB:
case o30bazantB:
case C30bazantB:
case C60bazantB:{
multiph mtph;
388,6 → 394,7
case C60baroghelB:
case C30baroghelB:
case o30bazantB:
case C30bazantB:
case C60bazantB:{
multiph mtph;
452,6 → 459,7
case C60baroghelB:
case C30baroghelB:
case o30bazantB:
case C30bazantB:
case C60bazantB:{
multiph mtph;
517,6 → 525,7
case C60baroghelB:
case C30baroghelB:
case o30bazantB:
case C30bazantB:
case C60bazantB:{
multiph mtph;
584,6 → 593,7
case C60baroghelB:
case C30baroghelB:
case o30bazantB:
case C30bazantB:
case C60bazantB:
{
multiph mtph;
647,6 → 657,7
case C60baroghelB:
case C30baroghelB:
case o30bazantB:
case C30bazantB:
case C60bazantB:{
multiph mtph;
/trunk/SIFEL/TRFEL/SRC/transmat.cpp
686,6 → 686,10
break;
}
case C30bazantB:
C30bazant[i].give_dof_names(dofname, ntm);
break;
case C60bazantB:{
C60bazant[i].give_dof_names(dofname, ntm);
break;
2653,6 → 2657,7
case C60baroghelB:
case C30baroghelB:
case o30bazantB:
case C30bazantB:
case C60bazantB:
case soilmat1:
break;
2821,10 → 2826,9
break;
}
default:{
print_err("unknown material type is required",__FILE__,__LINE__,__func__);
print_err("unknown material type is required on ip %ld, eid=%ld",__FILE__,__LINE__,__func__, ipp, Tm->elip[ipp]+1);
}
}
return t;
}
 
2870,7 → 2874,7
break;
}
default:{
print_err("unknown material type is required",__FILE__,__LINE__,__func__);
print_err("unknown material type %d is required on ip %ld, eid=%ld",__FILE__,__LINE__,__func__, ipp, Tm->elip[ipp]+1);
}
}
3140,6 → 3144,14
pp = consol_wf1[i].give_effective_pore_pressure (ipp);
break;
}
case consolhwf2:{
pp = consol_hwf2[i].give_effective_pore_pressure (ipp);
break;
}
case consolhawf3:{
pp = consol_hawf3[i].give_effective_pore_pressure (ipp);
break;
}
default:{
print_err("unknown material type is required",__FILE__,__LINE__,__func__);
}
4257,6 → 4269,7
case C60baroghelB:
case C30baroghelB:
case o30bazantB:
case C30bazantB:
case C60bazantB:{
multiph mtph;
mtph.values_correction (nv);
4748,6 → 4761,7
case C60baroghelB:
case C30baroghelB:
case o30bazantB:
case C30bazantB:
case C60bazantB:
case soilmat1:
break;
5034,6 → 5048,7
case C60baroghelB:
case C30baroghelB:
case o30bazantB:
case C30bazantB:
case C60bazantB:
case soilmat1:
break;
5213,6 → 5228,7
case C60baroghelB:
case C30baroghelB:
case o30bazantB:
case C30bazantB:
case C60bazantB:
case soilmat1:
case consolwf2:
5508,6 → 5524,7
case C60baroghelB:
case C30baroghelB:
case o30bazantB:
case C30bazantB:
case C60bazantB:
case soilmat1:
case consolwf2:
/trunk/SIFEL/TRFEL/SRC/van_genuchten.cpp
3,9 → 3,20
Author: Tomas Krejci, 13/04/2018
Purpose: retention curve accorging to Van_Genuchten model
sources:
M. Th. van Genuchten, A closed equation for predicting the hydraulic conductivity of
classical expr: M. Th. van Genuchten, A closed equation for predicting the hydraulic conductivity of
unsaturated soils, Journal Soil Science Society of America 44 (1980), 892-898;
pore water pressure (suction) is assumed in kPa (kilo Pascals)
 
extension 1: A full-scale in situ heating test for high-level nuclear waste disposal: observations, analysis and interpretation
A. Gens, M. Sanchez, L. Do N. Guimaraes, E. E. Alonso, A. Lloret, S. Olivella, M. V. Villar, and F. Huertas
Geotechnique 2009 59:4, 377-399
 
extension 2: ??
 
extension 3: Abel Carlos Jacinto, Maria Victoria Villar, Roberto Gomez-Espina, Alberto Ledesma,
Adaptation of the van Genuchten expression to the effects of temperature and density for compacted bentonites, Applied Clay Science,
Volume 42, Issues 3–4, 2009,Pages 575-582,ISSN 0169-1317,https://doi.org/10.1016/j.clay.2008.04.001.
*/
 
#include <stdio.h>
16,6 → 27,8
 
van_genuchten_reten::van_genuchten_reten()
{
vg_ret_type = 0; //retention curve type
 
ssat = 1.0; //saturation degree [-]
sirr = 0.2; //irreversible saturation degree [-]
ksat = 0.1; //saturation permeability [??]
23,6 → 36,11
delta = 20.0; //parameter in m^(-1); delta = 20.0 [1/m]; delta = 0.2 [1/cm]
expn = 2.0; //parameter n
expm = 0.0; //parameter m
 
p0 = 0.0; //parameter
pd = 0.0; //parameter
lambda0 = 1.0; //parameter
lambdap = 1.0; //parameter
}
 
van_genuchten_reten::~van_genuchten_reten()
38,7 → 56,29
*/
void van_genuchten_reten::read(XFILE *in)
{
xfscanf (in,"%lf %lf %lf %lf %lf %lf", &ssat, &sirr, &expn, &expm, &ksat, &delta);
//retention curve type:
xfscanf (in,"%ld",&vg_ret_type);
 
switch (vg_ret_type){
case 0:{//classical expression
xfscanf (in,"%lf %lf %lf %lf %lf %lf", &ssat, &sirr, &expn, &expm, &ksat, &delta);
break;
}
case 1:{//extended for expansive clays
xfscanf (in,"%lf %lf %lf %lf %lf %lf", &ssat, &sirr, &p0, &lambda0, &pd, &lambdap);
break;
}
case 2:{//extended for expansive clays and temperature dependent
xfscanf (in,"%lf %lf %lf %lf %lf %lf", &ssat, &sirr, &p0, &lambda0, &pd, &lambdap);
break;
}
default:{
print_err ("unknown van genuchten retention curve type is required", __FILE__, __LINE__, __func__);
abort();
}
}
 
}
 
/**
50,7 → 90,24
*/
void van_genuchten_reten::print(FILE *out)
{
fprintf (out,"\n%lf %lf %lf %lf %lf %lf\n", ssat, sirr, expn, expm, ksat, delta);
switch (vg_ret_type){
case 0:{//classical expression
fprintf (out,"\n%lf %lf %lf %lf %lf %lf\n", ssat, sirr, expn, expm, ksat, delta);
break;
}
case 1:{//extended for expansive clays
fprintf (out,"\n%lf %lf %lf %lf %lf %lf\n", ssat, sirr, p0, lambda0, pd, lambdap);
break;
}
case 2:{//extended for expansive clays and temperature dependent
fprintf (out,"\n%lf %lf %lf %lf %lf %lf\n", ssat, sirr, p0, lambda0, pd, lambdap);
break;
}
default:{
print_err ("unknown van genuchten retention curve type is required", __FILE__, __LINE__, __func__);
abort();
}
}
}
 
/**
63,18 → 120,48
*/
double van_genuchten_reten::sw(double pw)
{
double sw,hp,theta;
double sw,hp,theta,fd=1.0,ft=1.0;
 
pw = pw/1000.0;//in kPa
 
if(pw >= 0.0)
pw = 0.0;//for positive pressure
hp = pw/gamaw;
if(expm == 0.0)
expm = 1.0 - 1.0/expn;
theta = pow(1+(pow(delta*fabs(hp),expn)),-expm);
sw = sirr + (ssat - sirr)*theta;
switch (vg_ret_type){
case 0:{//classical expression
if(pw >= 0.0)
pw = 0.0;//for positive pressure
hp = pw/gamaw;
if(expm == 0.0)
expm = 1.0 - 1.0/expn;
theta = pow(1+(pow(delta*fabs(hp),expn)),-expm);
sw = sirr + (ssat - sirr)*theta;
break;
}
case 1:{//extended for expansive clays - this is wrong!!
if(pw >= 0.0)
pw = 0.0;//for positive pressure (suction)
expm = 1.0 - 1.0/lambda0;
fd = pow((1.0-pw/pd),lambdap);
theta = pow(1+(pow((pw/p0),expm)),-lambda0)*fd;
sw = sirr + (ssat - sirr)*theta;
break;
}
case 2:{//extended for expansive clays and temperature dependent - this is wrong!!
if(pw >= 0.0)
pw = 0.0;//for positive pressure (suction)
expm = 1.0 - 1.0/lambda0;
fd = pow((1.0-pw/pd),lambdap);
ft = 1.0;//temp
theta = pow(1+(pow((pw/p0),expm)),-lambda0)*fd*ft;
sw = sirr + (ssat - sirr)*theta;
 
break;
}
default:{
print_err ("unknown van genuchten retention curve type is required", __FILE__, __LINE__, __func__);
abort();
}
}
 
return(sw);
}
 
89,21 → 176,51
*/
double van_genuchten_reten::dsw_dpw(double pw)
{
double dsw_dpw,hp;
double dsw_dpw,hp,fd,theta,dtheta_dpw,dfd_dpw;
pw = pw/1000.0;//in kPa
if(pw >= 0.0){
pw = 0.0;//for positive pressure
dsw_dpw = 0.0;
switch (vg_ret_type){
case 0:{//classical expression
if(pw >= 0.0){
pw = 0.0;//for positive pressure
dsw_dpw = 0.0;
}
else{
hp = pw/gamaw;
if(expm == 0.0)
expm = 1.0 - 1.0/expn;
dsw_dpw = (expm*expn*delta*(ssat - sirr)*pow(delta*fabs(hp),(expn-1)))/(pow(1+(pow(delta*fabs(hp),expn)),(expm+1)))/gamaw;
}
break;
}
else{
hp = pw/gamaw;
if(expm == 0.0)
expm = 1.0 - 1.0/expn;
dsw_dpw = (expm*expn*delta*(ssat - sirr)*pow(delta*fabs(hp),(expn-1)))/(pow(1+(pow(delta*fabs(hp),expn)),(expm+1)))/gamaw;
case 1:{//extended for expansive clays - this is wrong!!
if(pw >= 0.0){
pw = 0.0;//for positive pressure
dsw_dpw = 0.0;
}
else{
expm = 1.0 - 1.0/lambda0;
fd = pow((1.0-pw/pd),lambdap);
theta = pow(1+(pow((pw/p0),expm)),-lambda0);
dtheta_dpw = -lambda0*pow(1+(pow((pw/p0),expm)),-lambda0-1.0)*expm*pow((pw/p0),expm-1);
dfd_dpw = lambdap*pow((1.0-pw/pd),-lambdap-1.0);
dsw_dpw = dtheta_dpw*fd + theta*dfd_dpw;
dsw_dpw = (ssat - sirr)*dsw_dpw;
}
break;
}
case 2:{//extended for expansive clays and temperature dependent
//has to be completed
break;
}
default:{
print_err ("unknown van genuchten retention curve type is required", __FILE__, __LINE__, __func__);
abort();
}
}
 
dsw_dpw = dsw_dpw/1000.0;//basic units are Pa
 
return(dsw_dpw);
121,7 → 238,7
double van_genuchten_reten::dsw_dt(double pw)
{
double dsw_dt;
//has to be completed
dsw_dt = 0.0;
return(dsw_dt);
/trunk/SIFEL/TRFEL/SRC/van_genuchten.h
23,7 → 23,9
double get_k(double pw);
 
private:
long vg_ret_type;
double ssat,sirr,ksat,gamaw,delta,expn,expm;
double p0,pd,lambda0,lambdap;
 
};