17 return (E * nu) / ((1.0 + nu) * (1.0 - 2.0 * nu));
19 return (nu * E) / (1.0 - nu * nu);
24 std::vector<Eigen::Vector3d> read_cell_vectors_legacy_vtk(
25 const std::string &path,
const std::string &field_name)
27 std::ifstream in(path);
31 std::vector<Eigen::Vector3d> out;
36 while (std::getline(in, line))
38 std::istringstream ss(line);
41 if (tok ==
"CELL_DATA")
45 else if (tok ==
"VECTORS")
49 if (name != field_name)
53 out.resize(n_cell_data);
54 for (
int i = 0; i < n_cell_data; ++i)
56 if (!(in >> out[i].
x() >> out[i].
y() >> out[i].
z()))
58 "Fiber VTK '{}' ended early: expected {} vectors", path, n_cell_data));
66 "VECTORS '{}' not found under CELL_DATA in {}", field_name, path));
72 return E / (2.0 * (1.0 + nu));
77 : param_name_(param_name)
83 for (
int i =
param_.size(); i <= index; ++i)
86 param_.back().set_unit_type(unit_type);
99 const double x = p(0);
100 const double y = p(1);
101 const double z = p.size() == 3 ? p(2) : 0;
103 return (*
this)(
x,
y,
z, t, index);
112 return tmp_param(
x,
y,
z, t, index);
116 : param_name_(param_name)
129 for (
int i = 0; i < params_array.size(); ++i)
132 for (
int i = 0; i <
params_.size(); ++i)
134 for (
int j =
params_.at(i).param_.size(); j <= index; ++j)
136 params_.at(i).param_.emplace_back();
137 params_.at(i).param_.back().set_unit_type(unit_type);
140 params_.at(i).param_[index].init(params_array[i], root_path);
190 entries[3], stress_units, root_path);
216 stress_units, root_path);
231 entries[8], stress_units, root_path);
270 (*this)(0, 0) = 2 * mu + lambda;
271 (*this)(0, 1) = lambda;
274 (*this)(1, 1) = 2 * mu + lambda;
281 (*this)(0, 0) = 2 * mu + lambda;
282 (*this)(0, 1) = lambda;
283 (*this)(0, 2) = lambda;
288 (*this)(1, 1) = 2 * mu + lambda;
289 (*this)(1, 2) = lambda;
294 (*this)(2, 2) = 2 * mu + lambda;
316 0.0, 0.0, (1.0 - nu) / 2.0;
324 v, 1. - v, v, 0, 0, 0,
325 v, v, 1. - v, 0, 0, 0,
326 0, 0, 0, (1. - 2. * v) / 2., 0, 0,
327 0, 0, 0, 0, (1. - 2. * v) / 2., 0,
328 0, 0, 0, 0, 0, (1. - 2. * v) / 2.;
334 double Ex,
double Ey,
double Ez,
335 double nuXY,
double nuXZ,
double nuYZ,
336 double muYZ,
double muZX,
double muXY,
const std::string &stress_units,
const std::string &root_path)
341 double nuYX = nuXY * Ey / Ex;
342 double nuZX = nuXZ * Ez / Ex;
343 double nuZY = nuYZ * Ez / Ey;
345 Eigen::MatrixXd compliance;
346 compliance.setZero(6, 6);
347 compliance << 1 / Ex, -nuYX / Ey, -nuZX / Ez, 0, 0, 0,
348 -nuXY / Ex, 1 / Ey, -nuZY / Ez, 0, 0, 0,
349 -nuXZ / Ex, -nuYZ / Ey, 1 / Ez, 0, 0, 0,
350 0, 0, 0, 1 / (2 * muYZ), 0, 0,
351 0, 0, 0, 0, 1 / (2 * muZX), 0,
352 0, 0, 0, 0, 0, 1 / (2 * muXY);
361 double nuYX = nuXY * Ey / Ex;
363 Eigen::MatrixXd compliance;
364 compliance.setZero(3, 3);
365 compliance << 1.0 / Ex, -nuYX / Ey, 0.0,
366 -nuXY / Ex, 1.0 / Ey, 0.0,
367 0.0, 0.0, 1.0 / (2 * muXY);
372 double Et,
double Ea,
373 double nu_t,
double nu_a,
374 double Ga,
const std::string &stress_units,
const std::string &root_path)
379 Eigen::MatrixXd compliance;
380 compliance.setZero(6, 6);
381 compliance << 1 / Et, -nu_t / Et, -nu_a / Ea, 0, 0, 0,
382 -nu_t / Et, 1 / Et, -nu_a / Ea, 0, 0, 0,
383 -nu_a / Ea, -nu_a / Ea, 1 / Ea, 0, 0, 0,
384 0, 0, 0, 1 / Ga, 0, 0,
385 0, 0, 0, 0, 1 / Ga, 0,
386 0, 0, 0, 0, 0, (2 * (1 + nu_t)) / Et;
395 for (
int k = 0; k < DIM; ++k)
396 res += (*
this)(j, k) * strain[k];
432 double llambda = tmp1(
x,
y,
z, t, el_id);
433 double mmu = tmp2(
x,
y,
z, t, el_id);
452 assert(!std::isnan(lambda));
453 assert(!std::isnan(mu));
454 assert(!std::isinf(lambda));
455 assert(!std::isinf(mu));
460 const int size = is_volume ? 3 : 2;
472 if (params.count(
"young"))
474 set_e_nu(index, params[
"young"], params[
"nu"], stress_unit, root_path);
476 else if (params.count(
"E"))
478 set_e_nu(index, params[
"E"], params[
"nu"], stress_unit, root_path);
480 else if (params.count(
"lambda"))
483 mu_or_nu_[index].init(params[
"mu"], root_path);
486 mu_or_nu_[index].set_unit_type(stress_unit);
512 rho_.back().init(1.0);
517 assert(
rho_.size() == 1 || el_id <
rho_.size());
519 const auto &tmp =
rho_.size() == 1 ?
rho_[0] :
rho_[el_id];
520 const double res = tmp(
x,
y,
z, t, el_id);
521 assert(!std::isnan(res));
522 assert(!std::isinf(res));
528 for (
int i =
rho_.size(); i <= index; ++i)
533 if (params.count(
"rho"))
535 rho_[index].init(params[
"rho"], root_path);
537 else if (params.count(
"density"))
539 rho_[index].init(params[
"density"], root_path);
544 rho_[index].set_unit_type(density_unit);
548 : rho_(
"rho"), heat_capacity_(
"heat_capacity")
568 assert(!std::isnan(res));
569 assert(!std::isinf(res));
575 return rho_(p, t, el_id);
589 assert(size == 2 || size == 3);
593 for (
const auto &m :
dir_)
595 assert((m.rows() == size && m.cols() == size) || (m.rows() == size && m.cols() == 1));
600 Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 1, 3, 3>
FiberDirection::operator()(
double px,
double py,
double pz,
double x,
double y,
double z,
double t,
int el_id)
const
606 if (el_id < 0 || el_id >=
static_cast<int>(
per_el_fibers_.size()))
608 "Fiber el_id {} out of range [0,{})", el_id,
per_el_fibers_.size()));
609 Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 1, 3, 3> res;
610 res.resize(
size_, 1);
611 for (
int i = 0; i <
size_; ++i)
616 assert(
dir_.size() == 1 || el_id <
dir_.size());
618 const auto &tmp =
dir_.size() == 1 ?
dir_[0] :
dir_[el_id];
619 Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 1, 3, 3> res;
620 res.resize(tmp.rows(), tmp.cols());
621 for (
int i = 0; i < tmp.rows(); ++i)
623 for (
int j = 0; j < tmp.cols(); ++j)
625 res(i, j) = tmp(i, j)(
x,
y,
z, t, el_id);
627 assert(!std::isnan(res(i, j)));
628 assert(!std::isinf(res(i, j)));
634 Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 1, 6, 6>
FiberDirection::stiffness_rotation_voigt(
double px,
double py,
double pz,
double x,
double y,
double z,
double t,
int el_id)
const
639 Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 1, 3, 3> rot = (*this)(px, py, pz,
x,
y,
z, t, el_id);
640 Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 1, 6, 6> res;
642 int dim = rot.rows();
644 static const double sqrt2 = std::sqrt(2.0);
659 res << rot(0, 0) * rot(0, 0), rot(0, 1) * rot(0, 1), rot(0, 2) * rot(0, 2), sqrt2 * rot(0, 1) * rot(0, 2), sqrt2 * rot(0, 0) * rot(0, 2), sqrt2 * rot(0, 0) * rot(0, 1),
660 rot(1, 0) * rot(1, 0), rot(1, 1) * rot(1, 1), rot(1, 2) * rot(1, 2), sqrt2 * rot(1, 1) * rot(1, 2), sqrt2 * rot(1, 0) * rot(1, 2), sqrt2 * rot(1, 0) * rot(1, 1),
661 rot(2, 0) * rot(2, 0), rot(2, 1) * rot(2, 1), rot(2, 2) * rot(2, 2), sqrt2 * rot(2, 1) * rot(2, 2), sqrt2 * rot(2, 0) * rot(2, 2), sqrt2 * rot(2, 0) * rot(2, 1),
662 sqrt2 * rot(1, 0) * rot(2, 0), sqrt2 * rot(1, 1) * rot(2, 1), sqrt2 * rot(1, 2) * rot(2, 2), rot(1, 1) * rot(2, 2) + rot(1, 2) * rot(2, 1), rot(1, 0) * rot(2, 2) + rot(1, 2) * rot(2, 0), rot(1, 0) * rot(2, 1) + rot(1, 1) * rot(2, 0),
663 sqrt2 * rot(0, 0) * rot(2, 0), sqrt2 * rot(0, 1) * rot(2, 1), sqrt2 * rot(0, 2) * rot(2, 2), rot(0, 1) * rot(2, 2) + rot(0, 2) * rot(2, 1), rot(0, 0) * rot(2, 2) + rot(0, 2) * rot(2, 0), rot(0, 0) * rot(2, 1) + rot(0, 1) * rot(2, 0),
664 sqrt2 * rot(0, 0) * rot(1, 0), sqrt2 * rot(0, 1) * rot(1, 1), sqrt2 * rot(0, 2) * rot(1, 2), rot(0, 1) * rot(1, 2) + rot(0, 2) * rot(1, 1), rot(0, 0) * rot(1, 2) + rot(0, 2) * rot(1, 0), rot(0, 0) * rot(1, 1) + rot(0, 1) * rot(1, 0);
678 if (dir.is_object() && dir.value(
"type", std::string()) ==
"per_element_file")
680 const std::string field = dir.value(
"field", std::string(
"FIB_DIR1"));
686 const double n = v.norm();
693 logger().info(
"FiberDirection: loaded {} per-element fibers ('{}') from {}",
698 for (
int i =
dir_.size(); i <= index; ++i)
703 if (dir.size() == 3 || dir.size() == 2)
705 const int size = dir.size();
706 const int other_size = dir[0].is_array() ? size : 1;
708 assert(size ==
size_);
709 dir_[index].resize(size, other_size);
710 for (
int i = 0; i < size; ++i)
714 if (dir[i].is_array())
716 log_and_throw_error(fmt::format(
"Fiber must be a {} vector, row {} is {}", size, i, dir[i].dump()));
718 dir_[index](i, 0).init(dir[i], root_path);
719 dir_[index](i, 0).set_unit_type(unit);
722 if (dir[i].size() != size)
724 log_and_throw_error(fmt::format(
"Fiber must be {}x{}, row {} is {}", size, other_size, i, dir[i].dump()));
726 for (
int j = 0; j < size; ++j)
728 dir_[index](i, j).init(dir[i][j], root_path);
729 dir_[index](i, j).set_unit_type(unit);
734 else if (dir.size() == 9 || dir.size() == 4)
736 const int size = dir.size() == 9 ? 3 : 2;
737 assert(size ==
size_);
738 dir_[index].resize(size, size);
739 for (
int i = 0; i < size; ++i)
741 for (
int j = 0; j < size; ++j)
743 dir_[index](i, j).init(dir[i * size + j], root_path);
744 dir_[index](i, j).set_unit_type(unit);
749 else if (dir.empty())
752 for (
int i = 0; i <
size_; ++i)
754 for (
int j = 0; j <
size_; ++j)
756 dir_[index](i, j).init(i == j ? 1.0 : 0.0);
757 dir_[index](i, j).set_unit_type(unit);
769 template double ElasticityTensor::compute_stress<3>(
const std::array<double, 3> &strain,
const int j)
const;
770 template double ElasticityTensor::compute_stress<6>(
const std::array<double, 6> &strain,
const int j)
const;
std::vector< Eigen::Triplet< double > > entries
std::vector< utils::ExpressionValue > rho_
virtual double operator()(double px, double py, double pz, double x, double y, double z, double t, int el_id) const
virtual void add_multimaterial(const int index, const json ¶ms, const std::string &density_unit, const std::string &root_path)
double operator()(int i, int j) const
void set_from_young_poisson(const double young, const double poisson, const std::string &stress_unit, const std::string &root_path)
void rotate_stiffness(const Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, 0, 6, 6 > &rotation_mtx_voigt)
void resize(const int size)
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, 0, 6, 6 > stiffness_tensor_
void set_transversely_isotropic(double Et, double Ea, double nu_t, double nu_a, double Ga, const std::string &stress_units, const std::string &root_path)
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, 0, 6, 6 > reference_stiffness_tensor_
void set_orthotropic(double Ex, double Ey, double Ez, double nuXY, double nuXZ, double nuYZ, double muYZ, double muZX, double muXY, const std::string &stress_unit, const std::string &root_path)
double compute_stress(const std::array< double, DIM > &strain, const int j) const
void set_from_entries(const std::vector< double > &entries, const std::string &stress_unit, const std::string &root_path)
void set_from_lambda_mu(const double lambda, const double mu, const std::string &stress_unit, const std::string &root_path)
void unrotate_stiffness()
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, 1, 6, 6 > stiffness_rotation_voigt(double px, double py, double pz, double x, double y, double z, double t, int el_id) const
std::vector< Eigen::Matrix< utils::ExpressionValue, Eigen::Dynamic, Eigen::Dynamic, 1, 3, 3 > > dir_
bool use_per_element_file_
void resize(const int size)
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, 1, 3, 3 > operator()(double px, double py, double pz, double x, double y, double z, double t, int el_id) const
void add_multimaterial(const int index, const json ¶ms, const std::string &unit, const std::string &root_path)
std::vector< Eigen::Vector3d > per_el_fibers_
double operator()(const RowVectorNd &p, double t, int index) const
GenericMatParam(const std::string ¶m_name)
void add_multimaterial(const int index, const json ¶ms, const std::string &unit_type, const std::string &root_path)
std::vector< utils::ExpressionValue > param_
const std::string param_name_
std::vector< GenericMatParam > params_
GenericMatParams(const std::string ¶m_name)
const std::string param_name_
void add_multimaterial(const int index, const json ¶ms, const std::string &unit_type, const std::string &root_path)
std::vector< utils::ExpressionValue > mu_or_nu_
void lambda_mu(double px, double py, double pz, double x, double y, double z, double t, int el_id, double &lambda, double &mu) const
std::vector< utils::ExpressionValue > lambda_or_E_
void set_e_nu(const int index, const json &E, const json &nu, const std::string &stress_unit, const std::string &root_path)
Eigen::MatrixXd lambda_mat_
void add_multimaterial(const int index, const json ¶ms, const bool is_volume, const std::string &stress_unit, const std::string &root_path)
double rho(const RowVectorNd &p, double t, int el_id) const
double heat_capacity(const RowVectorNd &p, double t, int el_id) const
GenericMatParam heat_capacity_
double operator()(double px, double py, double pz, double x, double y, double z, double t, int el_id) const override
void add_multimaterial(const int index, const json ¶ms, const std::string &density_unit, const std::string &root_path) override
constexpr const char * MATERIAL_ELEMENT_INDEX
std::string resolve_path(const std::string &path, const std::string &input_file_path, const bool only_if_exists=false)
std::vector< T > json_as_array(const json &j)
Return the value of a json object as an array.
spdlog::logger & logger()
Retrieves the current logger.
double convert_to_mu(const double E, const double nu)
Eigen::Matrix< double, 1, Eigen::Dynamic, Eigen::RowMajor, 1, 3 > RowVectorNd
double convert_to_lambda(const bool is_volume, const double E, const double nu)
void log_and_throw_error(const std::string &msg)