diff --git a/cmake/check_builtin_expect.cc b/cmake/check_builtin_expect.cc index c1e0fa4e3..3698dbd44 100644 --- a/cmake/check_builtin_expect.cc +++ b/cmake/check_builtin_expect.cc @@ -1,26 +1,26 @@ /** * Copyright (©) 2022-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ #include int main() { if (__builtin_expect(true, 1)) { std::cout << "has __builtin_expect" << std::endl; } } diff --git a/cmake/check_constexpr_map.cc b/cmake/check_constexpr_map.cc index 0c8c2101f..6e7e2bf9c 100644 --- a/cmake/check_constexpr_map.cc +++ b/cmake/check_constexpr_map.cc @@ -1,35 +1,35 @@ /** * Copyright (©) 2022-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ #include #include "aka_constexpr_map.hh" int main() { akantu::details::static_switch_dispatch( std::tuple, std::integral_constant>{}, [](auto && type) { std::cout << std::decay_t::value << std::endl; }, 2, [](auto && /*type*/) { std::cout << "Default" << std::endl; }, std::make_index_sequence<2>{}); } diff --git a/cmake/check_gnu_unlikely.cc b/cmake/check_gnu_unlikely.cc index a567a1ad9..dbf35c049 100644 --- a/cmake/check_gnu_unlikely.cc +++ b/cmake/check_gnu_unlikely.cc @@ -1,26 +1,26 @@ /** * Copyright (©) 2022-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ #include int main() { if (true) [[gnu::likely]] { std::cout << "has __builtin_expect" << std::endl; } } diff --git a/cmake/libakantu/v3/printers.py b/cmake/libakantu/v3/printers.py index 652152366..2210e16fe 100755 --- a/cmake/libakantu/v3/printers.py +++ b/cmake/libakantu/v3/printers.py @@ -1,370 +1,356 @@ #!/usr/bin/env python3 __copyright__ = "Copyright (©) 2016-2023 EPFL (Ecole Polytechnique Fédérale" \ " de Lausanne) Laboratory (LSMS - Laboratoire de Simulation" \ " en Mécanique des Solides)" __license__ = "LGPLv3" -"""printers.py: gdb pretty printers.""" - -__author__ = "Nicolas Richart" -__credits__ = [ - "Nicolas Richart ", -] -__copyright__ = ( - "Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale" - " de Lausanne) Laboratory (LSMS - Laboratoire de Simulation" - " en Mécanique des Solides)" -) -__license__ = "LGPLv3" - - # # Inspired from boost's pretty printers from # Rüdiger Sonderfeld # and from Pretty-printers for libstc++ from Free Software Foundation, Inc. # import gdb import re import itertools try: import gdb.printing except ImportError: raise RuntimeError("Your GDB is too old") class AkantuPrinter(object): regex = None @classmethod def supports(cls, typename): # print('{0} ~= {1}'.format(typename, cls.regex), file=sys.stderr) return cls.regex.search(typename) @classmethod def get_basic_type(cls, value): """Determines the type associated to a value""" _type = value.type # If it points to a reference, get the reference. if _type.code == gdb.TYPE_CODE_REF: _type = _type.target() # Get the unqualified type, stripped of typedefs. _type = _type.unqualified().strip_typedefs() return _type.tag __akantu_pretty_printers__ = \ gdb.printing.RegexpCollectionPrettyPrinter("libakantu-v3") def register_pretty_printer(pretty_printer): """Registers a Pretty Printer""" __akantu_pretty_printers__.add_printer( pretty_printer.name, pretty_printer.regex, pretty_printer ) return pretty_printer @register_pretty_printer class AkaArrayPrinter(AkantuPrinter): """Pretty printer for akantu::Array""" regex = re.compile( "^akantu::Array<(.*?), (true|false)>$|^akantu::ArrayDataLayer<(.*?), \(akantu::ArrayAllocationType\)1>$" # noqa ) name = "akantu::Array" def __init__(self, value): self.typename = self.get_basic_type(value) self.value = value self.ptr = self.value["values"] self.size = int(self.value["size_"]) self.nb_component = int(self.value["nb_component"]) def to_string(self): m = self.regex.search(self.typename) return "Array<{0}>({1}, {2}) stored at {3}".format( m.group(1), self.size, self.nb_component, self.ptr ) def display_hint(self): return "array" def children(self): _ptr = self.ptr for i in range(self.size): for j in range(self.nb_component): yield ("[{0}, {1}]".format(i, j), (_ptr + j).dereference()) _ptr = _ptr + self.nb_component class RbtreeIterator(object): """ Turn an RB-tree-based container (std::map, std::set etc.) into a Python iterable object. """ def __init__(self, rbtree): self.size = rbtree["_M_t"]["_M_impl"]["_M_node_count"] self.node = rbtree["_M_t"]["_M_impl"]["_M_header"]["_M_left"] self.count = 0 def __iter__(self): return self def __len__(self): return int(self.size) def __next__(self): if self.count == self.size: raise StopIteration result = self.node self.count = self.count + 1 if self.count < self.size: # Compute the next node. node = self.node if node.dereference()["_M_right"]: node = node.dereference()["_M_right"] while node.dereference()["_M_left"]: node = node.dereference()["_M_left"] else: parent = node.dereference()["_M_parent"] while node == parent.dereference()["_M_right"]: node = parent parent = parent.dereference()["_M_parent"] if node.dereference()["_M_right"] != parent: node = parent self.node = node return result def get_value_from_aligned_membuf(buf, valtype): """Returns the value held in a __gnu_cxx::__aligned_membuf.""" return buf["_M_storage"].address.cast(valtype.pointer()).dereference() def get_value_from_Rb_tree_node(node): """Returns the value held in an _Rb_tree_node<_Val>""" try: member = node.type.fields()[1].name if member == "_M_value_field": # C++03 implementation, node contains the value as a member return node["_M_value_field"] elif member == "_M_storage": # C++11 implementation, node stores value in __aligned_membuf valtype = node.type.template_argument(0) return get_value_from_aligned_membuf(node["_M_storage"], valtype) except: # noqa: E722 pass raise ValueError("Unsupported implementation for %s" % str(node.type)) def find_type(orig, name): typ = orig.strip_typedefs() while True: # Strip cv-qualifiers. PR 67440. search = "%s::%s" % (typ.unqualified(), name) try: return gdb.lookup_type(search) except RuntimeError: pass # The type was not found, so try the superclass. We only need # to check the first superclass, so we don't bother with # anything fancier here. field = typ.fields()[0] if not field.is_base_class: raise ValueError("Cannot find type %s::%s" % (str(orig), name)) typ = field.type @register_pretty_printer class AkaElementTypeMapArrayPrinter(AkantuPrinter): """Pretty printer for akantu::ElementTypeMap>""" regex = re.compile( "^akantu::ElementTypeMap\*, akantu::(.*?)>$" # noqa ) # noqa: E501,W605 name = "akantu::ElementTypeMapArray" # Turn an RbtreeIterator into a pretty-print iterator. class _rb_iter(object): def __init__(self, rbiter, type, ghost_type): self.rbiter = rbiter self.count = 0 self.type = type self.ghost_type = ghost_type def __iter__(self): return self def __next__(self): if self.count % 2 == 0: n = next(self.rbiter) n = n.cast(self.type).dereference() n = get_value_from_Rb_tree_node(n) self.pair = n item = "{0}:{1}".format(n["first"], self.ghost_type) else: item = self.pair["second"].dereference() result = ("[{0}]".format(self.count), item) self.count = self.count + 1 return result def _iter(self, not_ghost, ghost, type): iter_size = (len(not_ghost), len(ghost)) it = self._rb_iter(not_ghost, type, "_not_ghost") for _ in range(iter_size[0] * 2): yield next(it) it = self._rb_iter(ghost, type, "_ghost") for _ in range(iter_size[1] * 2): yield next(it) raise StopIteration def __init__(self, value): self.typename = self.get_basic_type(value) self.value = value self.data = self.value["data"] self.ghost_data = self.value["ghost_data"] def to_string(self): m = self.regex.search(self.typename) return "ElementTypMapArray<{0}> with " "{1} _not_ghost and {2} _ghost".format( # noqa m.group(1), len(RbtreeIterator(self.data)), len(RbtreeIterator(self.ghost_data))) def children(self): # m = self.regex.search(self.typename) rep_type = find_type(self.data.type, "_Rep_type") node = find_type(rep_type, "_Link_type") node = node.strip_typedefs() return itertools.chain( self._rb_iter(RbtreeIterator(self.data), node, "_not_ghost"), self._rb_iter(RbtreeIterator(self.ghost_data), node, "_ghost"), ) def display_hint(self): return "map" # @register_pretty_printer class AkaTensorPrinter(AkantuPrinter): """Pretty printer for akantu::Tensor""" regex = re.compile("^akantu::Tensor<(.*), +(.*), +(.*)>$") name = "akantu::Tensor" value = None typename = "" ptr = None dims = [] ndims = 0 def pretty_print(self): def ij2str(i, j, m): return "{0}".format((self.ptr + m * j + i).dereference()) def line(i, m, n): return "[{0}]".format( ", ".join((ij2str(i, j, m) for j in range(n)))) m = int(self.dims[0]) if self.ndims == 1: n = 1 else: n = int(self.dims[1]) return "[{0}]".format(", ".join(line(i, m, n) for i in range(m))) def __init__(self, value): self.typename = self.get_basic_type(value) self.value = value self.ptr = self.value["values"] self.dims = self.value["n"] def children(self): yield ("values", self.pretty_print()) yield ("wrapped", self.value["wrapped"]) @register_pretty_printer class AkaVectorPrinter(AkaTensorPrinter): """Pretty printer for akantu::Vector""" regex = re.compile("^akantu::Vector<(.*)>$") name = "akantu::Vector" n = 0 ptr = 0x0 def __init__(self, value): super(AkaVectorPrinter, self).__init__(value) self.ndims = 1 def to_string(self): m = self.regex.search(self.typename) return "Vector<{0}>({1}) [{2}]".format( m.group(1), int(self.dims[0]), str(self.ptr) ) @register_pretty_printer class AkaMatrixPrinter(AkaTensorPrinter): """Pretty printer for akantu::Matrix.""" regex = re.compile("^akantu::Matrix<(.*)>$") name = "akantu::Matrix" def __init__(self, value): super(AkaMatrixPrinter, self).__init__(value) self.ndims = 2 def to_string(self): m = self.regex.search(self.typename) return "Matrix<%s>(%d, %d) [%s]" % ( m.group(1), int(self.dims[0]), int(self.dims[1]), str(self.ptr), ) @register_pretty_printer class AkaElementPrinter(AkantuPrinter): """Pretty printer for akantu::Element.""" regex = re.compile("^akantu::Element$") name = "akantu::Element" def __init__(self, value): self.typename = self.get_basic_type(value) self.value = value self.element = self.value["element"] self.eltype = self.value["type"] self.ghost_type = self.value["ghost_type"] self._ek_not_defined = gdb.parse_and_eval("akantu::_not_defined") self._casper = gdb.parse_and_eval("akantu::_casper") self._max_uint = gdb.parse_and_eval("(akantu::Int) -1") def to_string(self): if ( (self.element == self._max_uint) and (self.eltype == self._ek_not_defined) and (self.ghost_type == self._casper) ): return "ElementNull" return "Element({0}, {1}, {2})".format( self.element, self.eltype, self.ghost_type ) def register_akantu_printers(obj): """Register Akantu Pretty Printers.""" gdb.printing.register_pretty_printer(obj, __akantu_pretty_printers__) diff --git a/cmake/material_lister.cc b/cmake/material_lister.cc index 8dbc28da3..1b8cc7c91 100644 --- a/cmake/material_lister.cc +++ b/cmake/material_lister.cc @@ -1,43 +1,43 @@ /** * Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "material_list.hh" #include #include int main(__attribute__((unused)) int argc, __attribute__((unused)) char * argv[]) { #define PRINT_OUT_OPTIONS(r, data, i, elem) \ << ":" << BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 0, elem)) #define PRINT_OUT(r, data, elem) \ std::cout << BOOST_PP_STRINGIZE(BOOST_PP_ARRAY_ELEM(0, elem)) << ":" \ << BOOST_PP_STRINGIZE(BOOST_PP_ARRAY_ELEM(1, elem)) BOOST_PP_IF( \ BOOST_PP_EQUAL(3, BOOST_PP_ARRAY_SIZE(elem)), \ BOOST_PP_SEQ_FOR_EACH_I(PRINT_OUT_OPTIONS, _, \ BOOST_PP_ARRAY_ELEM(2, elem)), ) \ << std::endl; BOOST_PP_SEQ_FOR_EACH(PRINT_OUT, "toto", AKANTU_MATERIAL_LIST); return 0; } diff --git a/cmake/semver.py b/cmake/semver.py index d39f08480..19c3c06c5 100644 --- a/cmake/semver.py +++ b/cmake/semver.py @@ -1,240 +1,239 @@ #!/usr/bin/env python3 __copyright__ = "Copyright (©) 2022-2023 EPFL (Ecole Polytechnique Fédérale" \ " de Lausanne) Laboratory (LSMS - Laboratoire de Simulation" \ " en Mécanique des Solides)" __license__ = "LGPLv3" -"""module to get the VERSION from a git repository.""" + import os import re import sys import subprocess def run_git_command(args): """Run git commands and capture outputs.""" git_dir = os.path.realpath( os.path.join(os.path.dirname(__file__), os.pardir)) cmd = ["git"] + args p = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=git_dir ) stdout = p.communicate()[0].strip().decode() if p.returncode != 0: return None, p.returncode return stdout, p.returncode def _split_git_describe(describe): describe_mo = re.search( r"^(?P.+)" r"-(?P\d+)" r"-g(?P[0-9a-f]+)" r"(-(?Pdirty))?$", describe, ) if describe_mo: pieces = {} pieces["tag"] = describe_mo.group("tag") # distance: number of commits since tag pieces["distance"] = int(describe_mo.group("distance")) # commit: short hex revision ID pieces["short"] = describe_mo.group("short") if describe_mo.group("dirty"): pieces["dirty"] = describe_mo.group("dirty") return pieces return None def _eprint(*args, **kwargs): print(*args, file=sys.stderr, **kwargs) semver_re = re.compile( r"^(?P0|[1-9]\d*)" r"(\.(?P0|[1-9]\d*))?" r"(\.(?P0|[1-9]\d*))?" r"(?:-(?P(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)" r"(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?" r"(?:\+(?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$" ) def _parse_semver(version): semver_mo = semver_re.search(version) if not semver_mo: return {} pieces = {} for p in ["major", "minor", "patch", "prerelease", "build"]: if semver_mo.group(p): pieces[p] = semver_mo.group(p) return pieces def get_git_version(): """Get the version from the git repository.""" out, rc = run_git_command(["rev-parse", "--git-dir"]) if rc != 0: return None git_describe, rc = run_git_command( ["describe", "--tags", "--dirty", "--always", "--match", "v*"] ) _eprint(f"git describe {git_describe}") if "-g" in git_describe: # TAG-DISTANCE-gHEX pieces = _split_git_describe(git_describe) else: # tag only or no tag and hash pieces = {"tag": git_describe} # major.minor.patch-prerelease+build if not pieces or ("tag" not in pieces): return None semver_mo = semver_re.search(pieces["tag"][1:]) if not semver_mo: return pieces for p in ["major", "minor", "patch", "prerelease", "build"]: if semver_mo.group(p): pieces[p] = semver_mo.group(p) return pieces def get_git_attributes_version(): """Get the version from the attributes set a `git archive`.""" file_dir = os.path.dirname(os.path.realpath(os.path.abspath(__file__))) attributes = None pieces = None with open(os.path.join(file_dir, "git_info")) as fh: describe_re = re.compile(r"describe: ([^$].*[^$])") for line in fh: mo = describe_re.search(line) if mo: attributes = mo.group(1) break if attributes: pieces = _split_git_describe(attributes) return pieces def get_ci_version(): """Get extra information from CI context.""" pieces = None if "CI_AKANTU_INSTALL_PREFIX" not in os.environ: return None ci_akantu_install_prefix = os.environ["CI_AKANTU_INSTALL_PREFIX"] akantu_dir = os.path.join(ci_akantu_install_prefix, "lib", "cmake", "Akantu") cmake_config = os.path.join(akantu_dir, "AkantuConfig.cmake") if not os.path.exists(cmake_config): return None version = None with open(cmake_config, "r") as fh: version_re = re.compile(r"^set\(AKANTU_VERSION (.*)\)$") for line in fh: version_mo = version_re.search(line) if version_mo: version = version_mo.group(1) break if not version: return None pieces = _parse_semver(version) return pieces def get_version_file(): """Get the version directly from the VERSION file.""" version_path = os.path.join( os.path.realpath( os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir)) ), "VERSION", ) if not os.path.exists(version_path): return None version = None with open(version_path, "r") as fh: version = fh.readline() if not version: return None pieces = _parse_semver(version) return pieces def get_version(): """Combine all the version determination functions.""" pieces = None if not pieces: pieces = get_ci_version() _eprint(f"pieces from ci_version: {pieces}") if not pieces: pieces = get_git_version() _eprint(f"pieces from git_version: {pieces}") if not pieces: pieces = get_git_attributes_version() _eprint(f"pieces from git attributes: {pieces}") if not pieces: pieces = get_version_file() _eprint(f"pieces from version file: {pieces}") if not pieces: raise Exception("No version could be determined") semver_build = [] if "build" in pieces: semver_build = [pieces["build"]] if "distance" in pieces: semver_build.extend([str(pieces["distance"]), "g" + pieces["short"]]) if "dirty" in pieces and pieces["dirty"]: semver_build.append(pieces["dirty"]) if semver_build: pieces["build_part"] = "+" + ".".join(semver_build) else: pieces["build_part"] = "" if "prerelease" in pieces: pieces["prerelease"] = "-" + pieces["prerelease"] else: pieces["prerelease"] = "" semver = "{major}.{minor}.{patch}{prerelease}{build_part}".format(**pieces) if "CI_MERGE_REQUEST_ID" in os.environ: semver = "{}.mr{}".format(semver, os.environ["CI_MERGE_REQUEST_ID"]) return semver if __name__ == "__main__": print(get_version()) - diff --git a/examples/boundary_conditions/predefined_bc/predefined_bc.cc b/examples/boundary_conditions/predefined_bc/predefined_bc.cc index 3f0dea6ff..b1ac57964 100644 --- a/examples/boundary_conditions/predefined_bc/predefined_bc.cc +++ b/examples/boundary_conditions/predefined_bc/predefined_bc.cc @@ -1,52 +1,52 @@ /** * Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char * argv[]) { initialize("material.dat", argc, argv); Mesh mesh(2); mesh.read("square.msh"); // model initialization SolidMechanicsModel model(mesh); model.initFull(); // Dirichlet boundary conditions model.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "Fixed_x"); model.applyBC(BC::Dirichlet::FixedValue(0.0, _y), "Fixed_y"); // output in a paraview file model.setBaseName("plate"); model.addDumpFieldVector("displacement"); model.addDumpField("blocked_dofs"); model.addDumpField("external_force"); model.dump(); finalize(); return EXIT_SUCCESS; } diff --git a/examples/boundary_conditions/python_user_defined_bc/python_user_defined_bc.cc b/examples/boundary_conditions/python_user_defined_bc/python_user_defined_bc.cc index 9b58320bc..2b20b484b 100644 --- a/examples/boundary_conditions/python_user_defined_bc/python_user_defined_bc.cc +++ b/examples/boundary_conditions/python_user_defined_bc/python_user_defined_bc.cc @@ -1,86 +1,86 @@ /** * Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "py_aka_array.hh" #include "solid_mechanics_model.hh" /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ namespace py = pybind11; /* -------------------------------------------------------------------------- */ using namespace akantu; class PYBIND11_EXPORT SineBoundary : public BC::Dirichlet::DirichletFunctor { public: SineBoundary(Real amplitude, Real phase) { py_module = py::module::import("boundary_condition"); py_sin_boundary = py_module.attr("SinBoundary")(amplitude, phase); } public: inline void operator()(__attribute__((unused)) UInt node, Vector & flags, Vector & primal, const Vector & coord) const { py_sin_boundary.attr("compute")(primal, coord, flags); } protected: py::object py_sin_boundary; py::module py_module; }; /* -------------------------------------------------------------------------- */ int main(int argc, char * argv[]) { initialize("material.dat", argc, argv); py::scoped_interpreter guard{}; Int spatial_dimension = 2; Mesh mesh(spatial_dimension); mesh.read("fine_mesh.msh"); SolidMechanicsModel model(mesh); /// model initialization model.initFull(); /// boundary conditions Vector traction(2, 0.2); SineBoundary sin_boundary(.2, 10.); model.applyBC(sin_boundary, "Fixed_x"); model.applyBC(BC::Dirichlet::FixedValue(0., _y), "Fixed_y"); model.applyBC(BC::Neumann::FromTraction(traction), "Traction"); // output a paraview file with the boundary conditions model.setBaseName("plate"); model.addDumpFieldVector("displacement"); model.addDumpFieldVector("external_force"); model.addDumpField("blocked_dofs"); model.dump(); finalize(); return EXIT_SUCCESS; } diff --git a/examples/boundary_conditions/user_defined_bc/user_defined_bc.cc b/examples/boundary_conditions/user_defined_bc/user_defined_bc.cc index 51b576307..e805b5f61 100644 --- a/examples/boundary_conditions/user_defined_bc/user_defined_bc.cc +++ b/examples/boundary_conditions/user_defined_bc/user_defined_bc.cc @@ -1,78 +1,78 @@ /** * Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model.hh" /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ using namespace akantu; class SineBoundary : public BC::Dirichlet::DirichletFunctor { public: SineBoundary(Real amp, Real phase, BC::Axis ax = _x) : DirichletFunctor(ax), amplitude(amp), phase(phase) {} public: inline void operator()(__attribute__((unused)) UInt node, Vector & flags, Vector & primal, const Vector & coord) const { DIRICHLET_SANITY_CHECK; flags(axis) = true; primal(axis) = -amplitude * std::sin(phase * coord(1)); } protected: Real amplitude; Real phase; }; /* -------------------------------------------------------------------------- */ int main(int argc, char * argv[]) { initialize("material.dat", argc, argv); Int spatial_dimension = 2; Mesh mesh(spatial_dimension); mesh.read("fine_mesh.msh"); SolidMechanicsModel model(mesh); /// model initialization model.initFull(); /// boundary conditions Vector traction{.2, .2}; model.applyBC(SineBoundary(.2, 10., _x), "Fixed_x"); model.applyBC(BC::Dirichlet::FixedValue(0., _y), "Fixed_y"); model.applyBC(BC::Neumann::FromTraction(traction), "Traction"); // output a paraview file with the boundary conditions model.setBaseName("plate"); model.addDumpFieldVector("displacement"); model.addDumpFieldVector("external_force"); model.addDumpField("blocked_dofs"); model.dump(); finalize(); return EXIT_SUCCESS; } diff --git a/examples/cohesive_element/cohesive_extrinsic/cohesive_extrinsic.cc b/examples/cohesive_element/cohesive_extrinsic/cohesive_extrinsic.cc index 2704a87d9..5c455e103 100644 --- a/examples/cohesive_element/cohesive_extrinsic/cohesive_extrinsic.cc +++ b/examples/cohesive_element/cohesive_extrinsic/cohesive_extrinsic.cc @@ -1,118 +1,118 @@ /** * Copyright (©) 2012-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model_cohesive.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char * argv[]) { initialize("material.dat", argc, argv); const Int spatial_dimension = 2; const Int max_steps = 1000; Mesh mesh(spatial_dimension); mesh.read("triangle.msh"); SolidMechanicsModelCohesive model(mesh); /// model initialization model.initFull(_analysis_method = _explicit_lumped_mass, _is_extrinsic = true); Real time_step = model.getStableTimeStep() * 0.05; model.setTimeStep(time_step); std::cout << "Time step: " << time_step << std::endl; CohesiveElementInserter & inserter = model.getElementInserter(); inserter.setLimit(_y, 0.30, 0.20); model.updateAutomaticInsertion(); Array & position = mesh.getNodes(); Array & velocity = model.getVelocity(); Array & boundary = model.getBlockedDOFs(); Array & displacement = model.getDisplacement(); Int nb_nodes = mesh.getNbNodes(); /// boundary conditions for (Int n = 0; n < nb_nodes; ++n) { if (position(n, 1) > 0.99 || position(n, 1) < -0.99) { boundary(n, 1) = true; } if (position(n, 0) > 0.99 || position(n, 0) < -0.99) { boundary(n, 0) = true; } } model.setBaseName("extrinsic"); model.addDumpFieldVector("displacement"); model.addDumpField("velocity"); model.addDumpField("acceleration"); model.addDumpField("internal_force"); model.addDumpField("stress"); model.addDumpField("grad_u"); model.dump(); /// initial conditions Real loading_rate = 0.5; Real disp_update = loading_rate * time_step; for (Int n = 0; n < nb_nodes; ++n) { velocity(n, 1) = loading_rate * position(n, 1); } /// Main loop for (Int s = 1; s <= max_steps; ++s) { /// update displacement on extreme nodes for (Int n = 0; n < nb_nodes; ++n) { if (position(n, 1) > 0.99 || position(n, 1) < -0.99) { displacement(n, 1) += disp_update * position(n, 1); } } model.checkCohesiveStress(); model.solveStep(); if (s % 10 == 0) { model.dump(); std::cout << "passing step " << s << "/" << max_steps << std::endl; } } Real Ed = model.getEnergy("dissipated"); Real Edt = 200 * std::sqrt(2); std::cout << Ed << " " << Edt << std::endl; if (Ed < Edt * 0.999 || Ed > Edt * 1.001 || std::isnan(Ed)) { std::cout << "The dissipated energy is incorrect" << std::endl; return EXIT_FAILURE; } finalize(); return EXIT_SUCCESS; } diff --git a/examples/cohesive_element/cohesive_extrinsic_ig_tg/cohesive_extrinsic_ig_tg.cc b/examples/cohesive_element/cohesive_extrinsic_ig_tg/cohesive_extrinsic_ig_tg.cc index 421ff17ce..eb5110fb7 100644 --- a/examples/cohesive_element/cohesive_extrinsic_ig_tg/cohesive_extrinsic_ig_tg.cc +++ b/examples/cohesive_element/cohesive_extrinsic_ig_tg/cohesive_extrinsic_ig_tg.cc @@ -1,141 +1,141 @@ /** * Copyright (©) 2014-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model_cohesive.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ using namespace akantu; /* -------------------------------------------------------------------------- */ class Velocity : public BC::Dirichlet::DirichletFunctor { public: explicit Velocity(SolidMechanicsModel & model, Real vel, BC::Axis ax = _x) : DirichletFunctor(ax), model(model), vel(vel) { disp = vel * model.getTimeStep(); } public: inline void operator()(UInt node, Vector & /*flags*/, Vector & disp, const Vector & coord) const { Real sign = std::signbit(coord(axis)) ? -1. : 1.; disp(axis) += sign * this->disp; model.getVelocity()(node, axis) = sign * vel; } private: SolidMechanicsModel & model; Real vel, disp; }; /* -------------------------------------------------------------------------- */ int main(int argc, char * argv[]) { initialize("material.dat", argc, argv); const Int spatial_dimension = 2; const Int max_steps = 1000; Mesh mesh(spatial_dimension); mesh.read("square.msh"); SolidMechanicsModelCohesive model(mesh); MaterialCohesiveRules rules{{{"btop", "bbottom"}, "tg_cohesive"}, {{"btop", "btop"}, "ig_cohesive"}, {{"bbottom", "bbottom"}, "ig_cohesive"}}; /// model initialization auto cohesive_material_selector = std::make_shared(model, rules); auto bulk_material_selector = std::make_shared>("physical_names", model); auto && current_selector = model.getMaterialSelector(); cohesive_material_selector->setFallback(bulk_material_selector); bulk_material_selector->setFallback(current_selector); model.setMaterialSelector(cohesive_material_selector); model.initFull(_analysis_method = _explicit_lumped_mass, _is_extrinsic = true); Real time_step = model.getStableTimeStep() * 0.05; model.setTimeStep(time_step); std::cout << "Time step: " << time_step << std::endl; model.assembleMassLumped(); auto & position = mesh.getNodes(); auto & velocity = model.getVelocity(); model.applyBC(BC::Dirichlet::FlagOnly(_y), "top"); model.applyBC(BC::Dirichlet::FlagOnly(_y), "bottom"); model.applyBC(BC::Dirichlet::FlagOnly(_x), "left"); model.applyBC(BC::Dirichlet::FlagOnly(_x), "right"); model.setBaseName("extrinsic"); model.addDumpFieldVector("displacement"); model.addDumpField("velocity"); model.addDumpField("acceleration"); model.addDumpField("internal_force"); model.addDumpField("stress"); model.addDumpField("grad_u"); model.addDumpField("material_index"); model.dump(); /// initial conditions Real loading_rate = 0.1; // bar_height = 2 Real VI = loading_rate * 2 * 0.5; for (auto && data : zip(make_view(position, spatial_dimension), make_view(velocity, spatial_dimension))) { std::get<1>(data) = loading_rate * std::get<0>(data); } model.dump(); Velocity vely(model, VI, _y); Velocity velx(model, VI, _x); /// Main loop for (Int s = 1; s <= max_steps; ++s) { model.applyBC(vely, "top"); model.applyBC(vely, "bottom"); model.applyBC(velx, "left"); model.applyBC(velx, "right"); model.checkCohesiveStress(); model.solveStep(); if (s % 10 == 0) { model.dump(); std::cout << "passing step " << s << "/" << max_steps << std::endl; } } return 0; } diff --git a/examples/cohesive_element/cohesive_intrinsic/cohesive_intrinsic.cc b/examples/cohesive_element/cohesive_intrinsic/cohesive_intrinsic.cc index fc673bd3b..0c760b0ea 100644 --- a/examples/cohesive_element/cohesive_intrinsic/cohesive_intrinsic.cc +++ b/examples/cohesive_element/cohesive_intrinsic/cohesive_intrinsic.cc @@ -1,127 +1,127 @@ /** * Copyright (©) 2012-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "element_group.hh" #include "mesh_iterators.hh" #include "solid_mechanics_model_cohesive.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ using namespace akantu; static void updateDisplacement(SolidMechanicsModelCohesive &, const ElementGroup &, Real); /* -------------------------------------------------------------------------- */ int main(int argc, char * argv[]) { initialize("material.dat", argc, argv); const Int spatial_dimension = 2; const Int max_steps = 350; Mesh mesh(spatial_dimension); mesh.read("triangle.msh"); SolidMechanicsModelCohesive model(mesh); model.getElementInserter().setLimit(_x, -0.26, -0.24); /// model initialization model.initFull(_analysis_method = _explicit_lumped_mass, _is_extrinsic = false); Real time_step = model.getStableTimeStep() * 0.8; model.setTimeStep(time_step); std::cout << "Time step: " << time_step << std::endl; Array & boundary = model.getBlockedDOFs(); Int nb_nodes = mesh.getNbNodes(); /// boundary conditions for (Int dim = 0; dim < spatial_dimension; ++dim) { for (Int n = 0; n < nb_nodes; ++n) { boundary(n, dim) = true; } } model.setBaseName("intrinsic"); model.addDumpFieldVector("displacement"); model.addDumpField("velocity"); model.addDumpField("acceleration"); model.addDumpField("stress"); model.addDumpField("grad_u"); model.addDumpField("external_force"); model.addDumpField("internal_force"); model.dump(); /// update displacement auto && elements = mesh.createElementGroup("diplacement"); Vector barycenter(spatial_dimension); for_each_element( mesh, [&](auto && el) { mesh.getBarycenter(el, barycenter); if (barycenter(_x) > -0.25) elements.add(el, true); }, _element_kind = _ek_regular); Real increment = 0.01; updateDisplacement(model, elements, increment); /// Main loop for (Int s = 1; s <= max_steps; ++s) { model.solveStep(); updateDisplacement(model, elements, increment); if (s % 1 == 0) { model.dump(); std::cout << "passing step " << s << "/" << max_steps << std::endl; } } Real Ed = model.getEnergy("dissipated"); Real Edt = 2 * sqrt(2); std::cout << Ed << " " << Edt << std::endl; if (Ed < Edt * 0.999 || Ed > Edt * 1.001 || std::isnan(Ed)) { std::cout << "The dissipated energy is incorrect" << std::endl; return EXIT_FAILURE; } finalize(); return EXIT_SUCCESS; } /* -------------------------------------------------------------------------- */ static void updateDisplacement(SolidMechanicsModelCohesive & model, const ElementGroup & group, Real increment) { Array & displacement = model.getDisplacement(); for (auto && node : group.getNodeGroup().getNodes()) { displacement(node, 0) += increment; } } diff --git a/examples/contact_mechanics/cohesive_contact_explicit_dynamic.cc b/examples/contact_mechanics/cohesive_contact_explicit_dynamic.cc index 379def871..6f0ba6b25 100644 --- a/examples/contact_mechanics/cohesive_contact_explicit_dynamic.cc +++ b/examples/contact_mechanics/cohesive_contact_explicit_dynamic.cc @@ -1,148 +1,148 @@ /** * Copyright (©) 2021-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "contact_mechanics_model.hh" #include "coupler_solid_cohesive_contact.hh" #include "solid_mechanics_model_cohesive.hh" #include "surface_selector.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char * argv[]) { const Int spatial_dimension = 2; initialize("material-cohesive.dat", argc, argv); Real time_step{0.}; Real time_factor = 0.1; UInt max_steps = 25000; Real max_displacement = 1e-3; Mesh mesh(spatial_dimension); mesh.read("cohesive-contact.msh"); CouplerSolidCohesiveContact coupler(mesh); auto & solid = coupler.getSolidMechanicsModelCohesive(); auto & contact = coupler.getContactMechanicsModel(); auto && material_selector = std::make_shared(solid); material_selector->setFallback(solid.getMaterialSelector()); solid.setMaterialSelector(material_selector); auto && surface_selector = std::make_shared(mesh); contact.getContactDetector().setSurfaceSelector(surface_selector); coupler.initFull(_analysis_method = _explicit_lumped_mass, _is_extrinsic = true); coupler.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "sides"); time_step = solid.getStableTimeStep(); time_step *= time_factor; std::cout << "Time Step = " << time_step << "s (" << time_step << "s)" << std::endl; coupler.setTimeStep(time_step); coupler.setBaseName("cohesive-contact-explicit-dynamic"); coupler.addDumpFieldVector("displacement"); coupler.addDumpFieldVector("velocity"); coupler.addDumpFieldVector("normals"); coupler.addDumpField("blocked_dofs"); coupler.addDumpField("grad_u"); coupler.addDumpField("stress"); coupler.addDumpField("gaps"); coupler.addDumpField("areas"); auto & velocity = solid.getVelocity(); auto & gaps = contact.getGaps(); Real damping_ratio = 0.99; auto increment = max_displacement / max_steps; for (auto i : arange(max_steps)) { coupler.applyBC(BC::Dirichlet::IncrementValue(increment, _y), "loading"); coupler.applyBC(BC::Dirichlet::IncrementValue(-increment, _y), "fixed"); coupler.solveStep(); solid.checkCohesiveStress(); // damping velocities only along the contacting zone for (auto && tuple : zip(gaps, make_view(velocity, spatial_dimension))) { auto & gap = std::get<0>(tuple); auto & vel = std::get<1>(tuple); if (gap > 0) { vel *= damping_ratio; } } // dumping energies if (i % 1000 == 0) { Real epot = solid.getEnergy("potential"); Real ekin = solid.getEnergy("kinetic"); std::cerr << i << "," << i * increment << "," << epot << "," << ekin << "," << epot + ekin << "," << std::endl; } if (i % 1000 == 0) { coupler.dump(); } } for (auto i : arange(max_steps)) { solid.applyBC(BC::Dirichlet::IncrementValue(-increment, _y), "loading"); solid.applyBC(BC::Dirichlet::IncrementValue(increment, _y), "fixed"); coupler.solveStep(); coupler.checkCohesiveStress(); // damping velocities only along the contacting zone for (auto && tuple : zip(gaps, make_view(velocity, spatial_dimension))) { auto & gap = std::get<0>(tuple); auto & vel = std::get<1>(tuple); if (gap > 0) { vel *= damping_ratio; } } // dumping energies if (i % 1000 == 0) { Real epot = solid.getEnergy("potential"); Real ekin = solid.getEnergy("kinetic"); std::cerr << i << "," << i * increment << "," << epot << "," << ekin << "," << epot + ekin << "," << std::endl; } if (i % 1000 == 0) { coupler.dump(); } } } diff --git a/examples/contact_mechanics/contact_explicit_dynamic.cc b/examples/contact_mechanics/contact_explicit_dynamic.cc index 422527458..03e7fb776 100644 --- a/examples/contact_mechanics/contact_explicit_dynamic.cc +++ b/examples/contact_mechanics/contact_explicit_dynamic.cc @@ -1,121 +1,121 @@ /** * Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "contact_mechanics_model.hh" #include "coupler_solid_contact.hh" #include "non_linear_solver.hh" #include "solid_mechanics_model.hh" #include "surface_selector.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; /* -------------------------------------------------------------------------- */ int main(int argc, char * argv[]) { const Int spatial_dimension = 2; initialize("material.dat", argc, argv); Real time_step; Real time_factor = 0.1; UInt max_steps = 20000; Real max_displacement = 5e-3; Mesh mesh(spatial_dimension); mesh.read("hertz.msh"); CouplerSolidContact coupler(mesh); auto & solid = coupler.getSolidMechanicsModel(); auto & contact = coupler.getContactMechanicsModel(); auto && selector = std::make_shared>( "physical_names", solid); solid.setMaterialSelector(selector); coupler.initFull(_analysis_method = _explicit_lumped_mass); auto && surface_selector = std::make_shared(mesh); contact.getContactDetector().setSurfaceSelector(surface_selector); solid.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "fixed"); solid.applyBC(BC::Dirichlet::FixedValue(0.0, _y), "fixed"); solid.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "loading"); solid.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "symmetry"); time_step = solid.getStableTimeStep(); time_step *= time_factor; std::cout << "Time Step = " << time_step << "s (" << time_step << "s)" << std::endl; coupler.setTimeStep(time_step); coupler.setBaseName("contact-explicit-dynamic"); coupler.addDumpFieldVector("displacement"); coupler.addDumpFieldVector("velocity"); coupler.addDumpFieldVector("normals"); coupler.addDumpFieldVector("contact_force"); coupler.addDumpFieldVector("external_force"); coupler.addDumpFieldVector("internal_force"); coupler.addDumpField("gaps"); coupler.addDumpField("areas"); coupler.addDumpField("blocked_dofs"); coupler.addDumpField("grad_u"); coupler.addDumpField("stress"); auto & velocity = solid.getVelocity(); auto & gaps = contact.getGaps(); Real damping_ratio = 0.99; auto increment = max_displacement / max_steps; for (auto i : arange(max_steps)) { solid.applyBC(BC::Dirichlet::IncrementValue(-increment, _y), "loading"); coupler.solveStep(); // damping velocities only along the contacting zone for (auto && tuple : zip(gaps, make_view(velocity, spatial_dimension))) { auto & gap = std::get<0>(tuple); auto & vel = std::get<1>(tuple); if (gap > 0) { vel *= damping_ratio; } } // dumping energies if (i % 1000 == 0) { Real epot = solid.getEnergy("potential"); Real ekin = solid.getEnergy("kinetic"); std::cerr << i << "," << i * increment << "," << epot << "," << ekin << "," << epot + ekin << "," << std::endl; } if (i % 1000 == 0) { coupler.dump(); } } finalize(); return EXIT_SUCCESS; } diff --git a/examples/contact_mechanics/contact_explicit_static.cc b/examples/contact_mechanics/contact_explicit_static.cc index 7b6b33f8f..6ebd407cc 100644 --- a/examples/contact_mechanics/contact_explicit_static.cc +++ b/examples/contact_mechanics/contact_explicit_static.cc @@ -1,84 +1,84 @@ /** * Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "contact_mechanics_model.hh" #include "coupler_solid_contact.hh" #include "non_linear_solver.hh" #include "solid_mechanics_model.hh" #include "surface_selector.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; /* -------------------------------------------------------------------------- */ int main(int argc, char * argv[]) { const Int spatial_dimension = 2; initialize("material.dat", argc, argv); Mesh mesh(spatial_dimension); mesh.read("hertz.msh"); CouplerSolidContact coupler(mesh); auto & solid = coupler.getSolidMechanicsModel(); auto & contact = coupler.getContactMechanicsModel(); auto && selector = std::make_shared>( "physical_names", solid); solid.setMaterialSelector(selector); coupler.initFull(_analysis_method = _static); auto && surface_selector = std::make_shared(mesh); contact.getContactDetector().setSurfaceSelector(surface_selector); coupler.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "fixed"); coupler.applyBC(BC::Dirichlet::FixedValue(0.0, _y), "fixed"); coupler.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "loading"); coupler.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "symmetry"); coupler.setBaseName("contact-explicit-static"); coupler.addDumpFieldVector("displacement"); coupler.addDumpFieldVector("normals"); coupler.addDumpFieldVector("contact_force"); coupler.addDumpFieldVector("external_force"); coupler.addDumpFieldVector("internal_force"); coupler.addDumpField("gaps"); coupler.addDumpField("areas"); coupler.addDumpField("blocked_dofs"); coupler.addDumpField("grad_u"); coupler.addDumpField("stress"); auto max_steps = 100u; for (auto _ [[gnu::unused]] : arange(max_steps)) { auto increment = 1e-4; coupler.applyBC(BC::Dirichlet::IncrementValue(-increment, _y), "loading"); coupler.solveStep(); coupler.dump(); } finalize(); return EXIT_SUCCESS; } diff --git a/examples/embedded/embedded.cc b/examples/embedded/embedded.cc index 826f7e978..e699a5eb7 100644 --- a/examples/embedded/embedded.cc +++ b/examples/embedded/embedded.cc @@ -1,88 +1,88 @@ /** * Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "embedded_interface_model.hh" #include "non_linear_solver.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char * argv[]) { initialize("material.dat", argc, argv); const Int dim = 2; // Loading the concrete mesh Mesh mesh(dim); mesh.read("concrete.msh"); // Loading the reinforcement mesh Mesh reinforcement_mesh(dim, "reinforcement_mesh"); // Exception is raised because reinforcement // mesh contains only segments, i.e. 1D elements try { reinforcement_mesh.read("reinforcement.msh"); } catch (debug::Exception & e) { } // Model creation EmbeddedInterfaceModel model(mesh, reinforcement_mesh, dim); model.initFull(EmbeddedInterfaceModelOptions(_static)); // Boundary conditions model.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "XBlocked"); model.applyBC(BC::Dirichlet::FixedValue(0.0, _y), "YBlocked"); Vector force(dim); force(0) = 0.0; force(1) = -1.0; model.applyBC(BC::Neumann::FromTraction(force), "Force"); // Dumping the concrete model.setBaseName("concrete"); model.addDumpFieldVector("displacement"); model.addDumpFieldVector("external_force"); model.addDumpFieldVector("internal_force"); model.addDumpFieldTensor("stress"); // Dumping the reinforcement model.setBaseNameToDumper("reinforcement", "reinforcement"); model.addDumpFieldTensorToDumper( "reinforcement", "stress_embedded"); // dumping stress in reinforcement auto & solver = model.getNonLinearSolver(); solver.set("max_iterations", 1); solver.set("threshold", 1e-6); solver.set("convergence_type", SolveConvergenceCriteria::_residual); model.solveStep(); // Dumping model model.dump(); model.dump("reinforcement"); finalize(); return EXIT_SUCCESS; } diff --git a/examples/explicit/explicit_dynamic.cc b/examples/explicit/explicit_dynamic.cc index 96f0d7a40..cbc98f7df 100644 --- a/examples/explicit/explicit_dynamic.cc +++ b/examples/explicit/explicit_dynamic.cc @@ -1,98 +1,98 @@ /** * Copyright (©) 2014-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char * argv[]) { initialize("material.dat", argc, argv); const Int spatial_dimension = 3; const Real pulse_width = 2.; const Real A = 0.01; Real time_step; Real time_factor = 0.8; Int max_steps = 1000; Mesh mesh(spatial_dimension); if (Communicator::getStaticCommunicator().whoAmI() == 0) mesh.read("bar.msh"); SolidMechanicsModel model(mesh); /// model initialization model.initFull(_analysis_method = _explicit_lumped_mass); time_step = model.getStableTimeStep(); std::cout << "Time Step = " << time_step * time_factor << "s (" << time_step << "s)" << std::endl; time_step *= time_factor; model.setTimeStep(time_step); /// boundary and initial conditions Array & displacement = model.getDisplacement(); const Array & nodes = mesh.getNodes(); for (Int n = 0; n < mesh.getNbNodes(); ++n) { Real x = nodes(n) - 2; // Sinus * Gaussian Real L = pulse_width; Real k = 0.1 * 2 * M_PI * 3 / L; displacement(n) = A * sin(k * x) * exp(-(k * x) * (k * x) / (L * L)); } std::ofstream energy; energy.open("energy.csv"); energy << "id,rtime,epot,ekin,tot" << std::endl; model.setBaseName("explicit_dynamic"); model.addDumpField("displacement"); model.addDumpField("velocity"); model.addDumpField("acceleration"); model.addDumpField("stress"); model.dump(); for (Int s = 1; s <= max_steps; ++s) { model.solveStep(); Real epot = model.getEnergy("potential"); Real ekin = model.getEnergy("kinetic"); energy << s << "," << s * time_step << "," << epot << "," << ekin << "," << epot + ekin << "," << std::endl; if (s % 10 == 0) std::cout << "passing step " << s << "/" << max_steps << std::endl; model.dump(); } energy.close(); finalize(); return EXIT_SUCCESS; } diff --git a/examples/heat_transfer/heat_transfer_dynamics_2d.cc b/examples/heat_transfer/heat_transfer_dynamics_2d.cc index 03fff9563..3f6cd9ad4 100644 --- a/examples/heat_transfer/heat_transfer_dynamics_2d.cc +++ b/examples/heat_transfer/heat_transfer_dynamics_2d.cc @@ -1,92 +1,92 @@ /** * Copyright (©) 2011-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "heat_transfer_model.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ using namespace akantu; const Int spatial_dimension = 2; /* -------------------------------------------------------------------------- */ int main(int argc, char * argv[]) { initialize("material.dat", argc, argv); // create mesh Mesh mesh(spatial_dimension); mesh.read("square.msh"); HeatTransferModel model(mesh); // initialize everything model.initFull(); // get stable time step Real time_step = model.getStableTimeStep() * 0.8; std::cout << "time step is:" << time_step << std::endl; model.setTimeStep(time_step); // boundary conditions const Array & nodes = model.getFEEngine().getMesh().getNodes(); Array & boundary = model.getBlockedDOFs(); Array & temperature = model.getTemperature(); double length = 1.; auto nb_nodes = model.getFEEngine().getMesh().getNbNodes(); for (Int i = 0; i < nb_nodes; ++i) { temperature(i) = 100.; Real dx = nodes(i, 0) - length / 4.; Real dy = 0.0; Real dz = 0.0; if (spatial_dimension > 1) dy = nodes(i, 1) - length / 4.; if (spatial_dimension == 3) dz = nodes(i, 2) - length / 4.; Real d = sqrt(dx * dx + dy * dy + dz * dz); if (d < 0.1) { boundary(i) = true; temperature(i) = 300.; } } model.setBaseName("heat_transfer_square2d"); model.addDumpField("temperature"); model.addDumpField("temperature_rate"); model.addDumpField("internal_heat_rate"); // main loop int max_steps = 15000; for (int i = 0; i < max_steps; i++) { model.solveStep(); if (i % 100 == 0) model.dump(); if (i % 10 == 0) std::cout << "Step " << i << "/" << max_steps << std::endl; } std::cout << "\n\n Stable Time Step is : " << time_step << "\n \n" << std::endl; return 0; } diff --git a/examples/heat_transfer/heat_transfer_dynamics_3d.cc b/examples/heat_transfer/heat_transfer_dynamics_3d.cc index 05b9ade59..155eda419 100644 --- a/examples/heat_transfer/heat_transfer_dynamics_3d.cc +++ b/examples/heat_transfer/heat_transfer_dynamics_3d.cc @@ -1,98 +1,98 @@ /** * Copyright (©) 2011-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "heat_transfer_model.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; Int spatial_dimension = 3; ElementType type = _tetrahedron_4; /* -------------------------------------------------------------------------- */ int main(int argc, char * argv[]) { initialize("material.dat", argc, argv); Mesh mesh(spatial_dimension); mesh.read("cube.msh"); HeatTransferModel model(mesh); // initialize everything model.initFull(); // get and set stable time step Real time_step = model.getStableTimeStep() * 0.8; std::cout << "Stable Time Step is : " << time_step / .8 << std::endl; std::cout << "time step is:" << time_step << std::endl; model.setTimeStep(time_step); /// boundary conditions const Array & nodes = mesh.getNodes(); Array & boundary = model.getBlockedDOFs(); Array & temperature = model.getTemperature(); auto nb_nodes = mesh.getNbNodes(); double length; length = 1.; for (Int i = 0; i < nb_nodes; ++i) { temperature(i) = 100.; // to insert a heat source Real dx = nodes(i, 0) - length / 2.; Real dy = nodes(i, 1) - length / 2.; Real dz = nodes(i, 2) - length / 2.; Real d = sqrt(dx * dx + dy * dy + dz * dz); if (d < 0.1) { boundary(i) = true; temperature(i) = 300.; } } model.setBaseName("heat_transfer_cube3d"); model.addDumpField("temperature"); model.addDumpField("temperature_rate"); model.addDumpField("internal_heat_rate"); // //for testing int max_steps = 1000; for (int i = 0; i < max_steps; i++) { model.solveStep(); if (i % 100 == 0) model.dump(); if (i % 10 == 0) { std::cout << "Step " << i << "/" << max_steps << std::endl; } } return 0; } diff --git a/examples/heat_transfer/heat_transfer_static_2d.cc b/examples/heat_transfer/heat_transfer_static_2d.cc index 0c14c6f80..edf161db6 100644 --- a/examples/heat_transfer/heat_transfer_static_2d.cc +++ b/examples/heat_transfer/heat_transfer_static_2d.cc @@ -1,84 +1,84 @@ /** * Copyright (©) 2011-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "heat_transfer_model.hh" /* -------------------------------------------------------------------------- */ #include #include #include #include /* -------------------------------------------------------------------------- */ using namespace akantu; /* -------------------------------------------------------------------------- */ Int spatial_dimension = 2; std::string base_name; int main(int argc, char * argv[]) { initialize("material.dat", argc, argv); // create mesh Mesh mesh(spatial_dimension); mesh.read("square.msh"); HeatTransferModel model(mesh); // initialize everything model.initFull(_analysis_method = _static); // boundary conditions const Array & nodes = mesh.getNodes(); Array & blocked_dofs = model.getBlockedDOFs(); Array & temperature = model.getTemperature(); double length = 1.; Int nb_nodes = nodes.size(); for (Int i = 0; i < nb_nodes; ++i) { temperature(i) = 100.; Real dx = nodes(i, 0); Real dy = nodes(i, 1); Vector dX = {dx, dy}; dX.array() -= length / 4.; Real d = dX.norm(); if (d < 0.1) { blocked_dofs(i) = true; temperature(i) = 300.; } if (std::abs(dx) < 1e-4 || std::abs(dy) < 1e-4) blocked_dofs(i) = true; if (std::abs(dx - length) < 1e-4 || std::abs(dy - length) < 1e-4) blocked_dofs(i) = true; } model.setBaseName("heat_transfer_static_2d"); model.addDumpField("temperature"); model.addDumpField("internal_heat_rate"); model.addDumpField("conductivity"); model.addDumpField("blocked_dofs"); model.dump(); model.solveStep(); model.dump(); return 0; } diff --git a/examples/implicit/implicit_dynamic.cc b/examples/implicit/implicit_dynamic.cc index d15b1dda6..31ea8fbfb 100644 --- a/examples/implicit/implicit_dynamic.cc +++ b/examples/implicit/implicit_dynamic.cc @@ -1,140 +1,140 @@ /** * Copyright (©) 2014-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "communicator.hh" #include "non_linear_solver.hh" #include "solid_mechanics_model.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ using namespace akantu; /* -------------------------------------------------------------------------- */ const Real bar_length = 10.; const Real bar_height = 1.; const Real bar_depth = 1.; const Real F = 5e3; const Real L = bar_length; const Real I = bar_depth * bar_height * bar_height * bar_height / 12.; const Real E = 12e7; const Real rho = 1000; const Real m = rho * bar_height * bar_depth; static Real w(UInt n) { return n * n * M_PI * M_PI / (L * L) * sqrt(E * I / m); } static Real analytical_solution(Real time) { return 2 * F * L * L * L / (pow(M_PI, 4) * E * I) * ((1. - cos(w(1) * time)) + (1. - cos(w(3) * time)) / 81. + (1. - cos(w(5) * time)) / 625.); } const Int spatial_dimension = 2; const Real time_step = 1e-4; const Real max_time = 0.62; /* -------------------------------------------------------------------------- */ int main(int argc, char * argv[]) { initialize("material_dynamic.dat", argc, argv); Mesh mesh(spatial_dimension); const auto & comm = Communicator::getStaticCommunicator(); Int prank = comm.whoAmI(); if (prank == 0) mesh.read("beam.msh"); mesh.distribute(); SolidMechanicsModel model(mesh); /// model initialization model.initFull(_analysis_method = _implicit_dynamic); Material & mat = model.getMaterial(0); mat.setParam("E", E); mat.setParam("rho", rho); Array & force = model.getExternalForce(); Array & displacment = model.getDisplacement(); // boundary conditions model.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "blocked"); model.applyBC(BC::Dirichlet::FixedValue(0.0, _y), "blocked"); model.applyBC(BC::Dirichlet::FixedValue(0.0, _y), "roller"); const Array & trac_nodes = mesh.getElementGroup("traction").getNodeGroup().getNodes(); bool dump_node = false; if (trac_nodes.size() > 0 && mesh.isLocalOrMasterNode(trac_nodes(0))) { force(trac_nodes(0), 1) = F; dump_node = true; } // output setup std::ofstream pos; pos.open("position.csv"); if (!pos.good()) AKANTU_ERROR("Cannot open file \"position.csv\""); pos << "id,time,position,solution" << std::endl; model.setBaseName("dynamic"); model.addDumpFieldVector("displacement"); model.addDumpField("velocity"); model.addDumpField("acceleration"); model.addDumpField("external_force"); model.addDumpField("internal_force"); model.dump(); model.setTimeStep(time_step); auto & solver = model.getNonLinearSolver(); solver.set("max_iterations", 100); solver.set("threshold", 1e-12); solver.set("convergence_type", SolveConvergenceCriteria::_solution); /// time loop Real time = 0.; for (Int s = 1; time < max_time; ++s, time += time_step) { if (prank == 0) std::cout << s << "\r" << std::flush; model.solveStep(); if (dump_node) pos << s << "," << time << "," << displacment(trac_nodes(0), 1) << "," << analytical_solution(s * time_step) << std::endl; if (s % 100 == 0) model.dump(); } std::cout << std::endl; pos.close(); finalize(); return EXIT_SUCCESS; } diff --git a/examples/io/dumper/dumpable_interface.cc b/examples/io/dumper/dumpable_interface.cc index a6df28ef3..c6dc21984 100644 --- a/examples/io/dumper/dumpable_interface.cc +++ b/examples/io/dumper/dumpable_interface.cc @@ -1,180 +1,180 @@ /** * Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "element_group.hh" #include "group_manager_inline_impl.hh" #include "mesh.hh" /* -------------------------------------------------------------------------- */ #include "dumpable_inline_impl.hh" #include "dumper_iohelper_paraview.hh" /* -------------------------------------------------------------------------- */ #include "locomotive_tools.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char * argv[]) { /* In this example, we present dumpers::Dumpable which is an interface for other classes who want to dump themselves. Several classes of Akantu inheritate from Dumpable (Model, Mesh, ...). In this example we reproduce the same tasks as example_dumper_low_level.cc using this time Dumpable interface inherted by Mesh, NodeGroup and ElementGroup. It is then advised to read first example_dumper_low_level.cc. */ initialize(argc, argv); // To start let us load the swiss train mesh and its mesh data information. Int spatial_dimension = 2; Mesh mesh(spatial_dimension); mesh.read("swiss_train.msh"); /* swiss_train.msh has the following physical groups that can be viewed with GMSH: "$MeshFormat 2.2 0 8 $EndMeshFormat $PhysicalNames 6 2 1 "red" 2 2 "white" 2 3 "lwheel_1" 2 4 "lwheel_2" 2 5 "rwheel_2" 2 6 "rwheel_1" $EndPhysicalNames ..." */ // Grouping nodes and elements belonging to train wheels (=four mesh data). ElementGroup & wheels_elements = mesh.createElementGroup("wheels", spatial_dimension); wheels_elements.append(mesh.getElementGroup("lwheel_1")); wheels_elements.append(mesh.getElementGroup("lwheel_2")); wheels_elements.append(mesh.getElementGroup("rwheel_1")); wheels_elements.append(mesh.getElementGroup("rwheel_2")); const Array & lnode_1 = (mesh.getElementGroup("lwheel_1")).getNodeGroup().getNodes(); const Array & lnode_2 = (mesh.getElementGroup("lwheel_2")).getNodeGroup().getNodes(); const Array & rnode_1 = (mesh.getElementGroup("rwheel_1")).getNodeGroup().getNodes(); const Array & rnode_2 = (mesh.getElementGroup("rwheel_2")).getNodeGroup().getNodes(); Array & node = mesh.getNodes(); Int nb_nodes = mesh.getNbNodes(); // This time a 2D Array is created and a padding size of 3 is passed to // NodalField in order to warp train deformation on Paraview. Array displacement(nb_nodes, spatial_dimension); // Create an ElementTypeMapArray for the colour ElementTypeMapArray colour("colour"); colour.initialize(mesh, _with_nb_element = true); /* ------------------------------------------------------------------------ */ /* Creating dumpers */ /* ------------------------------------------------------------------------ */ // Create dumper for the complete mesh and register it as default dumper. auto && dumper = std::make_shared("train", "./paraview/dumpable", false); mesh.registerExternalDumper(dumper, "train", true); mesh.addDumpMesh(mesh); // The dumper for the filtered mesh can be directly taken from the // ElementGroup and then registered as "wheels_elements" dumper. auto && wheels = mesh.getGroupDumper("paraview_wheels", "wheels"); mesh.registerExternalDumper(wheels.shared_from_this(), "wheels"); mesh.setDirectoryToDumper("wheels", "./paraview/dumpable"); // Arrays and ElementTypeMapArrays can be added as external fields directly mesh.addDumpFieldExternal("displacement", displacement); ElementTypeMapArrayFilter filtered_colour(colour, wheels_elements.getElements()); auto colour_field_wheel = std::make_shared, true>>( filtered_colour); mesh.addDumpFieldExternal("color", colour_field_wheel); mesh.addDumpFieldExternalToDumper("wheels", "displacement", displacement); mesh.addDumpFieldExternalToDumper("wheels", "colour", colour); // For some specific cases the Fields should be created, as when you want to // pad an array auto displacement_vector_field = mesh.createNodalField(&displacement, "all", 3); mesh.addDumpFieldExternal("displacement_as_paraview_vector", displacement_vector_field); mesh.addDumpFieldExternalToDumper("wheels", "displacement_as_paraview_vector", displacement_vector_field); /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ // Fill the ElementTypeMapArray colour. fillColour(mesh, colour); /// Apply displacement and wheels rotation. Real tot_displacement = 50.; Real radius = 1.; auto nb_steps = 100; Real theta = tot_displacement / radius; Vector l_center(spatial_dimension); Vector r_center(spatial_dimension); for (Int i = 0; i < spatial_dimension; ++i) { l_center(i) = node(14, i); r_center(i) = node(2, i); } for (Int i = 0; i < nb_steps; ++i) { displacement.zero(); Real step_ratio = Real(i) / Real(nb_steps); Real angle = step_ratio * theta; applyRotation(l_center, angle, node, displacement, lnode_1); applyRotation(l_center, angle, node, displacement, lnode_2); applyRotation(r_center, angle, node, displacement, rnode_1); applyRotation(r_center, angle, node, displacement, rnode_2); for (Int j = 0; j < nb_nodes; ++j) { displacement(j, _x) += step_ratio * tot_displacement; } /// Dump call is finally made through Dumpable interface. mesh.dump(); mesh.dump("wheels"); } finalize(); return 0; } diff --git a/examples/io/dumper/dumper_low_level.cc b/examples/io/dumper/dumper_low_level.cc index 0ed354efd..44f3f8719 100644 --- a/examples/io/dumper/dumper_low_level.cc +++ b/examples/io/dumper/dumper_low_level.cc @@ -1,188 +1,188 @@ /** * Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "element_group.hh" #include "group_manager.hh" #include "mesh.hh" #include "dumper_elemental_field.hh" #include "dumper_nodal_field.hh" #include "dumper_iohelper_paraview.hh" #include "locomotive_tools.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char * argv[]) { /* This example aims at illustrating how to manipulate low-level methods of DumperIOHelper. The aims is to visualize a colorized moving train with Paraview */ initialize(argc, argv); // To start let us load the swiss train mesh and its mesh data information. // We aknowledge here a weel-known swiss industry for mesh donation. Int spatial_dimension = 2; Mesh mesh(spatial_dimension); mesh.read("swiss_train.msh"); Array & nodes = mesh.getNodes(); Int nb_nodes = mesh.getNbNodes(); /* swiss_train.msh has the following physical groups that can be viewed with GMSH: "$MeshFormat 2.2 0 8 $EndMeshFormat $PhysicalNames 6 2 1 "red" 2 2 "white" 2 3 "lwheel_1" 2 4 "lwheel_2" 2 5 "rwheel_2" 2 6 "rwheel_1" $EndPhysicalNames ..." */ // Grouping nodes and elements belonging to train wheels (=four mesh data) ElementGroup & wheels_elements = mesh.createElementGroup("wheels", spatial_dimension); wheels_elements.append(mesh.getElementGroup("lwheel_1")); wheels_elements.append(mesh.getElementGroup("lwheel_2")); wheels_elements.append(mesh.getElementGroup("rwheel_1")); wheels_elements.append(mesh.getElementGroup("rwheel_2")); const Array & lnode_1 = (mesh.getElementGroup("lwheel_1")).getNodeGroup().getNodes(); const Array & lnode_2 = (mesh.getElementGroup("lwheel_2")).getNodeGroup().getNodes(); const Array & rnode_1 = (mesh.getElementGroup("rwheel_1")).getNodeGroup().getNodes(); const Array & rnode_2 = (mesh.getElementGroup("rwheel_2")).getNodeGroup().getNodes(); /* Note this Array is constructed with three components in order to warp train deformation on Paraview. A more appropriate way to do this is to set a padding in the NodalField (See example_dumpable_interface.cc.) */ Array displacement(nb_nodes, 3); // ElementalField are constructed with an ElementTypeMapArray. ElementTypeMapArray colour; colour.initialize(mesh, _with_nb_element = true); /* ------------------------------------------------------------------------ */ /* Dumper creation */ /* ------------------------------------------------------------------------ */ // Creation of two DumperParaview. One for full mesh, one for a filtered // mesh. DumperParaview dumper("train", "./paraview/dumper", false); DumperParaview wheels("wheels", "./paraview/dumper", false); // Register the full mesh dumper.registerMesh(mesh); // Register a filtered mesh limited to nodes and elements from wheels groups wheels.registerFilteredMesh(mesh, wheels_elements.getElements(), wheels_elements.getNodeGroup().getNodes()); // Generate an output file of the two mesh registered. dumper.dump(); wheels.dump(); /* At this stage no fields are attached to the two dumpers. To do so, a dumpers::Field object has to be created. Several types of dumpers::Field exist. In this example we present two of them. NodalField to describe nodal displacements of our train. ElementalField handling the color of our different part. */ // NodalField are constructed with an Array. auto displ_field = std::make_shared>(displacement); auto colour_field = std::make_shared>(colour); // Register the freshly created fields to our dumper. dumper.registerField("displacement", displ_field); dumper.registerField("colour", colour_field); // For the dumper wheels, fields have to be filtered at registration. // Filtered NodalField can be simply registered by adding an Array // listing the nodes. auto displ_field_wheel = std::make_shared>( displacement, 0, 0, &(wheels_elements.getNodeGroup().getNodes())); wheels.registerField("displacement", displ_field_wheel); // For the ElementalField, an ElementTypeMapArrayFilter has to be created. ElementTypeMapArrayFilter filtered_colour(colour, wheels_elements.getElements()); auto colour_field_wheel = std::make_shared, true>>( filtered_colour); wheels.registerField("colour", colour_field_wheel); /* ------------------------------------------------------------------------ */ // Now that the dumpers are created and the fields are associated, let's // paint and move the train! // Fill the ElementTypeMapArray colour according to mesh data information. fillColour(mesh, colour); // Apply displacement and wheels rotation. Real tot_displacement = 50.; Real radius = 1.; Int nb_steps = 100; Real theta = tot_displacement / radius; Vector l_center(3); Vector r_center(3); for (Int i = 0; i < spatial_dimension; ++i) { l_center(i) = nodes(14, i); r_center(i) = nodes(2, i); } for (Int i = 0; i < nb_steps; ++i) { displacement.zero(); Real angle = (Real)i / (Real)nb_steps * theta; applyRotation(l_center, angle, nodes, displacement, lnode_1); applyRotation(l_center, angle, nodes, displacement, lnode_2); applyRotation(r_center, angle, nodes, displacement, rnode_1); applyRotation(r_center, angle, nodes, displacement, rnode_2); for (Int j = 0; j < nb_nodes; ++j) { displacement(j, 0) += (Real)i / (Real)nb_steps * tot_displacement; } // Output results after each moving steps for main and wheel dumpers. dumper.dump(); wheels.dump(); } finalize(); return 0; } diff --git a/examples/io/dumper/locomotive_tools.cc b/examples/io/dumper/locomotive_tools.cc index 556a0b3d0..986e83153 100644 --- a/examples/io/dumper/locomotive_tools.cc +++ b/examples/io/dumper/locomotive_tools.cc @@ -1,81 +1,81 @@ /** * Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "aka_array.hh" #include "mesh.hh" /* -------------------------------------------------------------------------- */ #include "locomotive_tools.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; /* -------------------------------------------------------------------------- */ void applyRotation(const Vector & center, Real angle, const Array & nodes, Array & displacement, const Array & node_group) { auto nodes_it = nodes.begin(nodes.getNbComponent()); auto disp_it = displacement.begin(center.size()); auto node_num_it = node_group.begin(); auto node_num_end = node_group.end(); Vector pos_rel(center.size()); for (; node_num_it != node_num_end; ++node_num_it) { const Vector pos = nodes_it[*node_num_it]; for (Int i = 0; i < pos.size(); ++i) pos_rel(i) = pos(i); Vector dis = disp_it[*node_num_it]; pos_rel -= center; Real radius = pos_rel.norm(); if (std::abs(radius) < Math::getTolerance()) continue; Real phi_i = std::acos(pos_rel(_x) / radius); if (pos_rel(_y) < 0) phi_i *= -1; dis(_x) = std::cos(phi_i - angle) * radius - pos_rel(_x); dis(_y) = std::sin(phi_i - angle) * radius - pos_rel(_y); } } /* -------------------------------------------------------------------------- */ void fillColour(const Mesh & mesh, ElementTypeMapArray & colour) { const ElementTypeMapArray & phys_data = mesh.getData("physical_names"); const Array & txt_colour = phys_data(_triangle_3); auto & id_colour = colour(_triangle_3); for (Int i = 0; i < txt_colour.size(); ++i) { std::string phy_name = txt_colour(i); if (phy_name == "red") id_colour(i) = 3; else if (phy_name == "white" || phy_name == "lwheel_1" || phy_name == "rwheel_1") id_colour(i) = 2; else id_colour(i) = 1; } } diff --git a/examples/io/dumper/locomotive_tools.hh b/examples/io/dumper/locomotive_tools.hh index 336635670..0ed5f84f1 100644 --- a/examples/io/dumper/locomotive_tools.hh +++ b/examples/io/dumper/locomotive_tools.hh @@ -1,29 +1,29 @@ /** * Copyright (©) 2012-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ void applyRotation(const ::akantu::Vector<::akantu::Real> ¢er, ::akantu::Real angle, const ::akantu::Array<::akantu::Real> &nodes, ::akantu::Array<::akantu::Real> &displacement, const ::akantu::Array<::akantu::Idx> &node_group); void fillColour(const ::akantu::Mesh &mesh, ::akantu::ElementTypeMapArray<::akantu::Int> &colour); diff --git a/examples/io/parser/example_parser.cc b/examples/io/parser/example_parser.cc index fbcff4ae6..5c81c6402 100644 --- a/examples/io/parser/example_parser.cc +++ b/examples/io/parser/example_parser.cc @@ -1,77 +1,77 @@ /** * Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "non_linear_solver.hh" #include "solid_mechanics_model.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char * argv[]) { // Precise in initialize the name of the text input file to parse. initialize("input_file.dat", argc, argv); // Get the user ParserSection. const ParserSection & usersect = getUserParser(); // getParameterValue() allows to extract data associated to a given parameter // name // and cast it in the desired type set as template paramter. Mesh mesh(usersect.getParameterValue("spatial_dimension")); mesh.read(usersect.getParameterValue("mesh_file")); // getParameter() can be used with variable declaration (destination type is // explicitly known). Int max_iter = usersect.getParameter("max_nb_iterations"); Real precision = usersect.getParameter("precision"); // Following NumPy convention, data can be interpreted as Vector or Matrix // structures. Matrix eigen_stress = usersect.getParameter("stress"); SolidMechanicsModel model(mesh); model.initFull(SolidMechanicsModelOptions(_static)); model.applyBC(BC::Dirichlet::FixedValue(0.0, _x), usersect.getParameterValue("outter_crust")); model.applyBC(BC::Dirichlet::FixedValue(0.0, _y), usersect.getParameterValue("outter_crust")); model.applyBC(BC::Neumann::FromStress(eigen_stress), usersect.getParameterValue("inner_holes")); model.setDirectory("./paraview"); model.setBaseName("swiss_cheese"); model.addDumpFieldVector("displacement"); auto & solver = model.getNonLinearSolver(); solver.set("max_iterations", max_iter); solver.set("threshold", precision); model.solveStep(); model.dump(); finalize(); return EXIT_SUCCESS; } diff --git a/examples/new_material/local_material_damage.cc b/examples/new_material/local_material_damage.cc index 59ad26b41..4b133faa2 100644 --- a/examples/new_material/local_material_damage.cc +++ b/examples/new_material/local_material_damage.cc @@ -1,98 +1,98 @@ /** * Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "local_material_damage.hh" #include "solid_mechanics_model.hh" namespace akantu { /* -------------------------------------------------------------------------- */ LocalMaterialDamage::LocalMaterialDamage(SolidMechanicsModel & model, const ID & id) : Material(model, id), damage("damage", *this) { AKANTU_DEBUG_IN(); this->registerParam("E", E, 0., _pat_parsable, "Young's modulus"); this->registerParam("nu", nu, 0.5, _pat_parsable, "Poisson's ratio"); this->registerParam("lambda", lambda, _pat_readable, "First Lamé coefficient"); this->registerParam("mu", mu, _pat_readable, "Second Lamé coefficient"); this->registerParam("kapa", kpa, _pat_readable, "Bulk coefficient"); this->registerParam("Yd", Yd, 50., _pat_parsmod); this->registerParam("Sd", Sd, 5000., _pat_parsmod); damage.initialize(1); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void LocalMaterialDamage::initMaterial() { AKANTU_DEBUG_IN(); Material::initMaterial(); lambda = nu * E / ((1 + nu) * (1 - 2 * nu)); mu = E / (2 * (1 + nu)); kpa = lambda + 2. / 3. * mu; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void LocalMaterialDamage::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Real * dam = damage(el_type, ghost_type).data(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); computeStressOnQuad(grad_u, sigma, *dam); ++dam; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void LocalMaterialDamage::computePotentialEnergy(ElementType el_type) { AKANTU_DEBUG_IN(); Real * epot = potential_energy(el_type).data(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, _not_ghost); computePotentialEnergyOnQuad(grad_u, sigma, *epot); epot++; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } static bool material_is_alocated_local_damage [[gnu::unused]] = MaterialFactory::getInstance().registerAllocator( "local_damage", [](UInt, const ID &, SolidMechanicsModel & model, const ID & id) -> std::unique_ptr { return std::make_unique(model, id); }); } // namespace akantu diff --git a/examples/new_material/local_material_damage.hh b/examples/new_material/local_material_damage.hh index ab3df80cf..a7943f1ff 100644 --- a/examples/new_material/local_material_damage.hh +++ b/examples/new_material/local_material_damage.hh @@ -1,109 +1,109 @@ /** * Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material.hh" /* -------------------------------------------------------------------------- */ #ifndef AKANTU_LOCAL_MATERIAL_DAMAGE_HH_ #define AKANTU_LOCAL_MATERIAL_DAMAGE_HH_ namespace akantu { class LocalMaterialDamage : public Material { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: LocalMaterialDamage(SolidMechanicsModel &model, const ID &id = ""); virtual ~LocalMaterialDamage(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void initMaterial() override; /// constitutive law for all element of a type void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost) override; /// compute the potential energy for all elements void computePotentialEnergy(ElementType el_type) override; protected: /// constitutive law for a given quadrature point template inline void computeStressOnQuad(Eigen::MatrixBase &grad_u, Eigen::MatrixBase &sigma, Real &damage); /// compute the potential energy for on element template inline void computePotentialEnergyOnQuad(Eigen::MatrixBase &grad_u, Eigen::MatrixBase &sigma, Real &epot); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// compute the celerity of the fastest wave in the material inline Real getCelerity(const Element &element) const override; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Damage, damage, Real); private: /// the young modulus Real E; /// Poisson coefficient Real nu; /// First Lamé coefficient Real lambda; /// Second Lamé coefficient (shear modulus) Real mu; /// resistance to damage Real Yd; /// damage threshold Real Sd; /// Bulk modulus Real kpa; /// damage internal variable InternalField damage; }; } // namespace akantu /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "local_material_damage_inline_impl.hh" #endif /* AKANTU_LOCAL_MATERIAL_DAMAGE_HH_ */ diff --git a/examples/new_material/local_material_damage_inline_impl.hh b/examples/new_material/local_material_damage_inline_impl.hh index ddda748cb..251295014 100644 --- a/examples/new_material/local_material_damage_inline_impl.hh +++ b/examples/new_material/local_material_damage_inline_impl.hh @@ -1,80 +1,80 @@ /** * Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #ifndef AKANTU_LOCAL_MATERIAL_DAMAGE_INLINE_IMPL_HH_ #define AKANTU_LOCAL_MATERIAL_DAMAGE_INLINE_IMPL_HH_ namespace akantu { /* -------------------------------------------------------------------------- */ template inline void LocalMaterialDamage::computeStressOnQuad( Eigen::MatrixBase &grad_u, Eigen::MatrixBase &sigma, Real &dam) { Real trace = grad_u.trace(); /// \sigma_{ij} = \lambda * (\nabla u)_{kk} * \delta_{ij} + \mu * (\nabla /// u_{ij} + \nabla u_{ji}) for (Int i = 0; i < spatial_dimension; ++i) { for (Int j = 0; j < spatial_dimension; ++j) { sigma(i, j) = (i == j) * lambda * trace + mu * (grad_u(i, j) + grad_u(j, i)); } } Real Y = 0; for (Int i = 0; i < spatial_dimension; ++i) { for (Int j = 0; j < spatial_dimension; ++j) { Y += sigma(i, j) * grad_u(i, j); } } Y *= 0.5; Real Fd = Y - Yd - Sd * dam; if (Fd > 0) dam = (Y - Yd) / Sd; dam = std::min(dam, 1.); sigma *= 1 - dam; } /* -------------------------------------------------------------------------- */ template inline void LocalMaterialDamage::computePotentialEnergyOnQuad( Eigen::MatrixBase &grad_u, Eigen::MatrixBase &sigma, Real &epot) { epot = 0.; for (Int i = 0, t = 0; i < spatial_dimension; ++i) for (Int j = 0; j < spatial_dimension; ++j, ++t) epot += sigma(i, j) * (grad_u(i, j) - (i == j)); epot *= .5; } /* -------------------------------------------------------------------------- */ inline Real LocalMaterialDamage::getCelerity(__attribute__((unused)) const Element &element) const { // Here the fastest celerity is the push wave speed return (std::sqrt((2 * mu + lambda) / rho)); } } // namespace akantu #endif /* AKANTU_LOCAL_MATERIAL_DAMAGE_INLINE_IMPL_HH_ */ diff --git a/examples/new_material/new_local_material.cc b/examples/new_material/new_local_material.cc index 4fb84d413..a10970ccf 100644 --- a/examples/new_material/new_local_material.cc +++ b/examples/new_material/new_local_material.cc @@ -1,91 +1,91 @@ /** * Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "local_material_damage.hh" #include "solid_mechanics_model.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ using namespace akantu; #define bar_length 10. #define bar_height 4. akantu::Real eps = 1e-10; int main(int argc, char * argv[]) { akantu::initialize("material.dat", argc, argv); Int max_steps = 10000; Real epot, ekin; const Int spatial_dimension = 2; Mesh mesh(spatial_dimension); mesh.read("barre_trou.msh"); /// model creation SolidMechanicsModel model(mesh); /// model initialization model.initFull(_analysis_method = _explicit_lumped_mass); std::cout << model.getMaterial(0) << std::endl; Real time_step = model.getStableTimeStep(); model.setTimeStep(time_step / 10.); /// Dirichlet boundary conditions model.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "Fixed_x"); model.applyBC(BC::Dirichlet::FixedValue(0.0, _y), "Fixed_y"); // Neumann boundary condition Matrix stress(2, 2); stress.eye(3e2); model.applyBC(BC::Neumann::FromStress(stress), "Traction"); model.setBaseName("local_material"); model.addDumpField("displacement"); model.addDumpField("velocity"); model.addDumpField("acceleration"); model.addDumpField("external_force"); model.addDumpField("internal_force"); model.addDumpField("grad_u"); model.addDumpField("stress"); model.addDumpField("damage"); model.dump(); for (Int s = 0; s < max_steps; ++s) { model.solveStep(); epot = model.getEnergy("potential"); ekin = model.getEnergy("kinetic"); if (s % 100 == 0) std::cout << s << " " << epot << " " << ekin << " " << epot + ekin << std::endl; if (s % 1000 == 0) model.dump(); } akantu::finalize(); return EXIT_SUCCESS; } diff --git a/examples/new_material/viscoelastic_maxwell/material_viscoelastic_maxwell_energies.cc b/examples/new_material/viscoelastic_maxwell/material_viscoelastic_maxwell_energies.cc index a8e4607e8..1873a7631 100644 --- a/examples/new_material/viscoelastic_maxwell/material_viscoelastic_maxwell_energies.cc +++ b/examples/new_material/viscoelastic_maxwell/material_viscoelastic_maxwell_energies.cc @@ -1,157 +1,157 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include #include #include #include /* -------------------------------------------------------------------------- */ #include "material_viscoelastic_maxwell.hh" #include "non_linear_solver.hh" #include "solid_mechanics_model.hh" #include "sparse_matrix.hh" using namespace akantu; /* -------------------------------------------------------------------------- */ /* Main */ /* -------------------------------------------------------------------------- */ int main(int argc, char * argv[]) { akantu::initialize("material_viscoelastic_maxwell.dat", argc, argv); // sim data Real eps = 0.1; const Int dim = 2; Real sim_time = 100.; Real T = 10.; Mesh mesh(dim); mesh.read("material_viscoelastic_maxwell_mesh.msh"); SolidMechanicsModel model(mesh); /* ------------------------------------------------------------------------ */ /* Initialization */ /* ------------------------------------------------------------------------ */ model.initFull(_analysis_method = _static); std::cout << model.getMaterial(0) << std::endl; std::stringstream filename_sstr; filename_sstr << "material_viscoelastic_maxwell_output.out"; std::ofstream output_data; output_data.open(filename_sstr.str().c_str()); Material & mat = model.getMaterial(0); Real time_step = 0.1; const Array & coordinate = mesh.getNodes(); Array & displacement = model.getDisplacement(); Array & blocked = model.getBlockedDOFs(); /// Setting time step model.setTimeStep(time_step); model.setBaseName("dynamic"); model.addDumpFieldVector("displacement"); model.addDumpField("blocked_dofs"); model.addDumpField("external_force"); model.addDumpField("internal_force"); model.addDumpField("grad_u"); model.addDumpField("stress"); model.addDumpField("strain"); Int max_steps = sim_time / time_step + 1; Real time = 0.; auto & solver = model.getNonLinearSolver(); solver.set("max_iterations", 10); solver.set("threshold", 1e-7); solver.set("convergence_type", SolveConvergenceCriteria::_residual); /* ------------------------------------------------------------------------ */ /* Main loop */ /* ------------------------------------------------------------------------ */ for (Int s = 0; s <= max_steps; ++s) { std::cout << "Time Step = " << time_step << "s" << std::endl; std::cout << "Time = " << time << std::endl; // impose displacement Real epsilon = 0; if (time < T) { epsilon = eps * time / T; } else { epsilon = eps; } for (auto && [coord, disp, block] : zip(make_view(coordinate, dim), make_view(displacement, dim), make_view(blocked, dim))) { if (Math::are_float_equal(coord(_x), 0.0)) { disp(_x) = 0; disp(_y) = epsilon * coord(_y); block.set(true); } else if (Math::are_float_equal(coord(_y), 0.0)) { disp(_x) = epsilon * coord(_x); disp(_y) = 0; block.set(true); } else if (Math::are_float_equal(coord(_x), 0.001)) { disp = epsilon * coord; block.set(true); } else if (Math::are_float_equal(coord(_y), 0.001)) { disp = epsilon * coord; block.set(true); } } try { model.solveStep(); } catch (debug::NLSNotConvergedException & e) { std::cout << "Didn't converge after " << e.niter << " iterations. Error is " << e.error << std::endl; return EXIT_FAILURE; } // for debugging // auto int_force = model.getInternalForce(); // auto &K = model.getDOFManager().getMatrix("K"); // K.saveMatrix("K.mtx"); Int nb_iter = solver.get("nb_iterations"); std::cout << "Converged in " << nb_iter << " iterations" << std::endl; model.dump(); Real epot = mat.getEnergy("potential"); Real edis = mat.getEnergy("dissipated"); Real work = mat.getEnergy("work"); // data output output_data << s * time_step << " " << epsilon << " " << epot << " " << edis << " " << work << std::endl; time += time_step; } output_data.close(); finalize(); } diff --git a/examples/parallel/parallel_2d.cc b/examples/parallel/parallel_2d.cc index c8e77f0b5..288abdb98 100644 --- a/examples/parallel/parallel_2d.cc +++ b/examples/parallel/parallel_2d.cc @@ -1,97 +1,97 @@ /** * Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "communicator.hh" #include "solid_mechanics_model.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char * argv[]) { initialize("material.dat", argc, argv); Int spatial_dimension = 2; Int max_steps = 10000; Real time_factor = 0.8; Real max_disp = 1e-6; Mesh mesh(spatial_dimension); const auto & comm = Communicator::getStaticCommunicator(); Int prank = comm.whoAmI(); if (prank == 0) { // Read the mesh mesh.read("square_2d.msh"); } mesh.distribute(); SolidMechanicsModel model(mesh); model.initFull(); if (prank == 0) std::cout << model.getMaterial(0) << std::endl; model.setBaseName("multi"); model.addDumpFieldVector("displacement"); model.addDumpFieldVector("velocity"); model.addDumpFieldVector("acceleration"); model.addDumpFieldTensor("stress"); model.addDumpFieldTensor("grad_u"); /// boundary conditions Real eps = 1e-16; const Array & pos = mesh.getNodes(); Array & disp = model.getDisplacement(); Array & boun = model.getBlockedDOFs(); Real left_side = mesh.getLowerBounds()(0); Real right_side = mesh.getUpperBounds()(0); for (Int i = 0; i < mesh.getNbNodes(); ++i) { if (std::abs(pos(i, 0) - left_side) < eps) { disp(i, 0) = max_disp; boun(i, 0) = true; } if (std::abs(pos(i, 0) - right_side) < eps) { disp(i, 0) = -max_disp; boun(i, 0) = true; } } Real time_step = model.getStableTimeStep() * time_factor; std::cout << "Time Step = " << time_step << "s" << std::endl; model.setTimeStep(time_step); model.dump(); for (Int s = 1; s <= max_steps; ++s) { model.solveStep(); if (s % 200 == 0) model.dump(); if (prank == 0 && s % 100 == 0) std::cout << "passing step " << s << "/" << max_steps << std::endl; } finalize(); return EXIT_SUCCESS; } diff --git a/examples/phase_field/phase_field_notch.cc b/examples/phase_field/phase_field_notch.cc index 73d07c836..de2019ab3 100644 --- a/examples/phase_field/phase_field_notch.cc +++ b/examples/phase_field/phase_field_notch.cc @@ -1,109 +1,109 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "coupler_solid_phasefield.hh" #include "non_linear_solver.hh" #include "phase_field_model.hh" #include "solid_mechanics_model.hh" /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ using namespace akantu; using clk = std::chrono::high_resolution_clock; using second = std::chrono::duration; using millisecond = std::chrono::duration; const Int spatial_dimension = 2; /* -------------------------------------------------------------------------- */ int main(int argc, char * argv[]) { initialize("material_notch.dat", argc, argv); // create mesh Mesh mesh(spatial_dimension); mesh.read("square_notch.msh"); CouplerSolidPhaseField coupler(mesh); auto & model = coupler.getSolidMechanicsModel(); auto & phase = coupler.getPhaseFieldModel(); model.initFull(_analysis_method = _static); auto && mat_selector = std::make_shared>("physical_names", model); model.setMaterialSelector(mat_selector); auto && selector = std::make_shared>( "physical_names", phase); phase.setPhaseFieldSelector(selector); phase.initFull(_analysis_method = _static); model.applyBC(BC::Dirichlet::FixedValue(0., _y), "bottom"); model.applyBC(BC::Dirichlet::FixedValue(0., _x), "left"); model.setBaseName("phase_notch"); model.addDumpField("stress"); model.addDumpField("grad_u"); model.addDumpFieldVector("displacement"); model.addDumpField("damage"); model.dump(); auto nbSteps = 1500; Real increment = 1e-5; auto start_time = clk::now(); for (Int s = 1; s < nbSteps; ++s) { if (s >= 500) { increment = 1.e-6; } if (s % 10 == 0) { constexpr char wheel[] = "/-\\|"; auto elapsed = clk::now() - start_time; auto time_per_step = elapsed / s; std::cout << "\r[" << wheel[(s / 10) % 4] << "] " << std::setw(5) << s << "/" << nbSteps << " (" << std::setprecision(2) << std::fixed << std::setw(8) << millisecond(time_per_step).count() << "ms/step - elapsed: " << std::setw(8) << second(elapsed).count() << "s - ETA: " << std::setw(8) << second((nbSteps - s) * time_per_step).count() << "s)" << std::string(' ', 20) << std::flush; } model.applyBC(BC::Dirichlet::IncrementValue(increment, _y), "top"); coupler.solve(); if (s % 100 == 0) { model.dump(); } } finalize(); return EXIT_SUCCESS; } diff --git a/examples/python/cohesive/custom_material.py b/examples/python/cohesive/custom_material.py index 25c8ad4ae..92677463d 100755 --- a/examples/python/cohesive/custom_material.py +++ b/examples/python/cohesive/custom_material.py @@ -1,196 +1,194 @@ -__copyright__ = "Copyright (©) 2022-2023 EPFL (Ecole Polytechnique Fédérale" \ - " de Lausanne) Laboratory (LSMS - Laboratoire de Simulation" \ - " en Mécanique des Solides)" -__license__ = "LGPLv3" - - #!/usr/bin/env python3 # pylint: disable=missing-module-docstring # pylint: disable=missing-function-docstring """Example of custom cohesive material written in python.""" +__copyright__ = "Copyright (©) 2022-2023 EPFL (Ecole Polytechnique Fédérale" \ + " de Lausanne) Laboratory (LSMS - Laboratoire de Simulation" \ + " en Mécanique des Solides)" +__license__ = "LGPLv3" + import numpy as np import akantu as aka spatial_dimension = 2 class LinearCohesive(aka.MaterialCohesive): """Material Cohesive Linear.""" def __init__(self, model, _id): """Construct the material and register the parameters to the parser.""" super().__init__(model, _id) super().registerParamReal( "G_c", aka._pat_readable | aka._pat_parsable, "Fracture energy" ) super().registerParamReal("beta", aka._pat_readable | aka._pat_parsable) self.registerInternalReal("delta_max", 1) self.beta = 0. self.sigma_c = 0. self.delta_c = 0. self.G_c = 0. def initMaterial(self): """Initialize the parameters for the material.""" super().initMaterial() self.sigma_c = self.getReal("sigma_c") self.G_c = self.getReal("G_c") self.beta = self.getReal("beta") self.delta_c = 2 * self.G_c / self.sigma_c def checkInsertion(self, check_only): """Check if need to insert a cohesive element.""" model = self.getModel() facets = self.getFacetFilter() inserter = model.getElementInserter() for type_facet in facets.elementTypes(dim=(spatial_dimension - 1)): facet_filter = facets(type_facet) nb_facet = facet_filter.shape[0] if nb_facet == 0: continue fe_engine = model.getFEEngine("FacetsFEEngine") facets_check = inserter.getCheckFacets(type_facet) insertion = inserter.getInsertionFacets(type_facet) nb_quad_facet = fe_engine.getNbIntegrationPoints(type_facet) normals = fe_engine.getNormalsOnIntegrationPoints(type_facet) facets_stresses = model.getStressOnFacets(type_facet).reshape( normals.shape[0] // nb_quad_facet, nb_quad_facet, 2, spatial_dimension, spatial_dimension, ) tangents = model.getTangents(type_facet) for facet, facet_stresses in zip(facet_filter, facets_stresses): if not facets_check[facet]: continue ref_stress = 0 for q, quad_stresses in enumerate(facet_stresses): current_quad = facet * nb_quad_facet + q normal = normals[current_quad, :].ravel() tangent = tangents[current_quad, :].ravel() stress_1 = quad_stresses.T[0] stress_2 = quad_stresses.T[1] avg_stress = stress_1 + stress_2 / 2.0 traction = avg_stress.dot(normal) n = traction.dot(normal) n = max(0, n) t = traction.dot(tangent) ref_stress = max( ref_stress, np.sqrt(n * n + t * t / (self.beta**2)) ) if ref_stress > self.sigma_c: insertion[facet] = True # constitutive law def computeTraction(self, normals, el_type, ghost_type): """Compute the traction for a given opening.""" openings = self.getOpening(el_type, ghost_type) tractions = self.getTraction(el_type, ghost_type) delta_max = self.getInternalReal("delta_max")(el_type) for el in range(normals.shape[0]): normal = normals[el].ravel() opening = openings[el].ravel() delta_n = opening.dot(normal) * normal delta_s = opening - delta_n delta = ( self.beta * np.linalg.norm(delta_s) ** 2 + np.linalg.norm(delta_n) ** 2 ) delta_max[el] = max(delta_max[el], delta) tractions[el, :] = ( (delta * delta_s + delta_n) * self.sigma_c / delta * (1 - delta / self.delta_c) ) def allocator(_dim, unused, model, _id): """Register the material to the material factory.""" return LinearCohesive(model, _id) mat_factory = aka.MaterialFactory.getInstance() mat_factory.registerAllocator("local_cohesive", allocator) # ------------------------------------------------------------------------- # Initialization # ------------------------------------------------------------------------- aka.parseInput("local_material.dat") mesh = aka.Mesh(spatial_dimension) mesh.read("plate.msh") model = aka.SolidMechanicsModelCohesive(mesh) model.initFull(_analysis_method=aka._static, _is_extrinsic=True) model.initNewSolver(aka._explicit_lumped_mass) model.setBaseName("plate") model.addDumpFieldVector("displacement") model.addDumpFieldVector("external_force") model.addDumpField("strain") model.addDumpField("stress") model.addDumpField("blocked_dofs") model.setBaseNameToDumper("cohesive elements", "cohesive") model.addDumpFieldVectorToDumper("cohesive elements", "displacement") model.addDumpFieldToDumper("cohesive elements", "damage") model.addDumpFieldVectorToDumper("cohesive elements", "tractions") model.addDumpFieldVectorToDumper("cohesive elements", "opening") # ------------------------------------------------------------------------- # Boundary conditions # ------------------------------------------------------------------------- model.applyBC(aka.FixedValue(0.0, aka._x), "XBlocked") model.applyBC(aka.FixedValue(0.0, aka._y), "YBlocked") trac = np.zeros(spatial_dimension) traction = 0.095 trac[int(aka._y)] = traction model.getExternalForce()[:] = 0 model.applyBC(aka.FromTraction(trac), "Traction") print("Solve for traction ", traction) solver = model.getNonLinearSolver("static") solver.set("max_iterations", 100) solver.set("threshold", 1e-10) solver.set("convergence_type", aka.SolveConvergenceCriteria.residual) model.solveStep("static") model.dump() model.dump("cohesive elements") model.setTimeStep(model.getStableTimeStep() * 0.1) maxsteps = 100 for i in range(0, maxsteps): print("{0}/{1}".format(i, maxsteps)) model.checkCohesiveStress() model.solveStep("explicit_lumped") if i % 10 == 0: model.dump() model.dump("cohesive elements") - diff --git a/examples/python/cohesive/plate.py b/examples/python/cohesive/plate.py index a0cba5249..aa86acb45 100644 --- a/examples/python/cohesive/plate.py +++ b/examples/python/cohesive/plate.py @@ -1,106 +1,92 @@ #!/usr/bin/env python3 __copyright__ = "Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale" \ " de Lausanne) Laboratory (LSMS - Laboratoire de Simulation" \ " en Mécanique des Solides)" __license__ = "LGPLv3" - -"""plate.py: Python example: plate with a hole breaking with cohesive -elements""" - -__author__ = "Guillaume Anciaux" -__credits__ = [ - "Guillaume Anciaux ", -] -__copyright__ = ( - "Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale" - " de Lausanne) Laboratory (LSMS - Laboratoire de Simulation" - " en Mécanique des Solides)" -) -__license__ = "LGPLv3" - import akantu as aka import numpy as np + def set_dumpers(model): model.setBaseName("plate") model.addDumpFieldVector("displacement") model.addDumpFieldVector("external_force") model.addDumpField("strain") model.addDumpField("stress") model.addDumpField("blocked_dofs") model.setBaseNameToDumper("cohesive elements", "cohesive") model.addDumpFieldVectorToDumper("cohesive elements", "displacement") model.addDumpFieldToDumper("cohesive elements", "damage") model.addDumpFieldVectorToDumper("cohesive elements", "tractions") model.addDumpFieldVectorToDumper("cohesive elements", "opening") def solve(material_file, mesh_file, traction): aka.parseInput(material_file) spatial_dimension = 2 # ------------------------------------------------------------------------- # Initialization # ------------------------------------------------------------------------- mesh = aka.Mesh(spatial_dimension) mesh.read(mesh_file) model = aka.SolidMechanicsModelCohesive(mesh) model.initFull(_analysis_method=aka._static, _is_extrinsic=True) model.initNewSolver(aka._explicit_lumped_mass) set_dumpers(model) # ------------------------------------------------------------------------- # Boundary conditions # ------------------------------------------------------------------------- model.applyBC(aka.FixedValue(0.0, aka._x), "XBlocked") model.applyBC(aka.FixedValue(0.0, aka._y), "YBlocked") trac = np.zeros(spatial_dimension) trac[int(aka._y)] = traction print("Solve for traction ", traction) model.getExternalForce()[:] = 0 model.applyBC(aka.FromTraction(trac), "Traction") solver = model.getNonLinearSolver("static") solver.set("max_iterations", 100) solver.set("threshold", 1e-10) solver.set("convergence_type", aka.SolveConvergenceCriteria.residual) model.solveStep("static") model.dump() model.dump("cohesive elements") model.setTimeStep(model.getStableTimeStep() * 0.1) maxsteps = 100 for i in range(0, maxsteps): print("{0}/{1}".format(i, maxsteps)) model.checkCohesiveStress() model.solveStep("explicit_lumped") if i % 10 == 0: model.dump() model.dump("cohesive elements") # ----------------------------------------------------------------------------- # main # ----------------------------------------------------------------------------- def main(): mesh_file = "plate.msh" material_file = "material.dat" traction = 0.095 solve(material_file, mesh_file, traction) # ----------------------------------------------------------------------------- if __name__ == "__main__": main() diff --git a/examples/python/custom-material/custom-material.py b/examples/python/custom-material/custom-material.py index 4385443b2..2764f2afb 100644 --- a/examples/python/custom-material/custom-material.py +++ b/examples/python/custom-material/custom-material.py @@ -1,193 +1,180 @@ #!/usr/bin/env python3 __copyright__ = "Copyright (©) 2016-2023 EPFL (Ecole Polytechnique Fédérale" \ " de Lausanne) Laboratory (LSMS - Laboratoire de Simulation" \ " en Mécanique des Solides)" __license__ = "LGPLv3" -""" custom-material.py: Custom material example""" - -__author__ = "Guillaume Anciaux" -__credits__ = [ - "Guillaume Anciaux ", -] -__copyright__ = ( - "Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale" - " de Lausanne) Laboratory (LSMS - Laboratoire de Simulation" - " en Mécanique des Solides)" -) -__license__ = "LGPLv3" - import numpy as np import akantu as aka # ------------------------------------------------------------------------------ class LocalElastic(aka.Material): def __init__(self, model, _id): super().__init__(model, _id) super().registerParamReal( "E", aka._pat_readable | aka._pat_parsable, "Youngs modulus" ) super().registerParamReal( "nu", aka._pat_readable | aka._pat_parsable, "Poisson ratio" ) def initMaterial(self): nu = self.getReal("nu") E = self.getReal("E") self.mu = E / (2 * (1 + nu)) self.lame_lambda = nu * E / ((1.0 + nu) * (1.0 - 2.0 * nu)) # Second Lame coefficient (shear modulus) self.lame_mu = E / (2.0 * (1.0 + nu)) super().initMaterial() # declares all the parameters that are needed def getPushWaveSpeed(self, element): rho = self.getReal("rho") return np.sqrt((self.lame_lambda + 2 * self.lame_mu) / rho) # compute small deformation tensor @staticmethod def computeEpsilon(grad_u): return 0.5 * (grad_u + np.einsum("aij->aji", grad_u)) # constitutive law def computeStress(self, el_type, ghost_type): grad_u = self.getGradU(el_type, ghost_type) sigma = self.getStress(el_type, ghost_type) n_quads = grad_u.shape[0] grad_u = grad_u.reshape((n_quads, 2, 2)) epsilon = self.computeEpsilon(grad_u) sigma = sigma.reshape((n_quads, 2, 2)) trace = np.einsum("aii->a", grad_u) sigma[:, :, :] = ( np.einsum("a,ij->aij", trace, self.lame_lambda * np.eye(2)) + 2.0 * self.lame_mu * epsilon ) # constitutive law tangent modulii def computeTangentModuli(self, el_type, tangent_matrix, ghost_type): n_quads = tangent_matrix.shape[0] tangent = tangent_matrix.reshape(n_quads, 3, 3) Miiii = self.lame_lambda + 2 * self.lame_mu Miijj = self.lame_lambda Mijij = self.lame_mu tangent[:, 0, 0] = Miiii tangent[:, 1, 1] = Miiii tangent[:, 0, 1] = Miijj tangent[:, 1, 0] = Miijj tangent[:, 2, 2] = Mijij # computes the energy density def computePotentialEnergy(self, el_type): sigma = self.getStress(el_type) grad_u = self.getGradU(el_type) nquads = sigma.shape[0] stress = sigma.reshape(nquads, 2, 2) grad_u = grad_u.reshape((nquads, 2, 2)) epsilon = self.computeEpsilon(grad_u) energy_density = self.getPotentialEnergy(el_type) energy_density[:, 0] = 0.5 * np.einsum("aij,aij->a", stress, epsilon) # register material to the MaterialFactory def allocator(_dim, unused, model, _id): return LocalElastic(model, _id) mat_factory = aka.MaterialFactory.getInstance() mat_factory.registerAllocator("local_elastic", allocator) # ------------------------------------------------------------------------------ # main # ------------------------------------------------------------------------------ spatial_dimension = 2 aka.parseInput("material.dat") mesh_file = "bar.msh" max_steps = 250 time_step = 1e-3 # ------------------------------------------------------------------------------ # Initialization # ------------------------------------------------------------------------------ mesh = aka.Mesh(spatial_dimension) mesh.read(mesh_file) # parse input file aka.parseInput("material.dat") model = aka.SolidMechanicsModel(mesh) model.initFull(_analysis_method=aka._explicit_lumped_mass) model.setBaseName("waves") model.addDumpFieldVector("displacement") model.addDumpFieldVector("acceleration") model.addDumpFieldVector("velocity") model.addDumpFieldVector("internal_force") model.addDumpFieldVector("external_force") model.addDumpField("strain") model.addDumpField("stress") model.addDumpField("blocked_dofs") # ------------------------------------------------------------------------------ # boundary conditions # ------------------------------------------------------------------------------ model.applyBC(aka.FixedValue(0, aka._x), "XBlocked") model.applyBC(aka.FixedValue(0, aka._y), "YBlocked") # ------------------------------------------------------------------------------ # initial conditions # ------------------------------------------------------------------------------ displacement = model.getDisplacement() nb_nodes = mesh.getNbNodes() position = mesh.getNodes() pulse_width = 1 A = 0.01 for i in range(0, nb_nodes): # Sinus * Gaussian x = position[i, 0] - 5.0 L = pulse_width k = 0.1 * 2 * np.pi * 3 / L displacement[i, 0] = A * np.sin(k * x) * np.exp(-(k * x) * (k * x) / (L * L)) # ------------------------------------------------------------------------------ # timestep value computation # ------------------------------------------------------------------------------ time_factor = 0.8 stable_time_step = model.getStableTimeStep() * time_factor print("Stable Time Step = {0}".format(stable_time_step)) print("Required Time Step = {0}".format(time_step)) time_step = stable_time_step * time_factor model.setTimeStep(time_step) # ------------------------------------------------------------------------------ # loop for evolution of motion dynamics # ------------------------------------------------------------------------------ print("step,step * time_step,epot,ekin,epot + ekin") for step in range(0, max_steps + 1): model.solveStep() if step % 10 == 0: model.dump() epot = model.getEnergy("potential") ekin = model.getEnergy("kinetic") # output energy calculation to screen print( "{0},{1},{2},{3},{4}".format(step, step * time_step, epot, ekin, (epot + ekin)) ) diff --git a/examples/python/phase-field/phasefield-static.py b/examples/python/phase-field/phasefield-static.py index 5644c1f21..dec93de04 100644 --- a/examples/python/phase-field/phasefield-static.py +++ b/examples/python/phase-field/phasefield-static.py @@ -1,138 +1,124 @@ #!/usr/bin/env python # coding: utf-8 __copyright__ = "Copyright (©) 2021-2023 EPFL (Ecole Polytechnique Fédérale" \ " de Lausanne) Laboratory (LSMS - Laboratoire de Simulation" \ " en Mécanique des Solides)" __license__ = "LGPLv3" -""" phasefield-static.py: Static phase field example""" - -__author__ = "Mohit Pundir" -__credits__ = [ - "Mohit Pundir ", -] -__copyright__ = ( - "Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale" - " de Lausanne) Laboratory (LSMS - Laboratoire de Simulation" - " en Mécanique des Solides)" -) -__license__ = "LGPLv3" - - import numpy as np import akantu as aka aka.parseInput("material_static.dat") dim = 2 mesh = aka.Mesh(dim) mesh.read("plate_static.msh") model = aka.CouplerSolidPhaseField(mesh) solid = model.getSolidMechanicsModel() phase = model.getPhaseFieldModel() solid.initFull(_analysis_method=aka._static) solver = solid.getNonLinearSolver("static") solver.set("max_iterations", 100) solver.set("threshold", 1e-8) solver.set("convergence_type", aka.SolveConvergenceCriteria.solution) solid.getNewSolver( "linear_static", aka.TimeStepSolverType.static, aka.NonLinearSolverType.linear ) solid.setIntegrationScheme( "linear_static", "displacement", aka.IntegrationSchemeType.pseudo_time ) phase.initFull(_analysis_method=aka._static) phase.getNewSolver( "nonlinear_static", aka.TimeStepSolverType.static, aka.NonLinearSolverType.newton_raphson, ) phase.setIntegrationScheme( "nonlinear_static", "damage", aka.IntegrationSchemeType.pseudo_time ) solver = phase.getNonLinearSolver("nonlinear_static") solver.set("max_iterations", 100) solver.set("threshold", 1e-4) solver.set("convergence_type", aka.SolveConvergenceCriteria.solution) solid.applyBC(aka.FixedValue(0, aka._y), "bottom") solid.applyBC(aka.FixedValue(0, aka._x), "left") # Initialization for bulk vizualisation solid.setBaseName("phasefield-static") solid.addDumpFieldVector("displacement") solid.addDumpFieldVector("external_force") solid.addDumpField("strain") solid.addDumpField("stress") solid.addDumpField("damage") solid.addDumpField("blocked_dofs") nb_dofs = solid.getMesh().getNbNodes() * dim increment = solid.getIncrement() displacement = solid.getDisplacement() displacement = displacement.reshape(nb_dofs) blocked_dofs = solid.getBlockedDOFs() blocked_dofs = blocked_dofs.reshape(nb_dofs) damage = phase.getDamage() tolerance = 1e-5 steps = 1000 increment = 5e-6 for n in range(steps): print("Computing iteration " + str(n + 1) + "/" + str(steps)) solid.applyBC(aka.IncrementValue(increment, aka._y), "top") mask = blocked_dofs == False # NOQA: E712 iiter = 0 error_disp = 1 error_dam = 1 displacement_prev = displacement[mask].copy() damage_prev = damage.copy() damage_prev = damage_prev # solve using staggered scheme while error_disp > tolerance or error_dam > tolerance: model.solve("linear_static", "") displacement_new = displacement[mask] damage_new = damage delta_disp = displacement_new - displacement_prev delta_dam = damage_new - damage_prev error_disp = np.linalg.norm(delta_disp) error_dam = np.linalg.norm(delta_dam) iiter += 1 displacement_prev = displacement_new.copy() damage_prev = damage_new.copy() print(error_dam, error_disp) if iiter > 500: raise Exception("Convergence not reached") if n % 50 == 0: solid.dump() solid.dump() diff --git a/examples/static/static.cc b/examples/static/static.cc index df5a193bb..ddc9059a0 100644 --- a/examples/static/static.cc +++ b/examples/static/static.cc @@ -1,69 +1,69 @@ /** * Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "non_linear_solver.hh" #include "solid_mechanics_model.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; #define bar_length 0.01 #define bar_height 0.01 /* -------------------------------------------------------------------------- */ int main(int argc, char * argv[]) { initialize("material.dat", argc, argv); const Int spatial_dimension = 2; Mesh mesh(spatial_dimension); mesh.read("square.msh"); SolidMechanicsModel model(mesh); /// model initialization model.initFull(_analysis_method = _static); model.setBaseName("static"); model.addDumpFieldVector("displacement"); model.addDumpField("external_force"); model.addDumpField("internal_force"); model.addDumpField("grad_u"); model.addDumpField("stress"); /// Dirichlet boundary conditions model.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "Fixed_x"); model.applyBC(BC::Dirichlet::FixedValue(0.0, _y), "Fixed_y"); model.applyBC(BC::Dirichlet::FixedValue(0.0001, _y), "Traction"); model.dump(); auto & solver = model.getNonLinearSolver(); solver.set("max_iterations", 2); solver.set("threshold", 2e-4); solver.set("convergence_type", SolveConvergenceCriteria::_solution); model.solveStep(); model.dump(); finalize(); return EXIT_SUCCESS; } diff --git a/examples/structural_mechanics/bernoulli_beam_2_example.cc b/examples/structural_mechanics/bernoulli_beam_2_example.cc index 27e92545a..0762f4ce7 100644 --- a/examples/structural_mechanics/bernoulli_beam_2_example.cc +++ b/examples/structural_mechanics/bernoulli_beam_2_example.cc @@ -1,131 +1,131 @@ /** * Copyright (©) 2011-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "mesh_accessor.hh" #include "structural_mechanics_model.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #define TYPE _bernoulli_beam_2 using namespace akantu; /* -------------------------------------------------------------------------- */ int main(int argc, char * argv[]) { initialize(argc, argv); // Defining the mesh Mesh beams(2); const auto q = 6000.; const auto L = 10.; const auto M = -3600.; // Momentum at 3 auto nb_nodes = 3; auto nb_element = nb_nodes - 1; MeshAccessor mesh_accessor(beams); Array & nodes = mesh_accessor.getNodes(); nodes.resize(nb_nodes); beams.addConnectivityType(_bernoulli_beam_2); auto & connectivity = mesh_accessor.getConnectivity(_bernoulli_beam_2); connectivity.resize(nb_element); nodes.zero(); nodes(1, 0) = 10; nodes(2, 0) = 18; for (int i = 0; i < nb_element; ++i) { connectivity(i, 0) = i; connectivity(i, 1) = i + 1; } mesh_accessor.makeReady(); // Defining the materials StructuralMechanicsModel model(beams); StructuralMaterial mat1; mat1.E = 3e10; mat1.I = 0.0025; mat1.A = 0.01; model.addMaterial(mat1); StructuralMaterial mat2; mat2.E = 3e10; mat2.I = 0.00128; mat2.A = 0.01; model.addMaterial(mat2); // Defining the forces model.initFull(); auto & forces = model.getExternalForce(); auto & displacement = model.getDisplacement(); auto & boundary = model.getBlockedDOFs(); const auto & N_M = model.getStress(_bernoulli_beam_2); auto & element_material = model.getElementMaterial(_bernoulli_beam_2); boundary.set(false); forces.zero(); displacement.zero(); element_material(1) = 1; forces(0, 1) = -q * L / 2.; forces(0, 2) = -q * L * L / 12.; forces(1, 1) = -q * L / 2.; forces(1, 2) = q * L * L / 12.; forces(2, 2) = M; forces(2, 0) = mat2.E * mat2.A / 18; // Defining the boundary conditions boundary(0, 0) = true; boundary(0, 1) = true; boundary(0, 2) = true; boundary(1, 1) = true; boundary(2, 1) = true; model.addDumpFieldVector("displacement"); model.addDumpField("rotation"); model.addDumpFieldVector("force"); model.addDumpField("momentum"); model.solveStep(); model.assembleResidual(); // Post-Processing std::cout << " d1 = " << displacement(1, 2) << std::endl; std::cout << " d2 = " << displacement(2, 2) << std::endl; std::cout << " d3 = " << displacement(1, 0) << std::endl; std::cout << " M1 = " << N_M(0, 1) << std::endl; std::cout << " M2 = " << N_M(2 * (nb_nodes - 2), 1) << std::endl; model.dump(); finalize(); } diff --git a/extra_packages/extra-materials/src/material_FE2/material_FE2.cc b/extra_packages/extra-materials/src/material_FE2/material_FE2.cc index cf785b64f..caffc1c7b 100644 --- a/extra_packages/extra-materials/src/material_FE2/material_FE2.cc +++ b/extra_packages/extra-materials/src/material_FE2/material_FE2.cc @@ -1,204 +1,204 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "material_FE2.hh" #include "communicator.hh" #include "solid_mechanics_model_RVE.hh" /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ template MaterialFE2::MaterialFE2(SolidMechanicsModel & model, const ID & id) : Parent(model, id), C("material_stiffness", *this) { AKANTU_DEBUG_IN(); this->C.initialize(voigt_h::size * voigt_h::size); this->initialize(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template MaterialFE2::~MaterialFE2() = default; /* -------------------------------------------------------------------------- */ template void MaterialFE2::initialize() { this->registerParam("element_type", el_type, _triangle_3, _pat_parsable | _pat_modifiable, "element type in RVE mesh"); this->registerParam("mesh_file", mesh_file, _pat_parsable | _pat_modifiable, "the mesh file for the RVE"); this->registerParam("nb_gel_pockets", nb_gel_pockets, _pat_parsable | _pat_modifiable, "the number of gel pockets in each RVE"); } /* -------------------------------------------------------------------------- */ template void MaterialFE2::initMaterial() { AKANTU_DEBUG_IN(); Parent::initMaterial(); /// create a Mesh and SolidMechanicsModel on each integration point of the /// material auto C_it = this->C(this->el_type).begin(voigt_h::size, voigt_h::size); for (auto && data : enumerate(make_view(C(this->el_type), voigt_h::size, voigt_h::size))) { auto q = std::get<0>(data); auto & C = std::get<1>(data); meshes.emplace_back(std::make_unique( spatial_dimension, "RVE_mesh_" + std::to_string(q), q + 1)); auto & mesh = *meshes.back(); mesh.read(mesh_file); RVEs.emplace_back(std::make_unique( mesh, true, this->nb_gel_pockets, _all_dimensions, "SMM_RVE_" + std::to_string(q), q + 1)); auto & RVE = *RVEs.back(); RVE.initFull(_analysis_method = _static); /// compute intial stiffness of the RVE RVE.homogenizeStiffness(C); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialFE2::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); // Compute thermal stresses first Parent::computeStress(el_type, ghost_type); Array::const_scalar_iterator sigma_th_it = this->sigma_th(el_type, ghost_type).begin(); // Wikipedia convention: // 2*eps_ij (i!=j) = voigt_eps_I // http://en.wikipedia.org/wiki/Voigt_notation Array::const_matrix_iterator C_it = this->C(el_type, ghost_type).begin(voigt_h::size, voigt_h::size); // create vectors to store stress and strain in Voigt notation // for efficient computation of stress Vector voigt_strain(voigt_h::size); Vector voigt_stress(voigt_h::size); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); const Matrix & C_mat = *C_it; const Real & sigma_th = *sigma_th_it; /// copy strains in Voigt notation for (Int I = 0; I < voigt_h::size; ++I) { /// copy stress in Real voigt_factor = voigt_h::factors[I]; UInt i = voigt_h::vec[I][0]; UInt j = voigt_h::vec[I][1]; voigt_strain(I) = voigt_factor * (grad_u(i, j) + grad_u(j, i)) / 2.; } // compute stresses in Voigt notation voigt_stress.mul(C_mat, voigt_strain); /// copy stresses back in full vectorised notation for (Int I = 0; I < voigt_h::size; ++I) { UInt i = voigt_h::vec[I][0]; UInt j = voigt_h::vec[I][1]; sigma(i, j) = sigma(j, i) = voigt_stress(I) + (i == j) * sigma_th; } ++C_it; ++sigma_th_it; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialFE2::computeTangentModuli( ElementType el_type, Array & tangent_matrix, GhostType ghost_type) { AKANTU_DEBUG_IN(); Array::const_matrix_iterator C_it = this->C(el_type, ghost_type).begin(voigt_h::size, voigt_h::size); MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix); tangent.copy(*C_it); ++C_it; MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialFE2::advanceASR( const Matrix & prestrain) { AKANTU_DEBUG_IN(); for (auto && data : zip(RVEs, make_view(this->gradu(this->el_type), spatial_dimension, spatial_dimension), make_view(this->eigengradu(this->el_type), spatial_dimension, spatial_dimension), make_view(this->C(this->el_type), voigt_h::size, voigt_h::size), this->delta_T(this->el_type))) { auto & RVE = *(std::get<0>(data)); /// apply boundary conditions based on the current macroscopic displ. /// gradient RVE.applyBoundaryConditions(std::get<1>(data)); /// apply homogeneous temperature field to each RVE to obtain thermoelastic /// effect RVE.applyHomogeneousTemperature(std::get<4>(data)); /// advance the ASR in every RVE RVE.advanceASR(prestrain); /// compute the average eigen_grad_u RVE.homogenizeEigenGradU(std::get<2>(data)); /// compute the new effective stiffness of the RVE RVE.homogenizeStiffness(std::get<3>(data)); } AKANTU_DEBUG_OUT(); } INSTANTIATE_MATERIAL(material_FE2, MaterialFE2); } // namespace akantu diff --git a/extra_packages/extra-materials/src/material_FE2/material_FE2.hh b/extra_packages/extra-materials/src/material_FE2/material_FE2.hh index 8ab7018e0..976bcc871 100644 --- a/extra_packages/extra-materials/src/material_FE2/material_FE2.hh +++ b/extra_packages/extra-materials/src/material_FE2/material_FE2.hh @@ -1,115 +1,115 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "material.hh" #include "material_thermal.hh" /* -------------------------------------------------------------------------- */ #ifndef AKANTU_MATERIAL_FE_2_HH_ #define AKANTU_MATERIAL_FE_2_HH_ namespace akantu { class SolidMechanicsModelRVE; } namespace akantu { /* -------------------------------------------------------------------------- */ /// /!\ This material works ONLY for meshes with a single element type!!!!! /* -------------------------------------------------------------------------- */ /** * MaterialFE2 * * parameters in the material files : * - mesh_file */ template class MaterialFE2 : public MaterialThermal { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ private: typedef MaterialThermal Parent; public: MaterialFE2(SolidMechanicsModel & model, const ID & id = ""); virtual ~MaterialFE2(); typedef VoigtHelper voigt_h; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: virtual void initMaterial(); /// constitutive law for all element of a type virtual void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost); /// compute the tangent stiffness matrix for an element type void computeTangentModuli(ElementType el_type, Array & tangent_matrix, GhostType ghost_type = _not_ghost); /// advance alkali-silica reaction void advanceASR(const Matrix & prestrain); private: void initialize(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// Underlying RVE at each integration point std::vector> RVEs; /// Meshes for all RVEs std::vector> meshes; /// the element type of the associated mesh (this material handles only one /// type!!) ElementType el_type; /// the name of RVE mesh file ID mesh_file; /// Elastic stiffness tensor at each Gauss point (in voigt notation) InternalField C; /// number of gel pockets in each underlying RVE UInt nb_gel_pockets; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_FE2_inline_impl.hh" } // namespace akantu #endif /* AKANTU_MATERIAL_FE_2_HH_ */ diff --git a/extra_packages/extra-materials/src/material_FE2/material_FE2_inline_impl.hh b/extra_packages/extra-materials/src/material_FE2/material_FE2_inline_impl.hh index 9d9896118..0709c7cd5 100644 --- a/extra_packages/extra-materials/src/material_FE2/material_FE2_inline_impl.hh +++ b/extra_packages/extra-materials/src/material_FE2/material_FE2_inline_impl.hh @@ -1,20 +1,20 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ diff --git a/extra_packages/extra-materials/src/material_FE2/solid_mechanics_model_RVE.cc b/extra_packages/extra-materials/src/material_FE2/solid_mechanics_model_RVE.cc index 04eef1a38..06144882a 100644 --- a/extra_packages/extra-materials/src/material_FE2/solid_mechanics_model_RVE.cc +++ b/extra_packages/extra-materials/src/material_FE2/solid_mechanics_model_RVE.cc @@ -1,596 +1,596 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model_RVE.hh" #include "element_group.hh" #include "material_damage_iterative.hh" #include "node_group.hh" #include "non_linear_solver.hh" #include "non_local_manager.hh" #include "parser.hh" #include "sparse_matrix.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ SolidMechanicsModelRVE::SolidMechanicsModelRVE(Mesh & mesh, bool use_RVE_mat_selector, UInt nb_gel_pockets, Int dim, const ID & id) : SolidMechanicsModel(mesh, dim, id), volume(0.), use_RVE_mat_selector(use_RVE_mat_selector), nb_gel_pockets(nb_gel_pockets), nb_dumps(0) { AKANTU_DEBUG_IN(); /// find the four corner nodes of the RVE findCornerNodes(); /// remove the corner nodes from the surface node groups: /// This most be done because corner nodes a not periodic mesh.getElementGroup("top").removeNode(corner_nodes(2)); mesh.getElementGroup("top").removeNode(corner_nodes(3)); mesh.getElementGroup("left").removeNode(corner_nodes(3)); mesh.getElementGroup("left").removeNode(corner_nodes(0)); mesh.getElementGroup("bottom").removeNode(corner_nodes(1)); mesh.getElementGroup("bottom").removeNode(corner_nodes(0)); mesh.getElementGroup("right").removeNode(corner_nodes(2)); mesh.getElementGroup("right").removeNode(corner_nodes(1)); const auto & bottom = mesh.getElementGroup("bottom").getNodeGroup(); bottom_nodes.insert(bottom.begin(), bottom.end()); const auto & left = mesh.getElementGroup("left").getNodeGroup(); left_nodes.insert(left.begin(), left.end()); // /// enforce periodicity on the displacement fluctuations // auto surface_pair_1 = std::make_pair("top", "bottom"); // auto surface_pair_2 = std::make_pair("right", "left"); // SurfacePairList surface_pairs_list; // surface_pairs_list.push_back(surface_pair_1); // surface_pairs_list.push_back(surface_pair_2); // TODO: To Nicolas correct the PBCs // this->setPBC(surface_pairs_list); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SolidMechanicsModelRVE::~SolidMechanicsModelRVE() = default; /* -------------------------------------------------------------------------- */ void SolidMechanicsModelRVE::initFullImpl(const ModelOptions & options) { AKANTU_DEBUG_IN(); auto options_cp(options); options_cp.analysis_method = AnalysisMethod::_static; SolidMechanicsModel::initFullImpl(options_cp); // this->initMaterials(); auto & fem = this->getFEEngine("SolidMechanicsFEEngine"); /// compute the volume of the RVE GhostType gt = _not_ghost; for (auto element_type : this->mesh.elementTypes(spatial_dimension, gt, _ek_not_defined)) { Array Volume(this->mesh.getNbElement(element_type) * fem.getNbIntegrationPoints(element_type), 1, 1.); this->volume = fem.integrate(Volume, element_type); } std::cout << "The volume of the RVE is " << this->volume << std::endl; /// dumping std::stringstream base_name; base_name << this->id; this->setBaseName(base_name.str()); this->addDumpFieldVector("displacement"); this->addDumpField("stress"); this->addDumpField("grad_u"); this->addDumpField("eigen_grad_u"); this->addDumpField("blocked_dofs"); this->addDumpField("material_index"); this->addDumpField("damage"); this->addDumpField("Sc"); this->addDumpField("external_force"); this->addDumpField("equivalent_stress"); this->addDumpField("internal_force"); this->addDumpField("delta_T"); this->dump(); this->nb_dumps += 1; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelRVE::applyBoundaryConditions( const Matrix & displacement_gradient) { AKANTU_DEBUG_IN(); /// get the position of the nodes const Array & pos = mesh.getNodes(); /// storage for the coordinates of a given node and the displacement that will /// be applied Vector x(spatial_dimension); Vector appl_disp(spatial_dimension); /// fix top right node UInt node = this->corner_nodes(2); x(0) = pos(node, 0); x(1) = pos(node, 1); appl_disp.mul(displacement_gradient, x); (*this->blocked_dofs)(node, 0) = true; (*this->displacement)(node, 0) = appl_disp(0); (*this->blocked_dofs)(node, 1) = true; (*this->displacement)(node, 1) = appl_disp(1); // (*this->blocked_dofs)(node,0) = true; (*this->displacement)(node,0) = 0.; // (*this->blocked_dofs)(node,1) = true; (*this->displacement)(node,1) = 0.; /// apply Hx at all the other corner nodes; H: displ. gradient node = this->corner_nodes(0); x(0) = pos(node, 0); x(1) = pos(node, 1); appl_disp.mul(displacement_gradient, x); (*this->blocked_dofs)(node, 0) = true; (*this->displacement)(node, 0) = appl_disp(0); (*this->blocked_dofs)(node, 1) = true; (*this->displacement)(node, 1) = appl_disp(1); node = this->corner_nodes(1); x(0) = pos(node, 0); x(1) = pos(node, 1); appl_disp.mul(displacement_gradient, x); (*this->blocked_dofs)(node, 0) = true; (*this->displacement)(node, 0) = appl_disp(0); (*this->blocked_dofs)(node, 1) = true; (*this->displacement)(node, 1) = appl_disp(1); node = this->corner_nodes(3); x(0) = pos(node, 0); x(1) = pos(node, 1); appl_disp.mul(displacement_gradient, x); (*this->blocked_dofs)(node, 0) = true; (*this->displacement)(node, 0) = appl_disp(0); (*this->blocked_dofs)(node, 1) = true; (*this->displacement)(node, 1) = appl_disp(1); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelRVE::applyHomogeneousTemperature( const Real & temperature) { for (UInt m = 0; m < this->getNbMaterials(); ++m) { Material & mat = this->getMaterial(m); const ElementTypeMapArray & filter_map = mat.getElementFilter(); // Loop over all element types for (auto && type : filter_map.elementTypes(spatial_dimension)) { const Array & filter = filter_map(type); if (filter.size() == 0) continue; Array & delta_T = mat.getArray("delta_T", type); Array::scalar_iterator delta_T_it = delta_T.begin(); Array::scalar_iterator delta_T_end = delta_T.end(); for (; delta_T_it != delta_T_end; ++delta_T_it) { *delta_T_it = temperature; } } } } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelRVE::findCornerNodes() { AKANTU_DEBUG_IN(); // find corner nodes const auto & position = mesh.getNodes(); const auto & lower_bounds = mesh.getLowerBounds(); const auto & upper_bounds = mesh.getUpperBounds(); AKANTU_DEBUG_ASSERT(spatial_dimension == 2, "This is 2D only!"); corner_nodes.resize(4); corner_nodes.set(UInt(-1)); for (auto && data : enumerate(make_view(position, spatial_dimension))) { auto node = std::get<0>(data); const auto & X = std::get<1>(data); auto distance = X.distance(lower_bounds); // node 1 if (Math::are_float_equal(distance, 0)) { corner_nodes(0) = node; } // node 2 else if (Math::are_float_equal(X(_x), upper_bounds(_x)) && Math::are_float_equal(X(_y), lower_bounds(_y))) { corner_nodes(1) = node; } // node 3 else if (Math::are_float_equal(X(_x), upper_bounds(_x)) && Math::are_float_equal(X(_y), upper_bounds(_y))) { corner_nodes(2) = node; } // node 4 else if (Math::are_float_equal(X(_x), lower_bounds(_x)) && Math::are_float_equal(X(_y), upper_bounds(_y))) { corner_nodes(3) = node; } } for (UInt i = 0; i < corner_nodes.size(); ++i) { if (corner_nodes(i) == UInt(-1)) AKANTU_ERROR("The corner node " << i + 1 << " wasn't found"); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelRVE::advanceASR(const Matrix & prestrain) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(spatial_dimension == 2, "This is 2D only!"); /// apply the new eigenstrain for (auto element_type : mesh.elementTypes(spatial_dimension, _not_ghost, _ek_not_defined)) { Array & prestrain_vect = const_cast &>(this->getMaterial("gel").getInternal( "eigen_grad_u")(element_type)); auto prestrain_it = prestrain_vect.begin(spatial_dimension, spatial_dimension); auto prestrain_end = prestrain_vect.end(spatial_dimension, spatial_dimension); for (; prestrain_it != prestrain_end; ++prestrain_it) (*prestrain_it) = prestrain; } /// advance the damage MaterialDamageIterative<2> & mat_paste = dynamic_cast &>(*this->materials[1]); MaterialDamageIterative<2> & mat_aggregate = dynamic_cast &>(*this->materials[0]); UInt nb_damaged_elements = 0; Real max_eq_stress_aggregate = 0; Real max_eq_stress_paste = 0; auto & solver = this->getNonLinearSolver(); solver.set("max_iterations", 2); solver.set("threshold", 1e-6); solver.set("convergence_type", SolveConvergenceCriteria::_solution); do { this->solveStep(); /// compute damage max_eq_stress_aggregate = mat_aggregate.getNormMaxEquivalentStress(); max_eq_stress_paste = mat_paste.getNormMaxEquivalentStress(); nb_damaged_elements = 0; if (max_eq_stress_aggregate > max_eq_stress_paste) nb_damaged_elements = mat_aggregate.updateDamage(); else if (max_eq_stress_aggregate < max_eq_stress_paste) nb_damaged_elements = mat_paste.updateDamage(); else nb_damaged_elements = (mat_paste.updateDamage() + mat_aggregate.updateDamage()); std::cout << "the number of damaged elements is " << nb_damaged_elements << std::endl; } while (nb_damaged_elements); if (this->nb_dumps % 10 == 0) { this->dump(); } this->nb_dumps += 1; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModelRVE::averageTensorField(UInt row_index, UInt col_index, const ID & field_type) { AKANTU_DEBUG_IN(); auto & fem = this->getFEEngine("SolidMechanicsFEEngine"); Real average = 0; GhostType gt = _not_ghost; for (auto element_type : mesh.elementTypes(spatial_dimension, gt, _ek_not_defined)) { if (field_type == "stress") { for (UInt m = 0; m < this->materials.size(); ++m) { const auto & stress_vec = this->materials[m]->getStress(element_type); const auto & elem_filter = this->materials[m]->getElementFilter(element_type); Array int_stress_vec(elem_filter.size(), spatial_dimension * spatial_dimension, "int_of_stress"); fem.integrate(stress_vec, int_stress_vec, spatial_dimension * spatial_dimension, element_type, _not_ghost, elem_filter); for (UInt k = 0; k < elem_filter.size(); ++k) average += int_stress_vec(k, row_index * spatial_dimension + col_index); // 3 is the value // for the yy (in // 3D, the value is // 4) } } else if (field_type == "strain") { for (UInt m = 0; m < this->materials.size(); ++m) { const auto & gradu_vec = this->materials[m]->getGradU(element_type); const auto & elem_filter = this->materials[m]->getElementFilter(element_type); Array int_gradu_vec(elem_filter.size(), spatial_dimension * spatial_dimension, "int_of_gradu"); fem.integrate(gradu_vec, int_gradu_vec, spatial_dimension * spatial_dimension, element_type, _not_ghost, elem_filter); for (UInt k = 0; k < elem_filter.size(); ++k) /// averaging is done only for normal components, so stress and strain /// are equal average += 0.5 * (int_gradu_vec(k, row_index * spatial_dimension + col_index) + int_gradu_vec(k, col_index * spatial_dimension + row_index)); } } else if (field_type == "eigen_grad_u") { for (UInt m = 0; m < this->materials.size(); ++m) { const auto & eigen_gradu_vec = this->materials[m]->getInternal("eigen_grad_u")(element_type); const auto & elem_filter = this->materials[m]->getElementFilter(element_type); Array int_eigen_gradu_vec(elem_filter.size(), spatial_dimension * spatial_dimension, "int_of_gradu"); fem.integrate(eigen_gradu_vec, int_eigen_gradu_vec, spatial_dimension * spatial_dimension, element_type, _not_ghost, elem_filter); for (UInt k = 0; k < elem_filter.size(); ++k) /// averaging is done only for normal components, so stress and strain /// are equal average += int_eigen_gradu_vec(k, row_index * spatial_dimension + col_index); } } else { AKANTU_ERROR("Averaging not implemented for this field!!!"); } } return average / this->volume; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelRVE::homogenizeStiffness(Matrix & C_macro) { AKANTU_DEBUG_IN(); const Int dim = 2; AKANTU_DEBUG_ASSERT(this->spatial_dimension == dim, "Is only implemented for 2D!!!"); /// apply three independent loading states to determine C /// 1. eps_el = (1;0;0) 2. eps_el = (0,1,0) 3. eps_el = (0,0,0.5) /// clear the eigenstrain Matrix zero_eigengradu(dim, dim, 0.); GhostType gt = _not_ghost; for (auto element_type : mesh.elementTypes(dim, gt, _ek_not_defined)) { auto & prestrain_vect = const_cast &>(this->getMaterial("gel").getInternal( "eigen_grad_u")(element_type)); auto prestrain_it = prestrain_vect.begin(spatial_dimension, spatial_dimension); auto prestrain_end = prestrain_vect.end(spatial_dimension, spatial_dimension); for (; prestrain_it != prestrain_end; ++prestrain_it) (*prestrain_it) = zero_eigengradu; } /// storage for results of 3 different loading states UInt voigt_size = VoigtHelper::size; Matrix stresses(voigt_size, voigt_size, 0.); Matrix strains(voigt_size, voigt_size, 0.); Matrix H(dim, dim, 0.); /// save the damage state before filling up cracks // ElementTypeMapReal saved_damage("saved_damage"); // saved_damage.initialize(getFEEngine(), _nb_component = 1, _default_value = // 0); // this->fillCracks(saved_damage); /// virtual test 1: H(0, 0) = 0.01; this->performVirtualTesting(H, stresses, strains, 0); /// virtual test 2: H.zero(); H(1, 1) = 0.01; this->performVirtualTesting(H, stresses, strains, 1); /// virtual test 3: H.zero(); H(0, 1) = 0.01; this->performVirtualTesting(H, stresses, strains, 2); /// drain cracks // this->drainCracks(saved_damage); /// compute effective stiffness Matrix eps_inverse(voigt_size, voigt_size); eps_inverse.inverse(strains); C_macro.mul(stresses, eps_inverse); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelRVE::performVirtualTesting(const Matrix & H, Matrix & eff_stresses, Matrix & eff_strains, const UInt test_no) { AKANTU_DEBUG_IN(); this->applyBoundaryConditions(H); auto & solver = this->getNonLinearSolver(); solver.set("max_iterations", 2); solver.set("threshold", 1e-6); solver.set("convergence_type", SolveConvergenceCriteria::_solution); this->solveStep(); /// get average stress and strain eff_stresses(0, test_no) = this->averageTensorField(0, 0, "stress"); eff_strains(0, test_no) = this->averageTensorField(0, 0, "strain"); eff_stresses(1, test_no) = this->averageTensorField(1, 1, "stress"); eff_strains(1, test_no) = this->averageTensorField(1, 1, "strain"); eff_stresses(2, test_no) = this->averageTensorField(1, 0, "stress"); eff_strains(2, test_no) = 2. * this->averageTensorField(1, 0, "strain"); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelRVE::homogenizeEigenGradU( Matrix & eigen_gradu_macro) { AKANTU_DEBUG_IN(); eigen_gradu_macro(0, 0) = this->averageTensorField(0, 0, "eigen_grad_u"); eigen_gradu_macro(1, 1) = this->averageTensorField(1, 1, "eigen_grad_u"); eigen_gradu_macro(0, 1) = this->averageTensorField(0, 1, "eigen_grad_u"); eigen_gradu_macro(1, 0) = this->averageTensorField(1, 0, "eigen_grad_u"); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelRVE::initMaterials() { AKANTU_DEBUG_IN(); // make sure the material are instantiated if (!are_materials_instantiated) instantiateMaterials(); if (use_RVE_mat_selector) { const Vector & lowerBounds = mesh.getLowerBounds(); const Vector & upperBounds = mesh.getUpperBounds(); Real bottom = lowerBounds(1); Real top = upperBounds(1); Real box_size = std::abs(top - bottom); Real eps = box_size * 1e-6; auto tmp = std::make_shared(*this, box_size, "gel", this->nb_gel_pockets, eps); tmp->setFallback(material_selector); material_selector = tmp; } this->assignMaterialToElements(); // synchronize the element material arrays this->synchronize(SynchronizationTag::_material_id); for (auto & material : materials) { /// init internals properties const auto type = material->getID(); if (type.find("material_FE2") != std::string::npos) continue; material->initMaterial(); } this->synchronize(SynchronizationTag::_smm_init_mat); if (this->non_local_manager) { this->non_local_manager->initialize(); } // SolidMechanicsModel::initMaterials(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelRVE::fillCracks(ElementTypeMapReal & saved_damage) { const auto & mat_gel = this->getMaterial("gel"); Real E_gel = mat_gel.get("E"); Real E_homogenized = 0.; for (auto && mat : materials) { if (mat->getName() == "gel" || mat->getName() == "FE2_mat") continue; Real E = mat->get("E"); auto & damage = mat->getInternal("damage"); for (auto && type : damage.elementTypes()) { const auto & elem_filter = mat->getElementFilter(type); auto nb_integration_point = getFEEngine().getNbIntegrationPoints(type); auto sav_dam_it = make_view(saved_damage(type), nb_integration_point).begin(); for (auto && data : zip(elem_filter, make_view(damage(type), nb_integration_point))) { auto el = std::get<0>(data); auto & dam = std::get<1>(data); Vector sav_dam = sav_dam_it[el]; sav_dam = dam; for (auto q : arange(dam.size())) { E_homogenized = (E_gel - E) * dam(q) + E; dam(q) = 1. - (E_homogenized / E); } } } } } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelRVE::drainCracks( const ElementTypeMapReal & saved_damage) { for (auto && mat : materials) { if (mat->getName() == "gel" || mat->getName() == "FE2_mat") continue; auto & damage = mat->getInternal("damage"); for (auto && type : damage.elementTypes()) { const auto & elem_filter = mat->getElementFilter(type); auto nb_integration_point = getFEEngine().getNbIntegrationPoints(type); auto sav_dam_it = make_view(saved_damage(type), nb_integration_point).begin(); for (auto && data : zip(elem_filter, make_view(damage(type), nb_integration_point))) { auto el = std::get<0>(data); auto & dam = std::get<1>(data); Vector sav_dam = sav_dam_it[el]; dam = sav_dam; } } } } } // namespace akantu diff --git a/extra_packages/extra-materials/src/material_FE2/solid_mechanics_model_RVE.hh b/extra_packages/extra-materials/src/material_FE2/solid_mechanics_model_RVE.hh index 5c2fcc243..217f66618 100644 --- a/extra_packages/extra-materials/src/material_FE2/solid_mechanics_model_RVE.hh +++ b/extra_packages/extra-materials/src/material_FE2/solid_mechanics_model_RVE.hh @@ -1,224 +1,224 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #ifndef AKANTU_SOLID_MECHANICS_MODEL_RVE_HH_ #define AKANTU_SOLID_MECHANICS_MODEL_RVE_HH_ /* -------------------------------------------------------------------------- */ #include "aka_grid_dynamic.hh" #include "solid_mechanics_model.hh" #include /* -------------------------------------------------------------------------- */ namespace akantu { class SolidMechanicsModelRVE : public SolidMechanicsModel { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: SolidMechanicsModelRVE(Mesh & mesh, bool use_RVE_mat_selector = true, UInt nb_gel_pockets = 400, Int spatial_dimension = _all_dimensions, const ID & id = "solid_mechanics_model"); virtual ~SolidMechanicsModelRVE(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ protected: void initFullImpl(const ModelOptions & option) override; /// initialize the materials void initMaterials() override; public: /// apply boundary contions based on macroscopic deformation gradient virtual void applyBoundaryConditions(const Matrix & displacement_gradient); /// apply homogeneous temperature field from the macroscale level to the RVEs virtual void applyHomogeneousTemperature(const Real & temperature); /// advance the reactions -> grow gel and apply homogenized properties void advanceASR(const Matrix & prestrain); /// compute average stress or strain in the model Real averageTensorField(UInt row_index, UInt col_index, const ID & field_type); /// compute effective stiffness of the RVE void homogenizeStiffness(Matrix & C_macro); /// compute average eigenstrain void homogenizeEigenGradU(Matrix & eigen_gradu_macro); /* ------------------------------------------------------------------------ */ /* Data Accessor inherited members */ /* ------------------------------------------------------------------------ */ inline void unpackData(CommunicationBuffer & buffer, const Array & index, const SynchronizationTag & tag) override; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(CornerNodes, corner_nodes, const Array &); AKANTU_GET_MACRO(Volume, volume, Real); private: /// find the corner nodes void findCornerNodes(); /// perform virtual testing void performVirtualTesting(const Matrix & H, Matrix & eff_stresses, Matrix & eff_strains, const UInt test_no); void fillCracks(ElementTypeMapReal & saved_damage); void drainCracks(const ElementTypeMapReal & saved_damage); /* ------------------------------------------------------------------------ */ /* Members */ /* ------------------------------------------------------------------------ */ /// volume of the RVE Real volume; /// corner nodes 1, 2, 3, 4 (see Leonardo's thesis, page 98) Array corner_nodes; /// bottom nodes std::unordered_set bottom_nodes; /// left nodes std::unordered_set left_nodes; /// standard mat selector or user one bool use_RVE_mat_selector; /// the number of gel pockets inside the RVE UInt nb_gel_pockets; /// dump counter UInt nb_dumps; }; inline void SolidMechanicsModelRVE::unpackData(CommunicationBuffer & buffer, const Array & index, const SynchronizationTag & tag) { SolidMechanicsModel::unpackData(buffer, index, tag); // if (tag == SynchronizationTag::_smm_uv) { // auto disp_it = displacement->begin(spatial_dimension); // // for (auto node : index) { // Vector current_disp(disp_it[node]); // // // if node is at the bottom, u_bottom = u_top +u_2 -u_3 // if (bottom_nodes.count(node)) { // current_disp += Vector(disp_it[corner_nodes(1)]); // current_disp -= Vector(disp_it[corner_nodes(2)]); // } // // if node is at the left, u_left = u_right +u_4 -u_3 // else if (left_nodes.count(node)) { // current_disp += Vector(disp_it[corner_nodes(3)]); // current_disp -= Vector(disp_it[corner_nodes(2)]); // } // } // } } /* -------------------------------------------------------------------------- */ /* ASR material selector */ /* -------------------------------------------------------------------------- */ class GelMaterialSelector : public MeshDataMaterialSelector { public: GelMaterialSelector(SolidMechanicsModel & model, const Real box_size, const std::string & gel_material, const UInt nb_gel_pockets, Real /*tolerance*/ = 0.) : MeshDataMaterialSelector("physical_names", model), model(model), gel_material(gel_material), nb_gel_pockets(nb_gel_pockets), nb_placed_gel_pockets(0), box_size(box_size) { Mesh & mesh = this->model.getMesh(); Int spatial_dimension = model.getSpatialDimension(); Element el{_triangle_3, 0, _not_ghost}; UInt nb_element = mesh.getNbElement(el.type, el.ghost_type); Array barycenter(nb_element, spatial_dimension); for (auto && data : enumerate(make_view(barycenter, spatial_dimension))) { el.element = std::get<0>(data); auto & bary = std::get<1>(data); mesh.getBarycenter(el, bary); } /// generate the gel pockets srand(0.); Vector center(spatial_dimension); UInt placed_gel_pockets = 0; std::set checked_baries; while (placed_gel_pockets != nb_gel_pockets) { /// get a random bary center UInt bary_id = rand() % nb_element; if (checked_baries.find(bary_id) != checked_baries.end()) continue; checked_baries.insert(bary_id); el.element = bary_id; if (MeshDataMaterialSelector::operator()(el) == 1) continue; /// element belongs to paste gel_pockets.push_back(el); placed_gel_pockets += 1; } } UInt operator()(const Element & elem) { UInt temp_index = MeshDataMaterialSelector::operator()(elem); if (temp_index == 1) return temp_index; std::vector::const_iterator iit = gel_pockets.begin(); std::vector::const_iterator eit = gel_pockets.end(); if (std::find(iit, eit, elem) != eit) { nb_placed_gel_pockets += 1; std::cout << nb_placed_gel_pockets << " gelpockets placed" << std::endl; return model.getMaterialIndex(gel_material); ; } return 0; } protected: SolidMechanicsModel & model; std::string gel_material; std::vector gel_pockets; UInt nb_gel_pockets; UInt nb_placed_gel_pockets; Real box_size; }; } // namespace akantu ///#include "material_selector_tmpl.hh" #endif /* AKANTU_SOLID_MECHANICS_MODEL_RVE_HH_ */ diff --git a/extra_packages/extra-materials/src/material_damage/material_brittle.cc b/extra_packages/extra-materials/src/material_damage/material_brittle.cc index a52f21024..d341c64fe 100644 --- a/extra_packages/extra-materials/src/material_damage/material_brittle.cc +++ b/extra_packages/extra-materials/src/material_damage/material_brittle.cc @@ -1,128 +1,128 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "material_brittle.hh" #include "solid_mechanics_model.hh" namespace akantu { /* -------------------------------------------------------------------------- */ template MaterialBrittle::MaterialBrittle(SolidMechanicsModel & model, const ID & id) : MaterialDamage(model, id), strain_rate_brittle("strain_rate_brittle", *this) { AKANTU_DEBUG_IN(); this->registerParam("S_0", S_0, 157e6, _pat_parsable | _pat_modifiable); this->registerParam("E_0", E_0, 27e3, _pat_parsable, "Strain rate threshold"); this->registerParam("A", A, 1.622e-5, _pat_parsable, "Polynome cubic constant"); this->registerParam("B", B, -1.3274, _pat_parsable, "Polynome quadratic constant"); this->registerParam("C", C, 3.6544e4, _pat_parsable, "Polynome linear constant"); this->registerParam("D", D, -181.38e6, _pat_parsable, "Polynome constant"); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialBrittle::initMaterial() { AKANTU_DEBUG_IN(); MaterialDamage::initMaterial(); this->strain_rate_brittle.initialize(spatial_dimension * spatial_dimension); updateInternalParameters(); // this->Yd.resize(); // const Mesh & mesh = this->model.getFEEngine().getMesh(); // Mesh::type_iterator it = mesh.firstType(spatial_dimension); // Mesh::type_iterator last_type = mesh.lastType(spatial_dimension); // for(; it != last_type; ++it) { // UInt nb_element = this->element_filter(*it).getSize(); // UInt nb_quad = this->model.getFEEngine().getNbQuadraturePoints(*it); // Array & Yd_rand_vec = Yd_rand(*it); // for(UInt e = 0; e < nb_element; ++e) { // Real rand_part = (2 * drand48()-1) * Yd_randomness * Yd; // for(UInt q = 0; q < nb_quad; ++q) // Yd_rand_vec(nb_quad*e+q,0) = Yd + rand_part; // } // } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialBrittle::updateInternalParameters() { MaterialDamage::updateInternalParameters(); } /* -------------------------------------------------------------------------- */ template void MaterialBrittle::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Real * dam = this->damage(el_type, ghost_type).data(); Array & velocity = this->model.getVelocity(); Array & strain_rate_brittle = this->strain_rate_brittle(el_type, ghost_type); Array & elem_filter = this->element_filter(el_type, ghost_type); this->model.getFEEngine().gradientOnIntegrationPoints( velocity, strain_rate_brittle, spatial_dimension, el_type, ghost_type, elem_filter); Array::iterator> strain_rate_it = this->strain_rate_brittle(el_type, ghost_type) .begin(spatial_dimension, spatial_dimension); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); Real sigma_equivalent = 0; Real fracture_stress = 0; Matrix & grad_v = *strain_rate_it; computeStressOnQuad(grad_u, grad_v, sigma, *dam, sigma_equivalent, fracture_stress); ++strain_rate_it; ++dam; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ INSTANTIATE_MATERIAL(brittle, MaterialBrittle); } // namespace akantu diff --git a/extra_packages/extra-materials/src/material_damage/material_brittle.hh b/extra_packages/extra-materials/src/material_damage/material_brittle.hh index ccb792777..014245584 100644 --- a/extra_packages/extra-materials/src/material_damage/material_brittle.hh +++ b/extra_packages/extra-materials/src/material_damage/material_brittle.hh @@ -1,116 +1,116 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material.hh" #include "material_damage.hh" /* -------------------------------------------------------------------------- */ #ifndef AKANTU_MATERIAL_BRITTLE_HH_ #define AKANTU_MATERIAL_BRITTLE_HH_ namespace akantu { /** * Material brittle * * parameters in the material files : * - S_0 : Critical stress at low strain rate (default: 157e6) * - E_0 : Low strain rate threshold (default: 27e3) * - A,B,C,D : Fitting parameters for the critical stress at high strain * rates * (default: 1.622e-11, -1.3274e-6, 3.6544e-2, -181.38) */ template class MaterialBrittle : public MaterialDamage { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialBrittle(SolidMechanicsModel & model, const ID & id = ""); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void initMaterial() override; void updateInternalParameters() override; /// constitutive law for all element of a type void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost) override; protected: /// constitutive law for a given quadrature point inline void computeStressOnQuad(Matrix & grad_u, Matrix & grad_v, Matrix & sigma, Real & dam, Real & sigma_equivalent, Real & fracture_stress); inline void computeDamageAndStressOnQuad(Matrix & sigma, Real & dam, Real & sigma_c, Real & fracture_stress); /* ------------------------------------------------------------------------ */ /* DataAccessor inherited members */ /* ------------------------------------------------------------------------ */ public: inline UInt getNbData(const Array & elements, const SynchronizationTag & tag) const override; inline void packData(CommunicationBuffer & buffer, const Array & elements, const SynchronizationTag & tag) const override; inline void unpackData(CommunicationBuffer & buffer, const Array & elements, const SynchronizationTag & tag) override; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// strain rate arrays ordered by element types InternalField strain_rate_brittle; // polynome constants for critical stress value Real A; Real B; Real C; Real D; // minimum strain rate Real E_0; // Critical stress at low strain rates Real S_0; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_brittle_inline_impl.hh" } // namespace akantu #endif /* AKANTU_MATERIAL_brittle_HH_ */ diff --git a/extra_packages/extra-materials/src/material_damage/material_brittle_inline_impl.hh b/extra_packages/extra-materials/src/material_damage/material_brittle_inline_impl.hh index d67ef9fe8..4a06991d4 100644 --- a/extra_packages/extra-materials/src/material_damage/material_brittle_inline_impl.hh +++ b/extra_packages/extra-materials/src/material_damage/material_brittle_inline_impl.hh @@ -1,106 +1,106 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ template inline void MaterialBrittle::computeStressOnQuad( Matrix & grad_u, Matrix & grad_v, Matrix & sigma, Real & dam, Real & sigma_equivalent, Real & fracture_stress) { MaterialElastic::computeStressOnQuad(grad_u, sigma); Real equiv_strain_rate = 0.; Real volume_change_rate = grad_v.trace(); if (spatial_dimension == 2) { equiv_strain_rate += 2. / 3. * pow(volume_change_rate / 3., 2.); } for (Int i = 0; i < spatial_dimension; ++i) for (Int j = 0; j < spatial_dimension; ++j) equiv_strain_rate += 2. / 3. * pow(0.5 * (grad_v(i, j) + grad_v(j, i)) - (i == j) * volume_change_rate / 3., 2.); equiv_strain_rate = sqrt(equiv_strain_rate); fracture_stress = S_0; if (equiv_strain_rate > E_0) fracture_stress = A; Vector principal_stress(spatial_dimension); sigma.eig(principal_stress); sigma_equivalent = principal_stress(0); for (Int i = 1; i < spatial_dimension; ++i) sigma_equivalent = std::max(sigma_equivalent, principal_stress(i)); if (!this->is_non_local) { computeDamageAndStressOnQuad(sigma, dam, sigma_equivalent, fracture_stress); } } /* -------------------------------------------------------------------------- */ template inline void MaterialBrittle::computeDamageAndStressOnQuad( Matrix & sigma, Real & dam, Real & sigma_c, Real & fracture_stress) { if (sigma_c > fracture_stress) dam = 1.; dam = std::min(dam, 1.); sigma *= 1 - dam; } /* -------------------------------------------------------------------------- */ template inline UInt MaterialBrittle::getNbData( const Array & elements, const SynchronizationTag & tag) const { AKANTU_DEBUG_IN(); UInt size = MaterialDamage::getNbData(elements, tag); AKANTU_DEBUG_OUT(); return size; } /* -------------------------------------------------------------------------- */ template inline void MaterialBrittle::packData( CommunicationBuffer & buffer, const Array & elements, const SynchronizationTag & tag) const { AKANTU_DEBUG_IN(); MaterialDamage::packData(buffer, elements, tag); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template inline void MaterialBrittle::unpackData(CommunicationBuffer & buffer, const Array & elements, const SynchronizationTag & tag) { AKANTU_DEBUG_IN(); MaterialDamage::unpackData(buffer, elements, tag); AKANTU_DEBUG_OUT(); } diff --git a/extra_packages/extra-materials/src/material_damage/material_brittle_non_local.hh b/extra_packages/extra-materials/src/material_damage/material_brittle_non_local.hh index cdc22204b..014e7e986 100644 --- a/extra_packages/extra-materials/src/material_damage/material_brittle_non_local.hh +++ b/extra_packages/extra-materials/src/material_damage/material_brittle_non_local.hh @@ -1,94 +1,94 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material_brittle.hh" #include "material_damage_non_local.hh" /* -------------------------------------------------------------------------- */ #ifndef AKANTU_MATERIAL_BRITTLE_NON_LOCAL_HH_ #define AKANTU_MATERIAL_BRITTLE_NON_LOCAL_HH_ namespace akantu { /** * Material Brittle Non local * * parameters in the material files : */ template class MaterialBrittleNonLocal : public MaterialDamageNonLocal> { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: typedef MaterialDamageNonLocal> MaterialBrittleNonLocalParent; MaterialBrittleNonLocal(SolidMechanicsModel & model, const ID & id = ""); virtual ~MaterialBrittleNonLocal(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void initMaterial(); protected: /// constitutive law void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost); void computeNonLocalStress(ElementType type, GhostType ghost_type = _not_ghost); /// associate the non-local variables of the material to their neighborhoods virtual void nonLocalVariableToNeighborhood(); private: /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Sigma_max, Sigma_max, Real); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: InternalField Sigma_max; InternalField Sigma_maxnl; InternalField Sigma_fracture; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_brittle_non_local_inline_impl.hh" } // namespace akantu #endif /* AKANTU_MATERIAL_BRITTLE_NON_LOCAL_HH_ */ diff --git a/extra_packages/extra-materials/src/material_damage/material_brittle_non_local_inline_impl.hh b/extra_packages/extra-materials/src/material_damage/material_brittle_non_local_inline_impl.hh index 3f4498ca8..09669d616 100644 --- a/extra_packages/extra-materials/src/material_damage/material_brittle_non_local_inline_impl.hh +++ b/extra_packages/extra-materials/src/material_damage/material_brittle_non_local_inline_impl.hh @@ -1,122 +1,122 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ } // namespace akantu #if defined(AKANTU_DEBUG_TOOLS) #include "aka_debug_tools.hh" #include #endif namespace akantu { /* -------------------------------------------------------------------------- */ template MaterialBrittleNonLocal::MaterialBrittleNonLocal( SolidMechanicsModel & model, const ID & id) : Material(model, id), MaterialBrittleNonLocalParent(model, id), Sigma_max("Sigma max", *this), Sigma_maxnl("Sigma_max non local", *this), Sigma_fracture("Sigma_fracture", *this) { AKANTU_DEBUG_IN(); this->is_non_local = true; this->Sigma_max.initialize(1); this->Sigma_maxnl.initialize(1); this->Sigma_fracture.initialize(1); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialBrittleNonLocal::initMaterial() { AKANTU_DEBUG_IN(); this->model.getNonLocalManager().registerNonLocalVariable( this->Sigma_max.getName(), Sigma_maxnl.getName(), 1); MaterialBrittleNonLocalParent::initMaterial(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialBrittleNonLocal::computeStress( ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Real * dam = this->damage(el_type, ghost_type).data(); Real * Sigma_maxt = this->Sigma_max(el_type, ghost_type).data(); Real * fracture_stress = this->Sigma_fracture(el_type, ghost_type).data(); Array & velocity = this->model.getVelocity(); Array & strain_rate_brittle = this->strain_rate_brittle(el_type, ghost_type); Array & elem_filter = this->element_filter(el_type, ghost_type); this->model.getFEEngine().gradientOnIntegrationPoints( velocity, strain_rate_brittle, spatial_dimension, el_type, ghost_type, elem_filter); Array::iterator> strain_rate_it = this->strain_rate_brittle(el_type, ghost_type) .begin(spatial_dimension, spatial_dimension); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); Matrix & grad_v = *strain_rate_it; MaterialBrittle::computeStressOnQuad( grad_u, grad_v, sigma, *dam, *Sigma_maxt, *fracture_stress); ++dam; ++strain_rate_it; ++Sigma_maxt; ++fracture_stress; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialBrittleNonLocal::computeNonLocalStress( ElementType type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Real * dam = this->damage(type, ghost_type).data(); Real * Sigma_maxnlt = this->Sigma_maxnl(type, ghost_type).data(); Real * fracture_stress = this->Sigma_fracture(type, ghost_type).data(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(type, ghost_type); this->computeDamageAndStressOnQuad(sigma, *dam, *Sigma_maxnlt, *fracture_stress); ++dam; ++Sigma_maxnlt; ++fracture_stress; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialBrittleNonLocal< spatial_dimension>::nonLocalVariableToNeighborhood() { this->model.getNonLocalManager().nonLocalVariableToNeighborhood( Sigma_maxnl.getName(), this->name); } diff --git a/extra_packages/extra-materials/src/material_damage/material_damage_iterative.cc b/extra_packages/extra-materials/src/material_damage/material_damage_iterative.cc index 2ba7ed955..b5406de88 100644 --- a/extra_packages/extra-materials/src/material_damage/material_damage_iterative.cc +++ b/extra_packages/extra-materials/src/material_damage/material_damage_iterative.cc @@ -1,250 +1,250 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "material_damage_iterative.hh" #include "communicator.hh" #include "data_accessor.hh" #include "solid_mechanics_model_RVE.hh" /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ template MaterialDamageIterative::MaterialDamageIterative( SolidMechanicsModel & model, const ID & id) : MaterialDamage(model, id), Sc("Sc", *this), reduction_step("damage_step", *this), equivalent_stress("equivalent_stress", *this), max_reductions(0), norm_max_equivalent_stress(0) { AKANTU_DEBUG_IN(); this->registerParam("Sc", Sc, _pat_parsable, "critical stress threshold"); this->registerParam("prescribed_dam", prescribed_dam, 0.1, _pat_parsable | _pat_modifiable, "prescribed damage"); this->registerParam( "dam_threshold", dam_threshold, 0.8, _pat_parsable | _pat_modifiable, "damage threshold at which damage damage will be set to 1"); this->registerParam( "dam_tolerance", dam_tolerance, 0.01, _pat_parsable | _pat_modifiable, "damage tolerance to decide if quadrature point will be damageed"); this->registerParam("max_damage", max_damage, 0.99999, _pat_parsable | _pat_modifiable, "maximum damage value"); this->registerParam("max_reductions", max_reductions, UInt(10), _pat_parsable | _pat_modifiable, "max reductions"); this->use_previous_stress = true; this->use_previous_gradu = true; this->Sc.initialize(1); this->equivalent_stress.initialize(1); this->reduction_step.initialize(1); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialDamageIterative:: computeNormalizedEquivalentStress(const Array & grad_u, ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); /// Vector to store eigenvalues of current stress tensor Vector eigenvalues(spatial_dimension); auto Sc_it = Sc(el_type, ghost_type).begin(); auto equivalent_stress_it = equivalent_stress(el_type, ghost_type).begin(); Array::const_matrix_iterator grad_u_it = grad_u.begin(spatial_dimension, spatial_dimension); Array::const_matrix_iterator grad_u_end = grad_u.end(spatial_dimension, spatial_dimension); Real * dam = this->damage(el_type, ghost_type).data(); Matrix sigma(spatial_dimension, spatial_dimension); for (; grad_u_it != grad_u_end; ++grad_u_it) { sigma.zero(); MaterialElastic::computeStressOnQuad(*grad_u_it, sigma, 0.); computeDamageAndStressOnQuad(sigma, *dam); /// compute eigenvalues sigma.eig(eigenvalues); /// find max eigenvalue and normalize by tensile strength *equivalent_stress_it = *(std::max_element(eigenvalues.data(), eigenvalues.data() + spatial_dimension)) / *(Sc_it); ++Sc_it; ++equivalent_stress_it; ++dam; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialDamageIterative::computeAllStresses( GhostType ghost_type) { AKANTU_DEBUG_IN(); /// reset normalized maximum equivalent stress if (ghost_type == _not_ghost) norm_max_equivalent_stress = 0; MaterialDamage::computeAllStresses(ghost_type); /// find global Gauss point with highest stress auto rve_model = dynamic_cast(&this->model); if (rve_model == NULL) { /// is no RVE model const auto & comm = this->model.getMesh().getCommunicator(); comm.allReduce(norm_max_equivalent_stress, SynchronizerOperation::_max); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialDamageIterative:: findMaxNormalizedEquivalentStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); if (ghost_type == _not_ghost) { // const Array & e_stress = equivalent_stress(el_type); // if (e_stress.begin() != e_stress.end() ) { // auto equivalent_stress_it_max = // std::max_element(e_stress.begin(),e_stress.end()); // /// check if max equivalent stress for this element type is greater // than the current norm_max_eq_stress // if (*equivalent_stress_it_max > norm_max_equivalent_stress) // norm_max_equivalent_stress = *equivalent_stress_it_max; // } const Array & e_stress = equivalent_stress(el_type); auto equivalent_stress_it = e_stress.begin(); auto equivalent_stress_end = e_stress.end(); Array & dam = this->damage(el_type); auto dam_it = dam.begin(); for (; equivalent_stress_it != equivalent_stress_end; ++equivalent_stress_it, ++dam_it) { /// check if max equivalent stress for this element type is greater than /// the current norm_max_eq_stress and if the element is not already fully /// damaged if (*equivalent_stress_it > norm_max_equivalent_stress && *dam_it < max_damage) { norm_max_equivalent_stress = *equivalent_stress_it; } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialDamageIterative::computeStress( ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); MaterialDamage::computeStress(el_type, ghost_type); Real * dam = this->damage(el_type, ghost_type).data(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); computeDamageAndStressOnQuad(sigma, *dam); ++dam; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; computeNormalizedEquivalentStress(this->gradu(el_type, ghost_type), el_type, ghost_type); norm_max_equivalent_stress = 0; findMaxNormalizedEquivalentStress(el_type, ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template UInt MaterialDamageIterative::updateDamage() { UInt nb_damaged_elements = 0; AKANTU_DEBUG_ASSERT(prescribed_dam > 0., "Your prescribed damage must be greater than zero"); if (norm_max_equivalent_stress >= 1.) { AKANTU_DEBUG_IN(); /// update the damage only on non-ghosts elements! Doesn't make sense to /// update on ghost. GhostType ghost_type = _not_ghost; for (auto && el_type : this->model.getFEEngine().getMesh().elementTypes( spatial_dimension, ghost_type)) { const Array & e_stress = equivalent_stress(el_type); auto equivalent_stress_it = e_stress.begin(); auto equivalent_stress_end = e_stress.end(); Array & dam = this->damage(el_type); auto dam_it = dam.begin(); auto reduction_it = this->reduction_step(el_type, ghost_type).begin(); for (; equivalent_stress_it != equivalent_stress_end; ++equivalent_stress_it, ++dam_it, ++reduction_it) { /// check if damage occurs if (*equivalent_stress_it >= (1 - dam_tolerance) * norm_max_equivalent_stress) { /// check if this element can still be damaged if (*reduction_it == this->max_reductions) continue; *reduction_it += 1; if (*reduction_it == this->max_reductions) { *dam_it = max_damage; } else { *dam_it += prescribed_dam; } nb_damaged_elements += 1; } } } } auto * rve_model = dynamic_cast(&this->model); if (rve_model == NULL) { const auto & comm = this->model.getMesh().getCommunicator(); comm.allReduce(nb_damaged_elements, SynchronizerOperation::_sum); } AKANTU_DEBUG_OUT(); return nb_damaged_elements; } /* -------------------------------------------------------------------------- */ template void MaterialDamageIterative::updateEnergiesAfterDamage( ElementType el_type) { MaterialDamage::updateEnergies(el_type); } /* -------------------------------------------------------------------------- */ INSTANTIATE_MATERIAL(damage_iterative, MaterialDamageIterative); } // namespace akantu diff --git a/extra_packages/extra-materials/src/material_damage/material_damage_iterative.hh b/extra_packages/extra-materials/src/material_damage/material_damage_iterative.hh index d8c521c40..1a1841eb1 100644 --- a/extra_packages/extra-materials/src/material_damage/material_damage_iterative.hh +++ b/extra_packages/extra-materials/src/material_damage/material_damage_iterative.hh @@ -1,149 +1,149 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material.hh" #include "material_damage.hh" /* -------------------------------------------------------------------------- */ #ifndef AKANTU_MATERIAL_DAMAGE_ITERATIVE_HH_ #define AKANTU_MATERIAL_DAMAGE_ITERATIVE_HH_ namespace akantu { /** * Material damage iterative * * parameters in the material files : * - Sc */ template class MaterialDamageIterative : public MaterialDamage { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialDamageIterative(SolidMechanicsModel & model, const ID & id = ""); ~MaterialDamageIterative() override = default; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// virtual void updateInternalParameters(); void computeAllStresses(GhostType ghost_type = _not_ghost) override; /// update internal field damage virtual UInt updateDamage(); UInt updateDamage(UInt quad_index, Real eq_stress, ElementType el_type, GhostType ghost_type); /// update energies after damage has been updated void updateEnergiesAfterDamage(ElementType el_type) override; /// compute the equivalent stress on each Gauss point (i.e. the max prinicpal /// stress) and normalize it by the tensile strength virtual void computeNormalizedEquivalentStress(const Array & grad_u, ElementType el_type, GhostType ghost_type = _not_ghost); /// find max normalized equivalent stress void findMaxNormalizedEquivalentStress(ElementType el_type, GhostType ghost_type = _not_ghost); protected: /// constitutive law for all element of a type void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost) override; inline void computeDamageAndStressOnQuad(Matrix & sigma, Real & dam); /* ------------------------------------------------------------------------ */ /* DataAccessor inherited members */ /* ------------------------------------------------------------------------ */ inline UInt getNbData(const Array & elements, const SynchronizationTag & tag) const override; inline void packData(CommunicationBuffer & buffer, const Array & elements, const SynchronizationTag & tag) const override; inline void unpackData(CommunicationBuffer & buffer, const Array & elements, const SynchronizationTag & tag) override; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get max normalized equivalent stress AKANTU_GET_MACRO(NormMaxEquivalentStress, norm_max_equivalent_stress, Real); /// get a non-const reference to the max normalized equivalent stress AKANTU_GET_MACRO_NOT_CONST(NormMaxEquivalentStress, norm_max_equivalent_stress, Real &); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// resistance to damage RandomInternalField Sc; /// the reduction InternalField reduction_step; /// internal field to store equivalent stress on each Gauss point InternalField equivalent_stress; /// the number of total reductions steps until complete failure UInt max_reductions; /// damage increment Real prescribed_dam; /// maximum equivalent stress Real norm_max_equivalent_stress; /// deviation from max stress at which Gauss point will still get damaged Real dam_tolerance; /// define damage threshold at which damage will be set to 1 Real dam_threshold; /// maximum damage value Real max_damage; }; } // namespace akantu /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_damage_iterative_inline_impl.hh" #endif /* AKANTU_MATERIAL_DAMAGE_ITERATIVE_HH_ */ diff --git a/extra_packages/extra-materials/src/material_damage/material_damage_iterative_inline_impl.hh b/extra_packages/extra-materials/src/material_damage/material_damage_iterative_inline_impl.hh index d7858072c..d06fd9f0d 100644 --- a/extra_packages/extra-materials/src/material_damage/material_damage_iterative_inline_impl.hh +++ b/extra_packages/extra-materials/src/material_damage/material_damage_iterative_inline_impl.hh @@ -1,98 +1,98 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "material_damage_iterative.hh" /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ template inline void MaterialDamageIterative::computeDamageAndStressOnQuad( Matrix & sigma, Real & dam) { sigma *= 1 - dam; } /* -------------------------------------------------------------------------- */ template UInt MaterialDamageIterative::updateDamage( UInt quad_index, const Real /*eq_stress*/, ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_ASSERT(prescribed_dam > 0., "Your prescribed damage must be greater than zero"); Array & dam = this->damage(el_type, ghost_type); Real & dam_on_quad = dam(quad_index); /// check if damage occurs if (equivalent_stress(el_type, ghost_type)(quad_index) >= (1 - dam_tolerance) * norm_max_equivalent_stress) { if (dam_on_quad < dam_threshold) dam_on_quad += prescribed_dam; else dam_on_quad = max_damage; return 1; } return 0; } /* -------------------------------------------------------------------------- */ template inline UInt MaterialDamageIterative::getNbData( const Array & elements, const SynchronizationTag & tag) const { if (tag == SynchronizationTag::_user_2) { return sizeof(Real) * this->getModel().getNbIntegrationPoints(elements); } return MaterialDamage::getNbData(elements, tag); } /* -------------------------------------------------------------------------- */ template inline void MaterialDamageIterative::packData( CommunicationBuffer & buffer, const Array & elements, const SynchronizationTag & tag) const { if (tag == SynchronizationTag::_user_2) { DataAccessor::packElementalDataHelper( this->damage, buffer, elements, true, this->damage.getFEEngine()); } return MaterialDamage::packData(buffer, elements, tag); } /* -------------------------------------------------------------------------- */ template inline void MaterialDamageIterative::unpackData( CommunicationBuffer & buffer, const Array & elements, const SynchronizationTag & tag) { if (tag == SynchronizationTag::_user_2) { DataAccessor::unpackElementalDataHelper( this->damage, buffer, elements, true, this->damage.getFEEngine()); } return MaterialDamage::unpackData(buffer, elements, tag); } } // namespace akantu /* -------------------------------------------------------------------------- */ diff --git a/extra_packages/extra-materials/src/material_damage/material_damage_iterative_non_local.cc b/extra_packages/extra-materials/src/material_damage/material_damage_iterative_non_local.cc index c9ee353f5..fafca4525 100644 --- a/extra_packages/extra-materials/src/material_damage/material_damage_iterative_non_local.cc +++ b/extra_packages/extra-materials/src/material_damage/material_damage_iterative_non_local.cc @@ -1,47 +1,47 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "material_damage_iterative_non_local.hh" namespace akantu { /* -------------------------------------------------------------------------- */ template void MaterialDamageIterativeNonLocal< spatial_dimension>::computeNonLocalStresses(GhostType ghost_type) { AKANTU_DEBUG_IN(); /// reset normalized maximum equivalent stress if (ghost_type == _not_ghost) this->norm_max_equivalent_stress = 0; MaterialDamageIterativeNonLocalParent::computeNonLocalStresses(ghost_type); /// find global Gauss point with highest stress const auto & comm = this->model.getMesh().getCommunicator(); comm.allReduce(this->norm_max_equivalent_stress, SynchronizerOperation::_max); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ INSTANTIATE_MATERIAL(damage_iterative_non_local, MaterialDamageIterativeNonLocal); } // namespace akantu diff --git a/extra_packages/extra-materials/src/material_damage/material_damage_iterative_non_local.hh b/extra_packages/extra-materials/src/material_damage/material_damage_iterative_non_local.hh index 9b0768a80..bf265c7c3 100644 --- a/extra_packages/extra-materials/src/material_damage/material_damage_iterative_non_local.hh +++ b/extra_packages/extra-materials/src/material_damage/material_damage_iterative_non_local.hh @@ -1,86 +1,86 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material_damage_iterative.hh" #include "material_damage_non_local.hh" /* -------------------------------------------------------------------------- */ #ifndef AKANTU_MATERIAL_DAMAGE_ITERATIVE_NON_LOCAL_HH_ #define AKANTU_MATERIAL_DAMAGE_ITERATIVE_NON_LOCAL_HH_ namespace akantu { /** * Material Damage Iterative Non local * * parameters in the material files : */ template class MaterialDamageIterativeNonLocal : public MaterialDamageNonLocal< spatial_dimension, MaterialDamageIterative> { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: typedef MaterialDamageNonLocal> MaterialDamageIterativeNonLocalParent; MaterialDamageIterativeNonLocal(SolidMechanicsModel & model, const ID & id = ""); virtual ~MaterialDamageIterativeNonLocal(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void initMaterial(); virtual void computeNonLocalStresses(GhostType ghost_type); protected: void computeStress(ElementType type, GhostType ghost_type); void computeNonLocalStress(ElementType type, GhostType ghost_type = _not_ghost); private: /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: InternalField grad_u_nl; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_damage_iterative_non_local_inline_impl.hh" } // namespace akantu #endif /* AKANTU_MATERIAL_DAMAGE_ITERATIVE_NON_LOCAL_HH_ */ diff --git a/extra_packages/extra-materials/src/material_damage/material_damage_iterative_non_local_inline_impl.hh b/extra_packages/extra-materials/src/material_damage/material_damage_iterative_non_local_inline_impl.hh index e921a79ca..fbecd0c1c 100644 --- a/extra_packages/extra-materials/src/material_damage/material_damage_iterative_non_local_inline_impl.hh +++ b/extra_packages/extra-materials/src/material_damage/material_damage_iterative_non_local_inline_impl.hh @@ -1,94 +1,94 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ } // namespace akantu #if defined(AKANTU_DEBUG_TOOLS) #include "aka_debug_tools.hh" #include #endif namespace akantu { /* -------------------------------------------------------------------------- */ template MaterialDamageIterativeNonLocal:: MaterialDamageIterativeNonLocal(SolidMechanicsModel & model, const ID & id) : MaterialDamageIterativeNonLocalParent(model, id), grad_u_nl("grad_u non local", *this) { AKANTU_DEBUG_IN(); this->is_non_local = true; this->grad_u_nl.initialize(spatial_dimension * spatial_dimension); this->model.getNonLocalManager().registerNonLocalVariable( this->gradu.getName(), grad_u_nl.getName(), spatial_dimension * spatial_dimension); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialDamageIterativeNonLocal::initMaterial() { AKANTU_DEBUG_IN(); MaterialDamageIterativeNonLocalParent::initMaterial(); this->model.getNonLocalManager().nonLocalVariableToNeighborhood( grad_u_nl.getName(), this->name); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialDamageIterativeNonLocal::computeStress( ElementType /*type*/, GhostType /*ghost_type*/) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialDamageIterativeNonLocal::computeNonLocalStress( ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); /// compute the stress (based on the elastic law) MaterialDamage::computeStress(el_type, ghost_type); /// multiply the stress by (1-d) to get the effective stress Real * dam = this->damage(el_type, ghost_type).data(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); this->computeDamageAndStressOnQuad(sigma, *dam); ++dam; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; /// compute the normalized equivalent stress this->computeNormalizedEquivalentStress(this->grad_u_nl(el_type, ghost_type), el_type, ghost_type); /// find the maximum this->norm_max_equivalent_stress = 0; this->findMaxNormalizedEquivalentStress(el_type, ghost_type); AKANTU_DEBUG_OUT(); } diff --git a/extra_packages/extra-materials/src/material_damage/material_damage_linear.cc b/extra_packages/extra-materials/src/material_damage/material_damage_linear.cc index 365cf6ec6..a9371e037 100644 --- a/extra_packages/extra-materials/src/material_damage/material_damage_linear.cc +++ b/extra_packages/extra-materials/src/material_damage/material_damage_linear.cc @@ -1,79 +1,79 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "material_damage_linear.hh" #include "solid_mechanics_model.hh" namespace akantu { /* -------------------------------------------------------------------------- */ template MaterialDamageLinear::MaterialDamageLinear( SolidMechanicsModel & model, const ID & id) : MaterialDamage(model, id), K("K", *this) { AKANTU_DEBUG_IN(); this->registerParam("Sigc", Sigc, 1e5, _pat_parsable, "Sigma Critique"); this->registerParam("Gc", Gc, 2., _pat_parsable, "Gc"); this->K.initialize(1); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialDamageLinear::initMaterial() { AKANTU_DEBUG_IN(); MaterialDamage::initMaterial(); Epsmin = Sigc / this->E; Epsmax = 2 * Gc / Sigc + Epsmin; this->K.setDefaultValue(Epsmin); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialDamageLinear::computeStress( ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Real * dam = this->damage(el_type, ghost_type).data(); Real * K = this->K(el_type, ghost_type).data(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); this->computeStressOnQuad(grad_u, sigma, *dam, *K); ++dam; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ INSTANTIATE_MATERIAL(damage_linear, MaterialDamageLinear); } // namespace akantu diff --git a/extra_packages/extra-materials/src/material_damage/material_damage_linear.hh b/extra_packages/extra-materials/src/material_damage/material_damage_linear.hh index 21bffe322..0e8af9c57 100644 --- a/extra_packages/extra-materials/src/material_damage/material_damage_linear.hh +++ b/extra_packages/extra-materials/src/material_damage/material_damage_linear.hh @@ -1,90 +1,90 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material_damage.hh" /* -------------------------------------------------------------------------- */ #ifndef AKANTU_MATERIAL_DAMAGE_LINEAR_HH_ #define AKANTU_MATERIAL_DAMAGE_LINEAR_HH_ namespace akantu { /** * Material liner damage * * parameters in the material files : * - Sigc : (default: 1e5) * - Gc : (default: 2) */ template class MaterialDamageLinear : public MaterialDamage { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialDamageLinear(SolidMechanicsModel & model, const ID & id = ""); virtual ~MaterialDamageLinear(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void initMaterial(); /// constitutive law for all element of a type void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost); protected: /// constitutive law for a given quadrature point inline void computeStressOnQuad(Matrix & F, Matrix & sigma, Real & damage, Real & K); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// kind of toughness Real Gc; /// critical stress Real Sigc; /// damage internal variable InternalField K; Real Epsmin, Epsmax; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_damage_linear_inline_impl.hh" } // namespace akantu #endif /* AKANTU_MATERIAL_DAMAGE_LINEAR_HH_ */ diff --git a/extra_packages/extra-materials/src/material_damage/material_damage_linear_inline_impl.hh b/extra_packages/extra-materials/src/material_damage/material_damage_linear_inline_impl.hh index 721820ed2..a1fac1e95 100644 --- a/extra_packages/extra-materials/src/material_damage/material_damage_linear_inline_impl.hh +++ b/extra_packages/extra-materials/src/material_damage/material_damage_linear_inline_impl.hh @@ -1,48 +1,48 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ template inline void MaterialDamageLinear::computeStressOnQuad( Matrix & grad_u, Matrix & sigma, Real & dam, Real & K) { Real Fdiag[3]; Real Fdiagp[3]; Math::matrix33_eigenvalues(grad_u.data(), Fdiag); Fdiagp[0] = std::max(0., Fdiag[0]); Fdiagp[1] = std::max(0., Fdiag[1]); Fdiagp[2] = std::max(0., Fdiag[2]); Real Ehat = sqrt(Fdiagp[0] * Fdiagp[0] + Fdiagp[1] * Fdiagp[1] + Fdiagp[2] * Fdiagp[2]); MaterialElastic::computeStressOnQuad(grad_u, sigma); Real Fd = Ehat - K; if (Fd > 0) { dam = (Ehat - Epsmin) / (Epsmax - Epsmin) * (Ehat / Epsmax); dam = std::min(dam, 1.); K = Ehat; } sigma *= 1 - dam; } diff --git a/extra_packages/extra-materials/src/material_damage/material_iterative_stiffness_reduction.cc b/extra_packages/extra-materials/src/material_damage/material_iterative_stiffness_reduction.cc index edda7ddbb..23401f50f 100644 --- a/extra_packages/extra-materials/src/material_damage/material_iterative_stiffness_reduction.cc +++ b/extra_packages/extra-materials/src/material_damage/material_iterative_stiffness_reduction.cc @@ -1,197 +1,197 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "material_iterative_stiffness_reduction.hh" #include "communicator.hh" #include "solid_mechanics_model_RVE.hh" /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ template MaterialIterativeStiffnessReduction:: MaterialIterativeStiffnessReduction(SolidMechanicsModel & model, const ID & id) : MaterialDamageIterative(model, id), eps_u("ultimate_strain", *this), D("tangent", *this), Gf(0.), crack_band_width(0.), reduction_constant(0.) { AKANTU_DEBUG_IN(); this->registerParam("Gf", Gf, _pat_parsable | _pat_modifiable, "fracture energy"); this->registerParam("crack_band_width", crack_band_width, _pat_parsable | _pat_modifiable, "crack_band_width"); this->registerParam("reduction_constant", reduction_constant, 2., _pat_parsable | _pat_modifiable, "reduction constant"); this->eps_u.initialize(1); this->D.initialize(1); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialIterativeStiffnessReduction::initMaterial() { AKANTU_DEBUG_IN(); MaterialDamageIterative::initMaterial(); for (auto ghost_type : ghost_types) { /// loop over all types in the filter for (auto & el_type : this->element_filter.elementTypes(_ghost_type = ghost_type)) { /// get the stiffness on each quad point auto Sc_it = this->Sc(el_type, ghost_type).begin(); /// get the tangent of the tensile softening on each quad point auto D_it = this->D(el_type, ghost_type).begin(); auto D_end = this->D(el_type, ghost_type).end(); /// get the ultimate strain on each quad auto eps_u_it = this->eps_u(el_type, ghost_type).begin(); // compute the tangent and the ultimate strain for each quad for (; D_it != D_end; ++Sc_it, ++D_it, ++eps_u_it) { *eps_u_it = ((2. * this->Gf) / (*Sc_it * this->crack_band_width)); *D_it = *(Sc_it) / ((*eps_u_it) - ((*Sc_it) / this->E)); } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialIterativeStiffnessReduction:: computeNormalizedEquivalentStress(const Array & grad_u, ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); /// storage for the current stress Matrix sigma(spatial_dimension, spatial_dimension); /// Vector to store eigenvalues of current stress tensor Vector eigenvalues(spatial_dimension); /// iterators on the needed internal fields auto Sc_it = this->Sc(el_type, ghost_type).begin(); auto dam_it = this->damage(el_type, ghost_type).begin(); auto equivalent_stress_it = this->equivalent_stress(el_type, ghost_type).begin(); auto grad_u_it = grad_u.begin(spatial_dimension, spatial_dimension); auto grad_u_end = grad_u.end(spatial_dimension, spatial_dimension); /// loop over all the quadrature points and compute the equivalent stress for (; grad_u_it != grad_u_end; ++grad_u_it) { /// compute the stress sigma.zero(); MaterialElastic::computeStressOnQuad(*grad_u_it, sigma, 0.); MaterialDamageIterative::computeDamageAndStressOnQuad( sigma, *dam_it); /// compute eigenvalues sigma.eig(eigenvalues); /// find max eigenvalue and normalize by tensile strength *equivalent_stress_it = *(std::max_element(eigenvalues.data(), eigenvalues.data() + spatial_dimension)) / (*Sc_it); ++Sc_it; ++equivalent_stress_it; ++dam_it; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template UInt MaterialIterativeStiffnessReduction::updateDamage() { UInt nb_damaged_elements = 0; if (this->norm_max_equivalent_stress >= 1.) { AKANTU_DEBUG_IN(); /// update the damage only on non-ghosts elements! Doesn't make sense to /// update on ghost. GhostType ghost_type = _not_ghost; /// loop over all the elements for (auto && el_type : this->model.getFEEngine().getMesh().elementTypes( spatial_dimension, ghost_type)) { /// get iterators on the needed internal fields auto equivalent_stress_it = this->equivalent_stress(el_type, ghost_type).begin(); auto equivalent_stress_end = this->equivalent_stress(el_type, ghost_type).end(); auto dam_it = this->damage(el_type, ghost_type).begin(); auto reduction_it = this->reduction_step(el_type, ghost_type).begin(); auto eps_u_it = this->eps_u(el_type, ghost_type).begin(); auto Sc_it = this->Sc(el_type, ghost_type).begin(); auto D_it = this->D(el_type, ghost_type).begin(); /// loop over all the quads of the given element type for (; equivalent_stress_it != equivalent_stress_end; ++equivalent_stress_it, ++dam_it, ++reduction_it, ++eps_u_it, ++Sc_it, ++D_it) { /// check if damage occurs if (*equivalent_stress_it >= (1 - this->dam_tolerance) * this->norm_max_equivalent_stress) { /// check if this element can still be damaged if (*reduction_it == this->max_reductions) continue; /// increment the counter of stiffness reduction steps *reduction_it += 1; if (*reduction_it == this->max_reductions) *dam_it = this->max_damage; else { /// update the damage on this quad *dam_it = 1. - (1. / std::pow(this->reduction_constant, *reduction_it)); /// update the stiffness on this quad *Sc_it = (*eps_u_it) * (1. - (*dam_it)) * this->E * (*D_it) / ((1. - (*dam_it)) * this->E + (*D_it)); } nb_damaged_elements += 1; } } } } auto rve_model = dynamic_cast(&this->model); if (rve_model == NULL) { const auto & comm = this->model.getMesh().getCommunicator(); comm.allReduce(nb_damaged_elements, SynchronizerOperation::_sum); } AKANTU_DEBUG_OUT(); return nb_damaged_elements; } /* -------------------------------------------------------------------------- */ INSTANTIATE_MATERIAL(iterative_stiffness_reduction, MaterialIterativeStiffnessReduction); } // namespace akantu diff --git a/extra_packages/extra-materials/src/material_damage/material_iterative_stiffness_reduction.hh b/extra_packages/extra-materials/src/material_damage/material_iterative_stiffness_reduction.hh index 5447f2d5e..426476121 100644 --- a/extra_packages/extra-materials/src/material_damage/material_iterative_stiffness_reduction.hh +++ b/extra_packages/extra-materials/src/material_damage/material_iterative_stiffness_reduction.hh @@ -1,98 +1,98 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "material_damage_iterative.hh" /* -------------------------------------------------------------------------- */ #ifndef AKANTU_MATERIAL_ITERATIVE_STIFFNESS_REDUCTION_HH_ #define AKANTU_MATERIAL_ITERATIVE_STIFFNESS_REDUCTION_HH_ namespace akantu { /** * Material damage iterative * * parameters in the material files : * - Gfx * - h * - Sc */ /// Proposed by Rots and Invernizzi, 2004: Regularized sequentially linear // saw-tooth softening model (section 4.2) template class MaterialIterativeStiffnessReduction : public MaterialDamageIterative { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialIterativeStiffnessReduction(SolidMechanicsModel & model, const ID & id = ""); virtual ~MaterialIterativeStiffnessReduction(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// init the material virtual void initMaterial(); /// compute the equivalent stress on each Gauss point (i.e. the max prinicpal /// stress) and normalize it by the tensile stiffness virtual void computeNormalizedEquivalentStress(const Array & grad_u, ElementType el_type, GhostType ghost_type = _not_ghost); /// update internal field damage virtual UInt updateDamage(); /* ------------------------------------------------------------------------ */ /* DataAccessor inherited members */ /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// the ultimate strain InternalField eps_u; /// the tangent of the tensile stress-strain softening InternalField D; /// fracture energy Real Gf; /// crack_band_width for normalization of fracture energy Real crack_band_width; /// the reduction constant (denoated by a in the paper of rots) Real reduction_constant; }; } // namespace akantu #endif /* AKANTU_MATERIAL_ITERATIVE_STIFFNESS_REDUCTION_HH_ */ diff --git a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage.hh b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage.hh index fe1848739..5c36d03d2 100644 --- a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage.hh +++ b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage.hh @@ -1,138 +1,138 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material_elastic.hh" /* -------------------------------------------------------------------------- */ #ifndef AKANTU_MATERIAL_ORTHOTROPIC_DAMAGE_HH_ #define AKANTU_MATERIAL_ORTHOTROPIC_DAMAGE_HH_ namespace akantu { template class Parent = MaterialElastic> class MaterialOrthotropicDamage : public Parent { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialOrthotropicDamage(SolidMechanicsModel & model, const ID & id = ""); virtual ~MaterialOrthotropicDamage(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void initMaterial() override; /// compute the tangent stiffness matrix for an element type void computeTangentModuli(ElementType el_type, Array & tangent_matrix, GhostType ghost_type = _not_ghost) override; protected: /// update the dissipated energy, must be called after the stress have been /// computed void updateEnergies(ElementType el_type) override; /// compute the tangent stiffness matrix for a given quadrature point inline void computeTangentModuliOnQuad( Matrix & tangent, const Matrix C, const Matrix & dam, const Matrix & dam_directions, Matrix & O_prime, Matrix & S_prime, Matrix & O, Matrix & S, Matrix & rotation_tmp); inline void computeDamageAndStressOnQuad(Matrix & sigma, Matrix & one_minus_D, Matrix & root_one_minus_D, Matrix & damage, Matrix & first_term, Matrix & third_term); /// rotate a Matrix of size dim*dim into the coordinate system of the FE /// computation inline void rotateIntoComputationFrame(const Matrix & to_rotate, Matrix & rotated, const Matrix & damage_directions, Matrix & rotation_tmp); /// rotate a Matrix of size dim*dim into the coordinate system of the damage inline void rotateIntoNewFrame(const Matrix & to_rotate, Matrix & rotated, const Matrix & damage_directions, Matrix & rotation_tmp); /// compute (1-D) inline void computeOneMinusD(Matrix & one_minus_D, const Matrix & damage); /// compute (1-D)^(1/2) inline void computeSqrtOneMinusD(const Matrix & one_minus_D, Matrix & sqrt_one_minus_D); /* ------------------------------------------------------------------------ */ /* DataAccessor inherited members */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// give the dissipated energy for the time step Real getDissipatedEnergy() const; // virtual Real getEnergy(std::string type); // virtual Real getEnergy(std::string energy_id, ElementType type, UInt index) // { // return Parent::getEnergy(energy_id, type, index); // }; AKANTU_GET_MACRO_NOT_CONST(Damage, damage, ElementTypeMapArray &); AKANTU_GET_MACRO(Damage, damage, const ElementTypeMapArray &); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Damage, damage, Real) /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// damage internal variable InternalField damage; /// dissipated energy InternalField dissipated_energy; /// contain the current value of @f$ \int_0^{\epsilon}\sigma(\omega)d\omega /// @f$ the dissipated energy InternalField int_sigma; /// direction vectors for the damage frame InternalField damage_dir_vecs; Real eta; /// maximum damage value Real max_damage; }; } // namespace akantu #include "material_orthotropic_damage_tmpl.hh" #endif /* AKANTU_MATERIAL_ORTHOTROPIC_DAMAGE_HH_ */ diff --git a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative.cc b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative.cc index c718394c3..660f155cb 100644 --- a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative.cc +++ b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative.cc @@ -1,378 +1,378 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "material_orthotropic_damage_iterative.hh" #include "communicator.hh" #include "solid_mechanics_model.hh" /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ template MaterialOrthotropicDamageIterative:: MaterialOrthotropicDamageIterative(SolidMechanicsModel & model, const ID & id) : MaterialOrthotropicDamage(model, id), Sc("Sc", *this), equivalent_stress("equivalent_stress", *this), stress_dir("equiv_stress_dir", *this), norm_max_equivalent_stress(0) { AKANTU_DEBUG_IN(); this->registerParam("Sc", Sc, _pat_parsable, "critical stress threshold"); this->registerParam("prescribed_dam", prescribed_dam, 0.1, _pat_parsable | _pat_modifiable, "increase of damage in every step"); this->registerParam( "dam_threshold", dam_threshold, 0.8, _pat_parsable | _pat_modifiable, "damage threshold at which damage damage will be set to 1"); this->use_previous_stress = true; this->use_previous_gradu = true; this->Sc.initialize(1); this->equivalent_stress.initialize(1); this->stress_dir.initialize(spatial_dimension * spatial_dimension); /// the Gauss point with the highest stress can only be of type _not_ghost q_max.ghost_type = _not_ghost; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialOrthotropicDamageIterative:: computeNormalizedEquivalentStress(const Array & grad_u, ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); /// Vector to store eigenvalues of current stress tensor Vector eigenvalues(spatial_dimension); auto Sc_it = Sc(el_type).begin(); auto equivalent_stress_it = equivalent_stress(el_type).begin(); Array::const_matrix_iterator grad_u_it = grad_u.begin(spatial_dimension, spatial_dimension); Array::const_matrix_iterator grad_u_end = grad_u.end(spatial_dimension, spatial_dimension); Array::matrix_iterator stress_dir_it = this->stress_dir(el_type).begin(spatial_dimension, spatial_dimension); /// initialize matrix to store the stress for the criterion (only different in /// non-local) Matrix sigma(spatial_dimension, spatial_dimension); Array::matrix_iterator damage_iterator = this->damage(el_type, ghost_type) .begin(this->spatial_dimension, this->spatial_dimension); Array::matrix_iterator damage_dir_it = this->damage_dir_vecs(el_type, ghost_type) .begin(this->spatial_dimension, this->spatial_dimension); /// for the computation of the Cauchy stress the matrices (1-D) and /// (1-D)^(1/2) are needed. For the formulation see Engineering /// Damage Mechanics by Lemaitre and Desmorat. Matrix one_minus_D(this->spatial_dimension, this->spatial_dimension); Matrix sqrt_one_minus_D(this->spatial_dimension, this->spatial_dimension); Matrix one_minus_D_rotated(this->spatial_dimension, this->spatial_dimension); Matrix sqrt_one_minus_D_rotated(this->spatial_dimension, this->spatial_dimension); Matrix rotation_tmp(this->spatial_dimension, this->spatial_dimension); /// create matrix to store the first term of the computation of the /// Cauchy stress Matrix first_term(this->spatial_dimension, this->spatial_dimension); Matrix third_term(this->spatial_dimension, this->spatial_dimension); for (; grad_u_it != grad_u_end; ++Sc_it, ++equivalent_stress_it, ++stress_dir_it, ++grad_u_it) { sigma.zero(); MaterialOrthotropicDamage::computeStressOnQuad( *grad_u_it, sigma, 0.); /// rotate the tensors from the damage principal coordinate system to the CS /// of the computation if (!(Math::are_float_equal((*damage_iterator).trace(), 0))) { /// compute (1-D) and (1-D)^1/2 this->computeOneMinusD(one_minus_D, *damage_iterator); this->computeSqrtOneMinusD(one_minus_D, sqrt_one_minus_D); this->rotateIntoComputationFrame(one_minus_D, one_minus_D_rotated, *damage_dir_it, rotation_tmp); this->rotateIntoComputationFrame(sqrt_one_minus_D, sqrt_one_minus_D_rotated, *damage_dir_it, rotation_tmp); } else { this->computeOneMinusD(one_minus_D_rotated, *damage_iterator); this->computeSqrtOneMinusD(one_minus_D_rotated, sqrt_one_minus_D_rotated); } computeDamageAndStressOnQuad(sigma, one_minus_D_rotated, sqrt_one_minus_D_rotated, *damage_iterator, first_term, third_term); /// compute the maximum principal stresses and their directions sigma.eig(eigenvalues, *stress_dir_it); *equivalent_stress_it = eigenvalues(0) / *(Sc_it); ++damage_dir_it; ++damage_iterator; } // for(;sigma_it != sigma_end; ++sigma_it, // ++Sc_it, ++equivalent_stress_it, ++stress_dir_it) { // /// compute the maximum principal stresses and their directions // (*sigma_it).eig(eigenvalues, *stress_dir_it); // *equivalent_stress_it = eigenvalues(0) / *(Sc_it); // } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialOrthotropicDamageIterative::computeAllStresses( GhostType ghost_type) { AKANTU_DEBUG_IN(); /// reset normalized maximum equivalent stress if (ghost_type == _not_ghost) norm_max_equivalent_stress = 0; MaterialOrthotropicDamage::computeAllStresses(ghost_type); /// find global Gauss point with highest stress this->model.getMesh().getCommunicator().allReduce( norm_max_equivalent_stress, SynchronizerOperation::_max); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialOrthotropicDamageIterative:: findMaxNormalizedEquivalentStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); if (ghost_type == _not_ghost) { /// initialize the iterators for the equivalent stress and the damage const Array & e_stress = equivalent_stress(el_type); auto equivalent_stress_it = e_stress.begin(); auto equivalent_stress_end = e_stress.end(); Array & dam = this->damage(el_type); auto dam_it = dam.begin(this->spatial_dimension, this->spatial_dimension); auto damage_directions_it = this->damage_dir_vecs(el_type, _not_ghost) .begin(this->spatial_dimension, this->spatial_dimension); auto stress_dir_it = this->stress_dir(el_type, _not_ghost) .begin(spatial_dimension, spatial_dimension); /// initialize the matrices for damage rotation results Matrix tmp(spatial_dimension, spatial_dimension); Matrix dam_in_computation_frame(spatial_dimension, spatial_dimension); Matrix dam_in_stress_frame(spatial_dimension, spatial_dimension); for (; equivalent_stress_it != equivalent_stress_end; ++equivalent_stress_it, ++dam_it, ++damage_directions_it, ++stress_dir_it) { /// check if max equivalent stress for this element type is greater than /// the current norm_max_eq_stress if (*equivalent_stress_it > norm_max_equivalent_stress && (spatial_dimension * this->max_damage - (*dam_it).trace() > Math::getTolerance())) { if (Math::are_float_equal((*dam_it).trace(), 0)) { /// gauss point has not been damaged yet norm_max_equivalent_stress = *equivalent_stress_it; q_max.type = el_type; q_max.global_num = equivalent_stress_it - e_stress.begin(); } else { /// find the damage increment on this Gauss point /// rotate damage into stress frame this->rotateIntoComputationFrame(*dam_it, dam_in_computation_frame, *damage_directions_it, tmp); this->rotateIntoNewFrame(dam_in_computation_frame, dam_in_stress_frame, *stress_dir_it, tmp); /// add damage increment dam_in_stress_frame(0, 0) += prescribed_dam; /// find new principal directions of damage Vector dam_eigenvalues(spatial_dimension); dam_in_stress_frame.eig(dam_eigenvalues); bool limit_reached = false; for (Int i = 0; i < spatial_dimension; ++i) { if (dam_eigenvalues(i) + Math::getTolerance() > this->max_damage) limit_reached = true; } if (!limit_reached) { norm_max_equivalent_stress = *equivalent_stress_it; q_max.type = el_type; q_max.global_num = equivalent_stress_it - e_stress.begin(); } } } /// end if equiv_stress > max_equiv_stress } /// end loop over all gauss points of this element type } // end if(_not_ghost) AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialOrthotropicDamageIterative::computeStress( ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); MaterialOrthotropicDamage::computeStress(el_type, ghost_type); auto damage_iterator = this->damage(el_type, ghost_type) .begin(this->spatial_dimension, this->spatial_dimension); auto damage_dir_it = this->damage_dir_vecs(el_type, ghost_type) .begin(this->spatial_dimension, this->spatial_dimension); /// for the computation of the Cauchy stress the matrices (1-D) and /// (1-D)^(1/2) are needed. For the formulation see Engineering /// Damage Mechanics by Lemaitre and Desmorat. Matrix one_minus_D(this->spatial_dimension, this->spatial_dimension); Matrix sqrt_one_minus_D(this->spatial_dimension, this->spatial_dimension); Matrix one_minus_D_rotated(this->spatial_dimension, this->spatial_dimension); Matrix sqrt_one_minus_D_rotated(this->spatial_dimension, this->spatial_dimension); Matrix rotation_tmp(this->spatial_dimension, this->spatial_dimension); /// create matrix to store the first term of the computation of the /// Cauchy stress Matrix first_term(this->spatial_dimension, this->spatial_dimension); Matrix third_term(this->spatial_dimension, this->spatial_dimension); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); /// rotate the tensors from the damage principal coordinate system to the CS /// of the computation if (!(Math::are_float_equal((*damage_iterator).trace(), 0))) { /// compute (1-D) and (1-D)^1/2 this->computeOneMinusD(one_minus_D, *damage_iterator); this->computeSqrtOneMinusD(one_minus_D, sqrt_one_minus_D); this->rotateIntoComputationFrame(one_minus_D, one_minus_D_rotated, *damage_dir_it, rotation_tmp); this->rotateIntoComputationFrame(sqrt_one_minus_D, sqrt_one_minus_D_rotated, *damage_dir_it, rotation_tmp); } else { this->computeOneMinusD(one_minus_D_rotated, *damage_iterator); this->computeSqrtOneMinusD(one_minus_D_rotated, sqrt_one_minus_D_rotated); } computeDamageAndStressOnQuad(sigma, one_minus_D_rotated, sqrt_one_minus_D_rotated, *damage_iterator, first_term, third_term); ++damage_dir_it; ++damage_iterator; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; computeNormalizedEquivalentStress(this->gradu(el_type, ghost_type), el_type, ghost_type); norm_max_equivalent_stress = 0; findMaxNormalizedEquivalentStress(el_type, ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template UInt MaterialOrthotropicDamageIterative::updateDamage() { UInt nb_damaged_elements = 0; AKANTU_DEBUG_ASSERT(prescribed_dam > 0., "Your prescribed damage must be greater than zero"); if (norm_max_equivalent_stress >= 1.) { AKANTU_DEBUG_IN(); /// get the arrays and iterators for the element_type of the highest /// quadrature point ElementType el_type = q_max.type; UInt q_global_num = q_max.global_num; Array & dam = this->damage(el_type, _not_ghost); auto dam_it = dam.begin(this->spatial_dimension, this->spatial_dimension); auto damage_directions_it = this->damage_dir_vecs(el_type, _not_ghost) .begin(this->spatial_dimension, this->spatial_dimension); auto stress_dir_it = this->stress_dir(el_type, _not_ghost) .begin(spatial_dimension, spatial_dimension); /// initialize the matrices for damage rotation results Matrix tmp(spatial_dimension, spatial_dimension); Matrix dam_in_computation_frame(spatial_dimension, spatial_dimension); Matrix dam_in_stress_frame(spatial_dimension, spatial_dimension); /// references to damage and directions of highest Gauss point Matrix q_dam = dam_it[q_global_num]; Matrix q_dam_dir = damage_directions_it[q_global_num]; Matrix q_stress_dir = stress_dir_it[q_global_num]; /// increment damage /// find the damage increment on this Gauss point /// rotate damage into stress frame this->rotateIntoComputationFrame(q_dam, dam_in_computation_frame, q_dam_dir, tmp); this->rotateIntoNewFrame(dam_in_computation_frame, dam_in_stress_frame, q_stress_dir, tmp); /// add damage increment dam_in_stress_frame(0, 0) += prescribed_dam; /// find new principal directions of damage Vector dam_eigenvalues(spatial_dimension); dam_in_stress_frame.eig(dam_eigenvalues, q_dam_dir); for (Int i = 0; i < spatial_dimension; ++i) { q_dam(i, i) = dam_eigenvalues(i); if (q_dam(i, i) + Math::getTolerance() >= dam_threshold) q_dam(i, i) = this->max_damage; } nb_damaged_elements += 1; } this->model.getMesh().getCommunicator().allReduce( nb_damaged_elements, SynchronizerOperation::_sum); AKANTU_DEBUG_OUT(); return nb_damaged_elements; } /* -------------------------------------------------------------------------- */ template void MaterialOrthotropicDamageIterative< spatial_dimension>::updateEnergiesAfterDamage(ElementType el_type) { MaterialOrthotropicDamage::updateEnergies(el_type); } /* -------------------------------------------------------------------------- */ INSTANTIATE_MATERIAL(orthotropic_damage_iterative, MaterialOrthotropicDamageIterative); } // namespace akantu diff --git a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative.hh b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative.hh index f3aad2e06..aa2e6a44d 100644 --- a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative.hh +++ b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative.hh @@ -1,129 +1,129 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material.hh" #include "material_orthotropic_damage.hh" /* -------------------------------------------------------------------------- */ #ifndef AKANTU_MATERIAL_ORTHOTROPIC_DAMAGE_ITERATIVE_HH_ #define AKANTU_MATERIAL_ORTHOTROPIC_DAMAGE_ITERATIVE_HH_ namespace akantu { /** * Material damage iterative * * parameters in the material files : * - Sc */ template class MaterialOrthotropicDamageIterative : public MaterialOrthotropicDamage { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialOrthotropicDamageIterative(SolidMechanicsModel & model, const ID & id = ""); virtual ~MaterialOrthotropicDamageIterative(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// virtual void updateInternalParameters(); virtual void computeAllStresses(GhostType ghost_type = _not_ghost); /// update internal field damage UInt updateDamage(); /// update energies after damage has been updated virtual void updateEnergiesAfterDamage(ElementType el_type); protected: /// constitutive law for all element of a type virtual void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost); /// compute the equivalent stress on each Gauss point (i.e. the max prinicpal /// stress) and normalize it by the tensile strength void computeNormalizedEquivalentStress(const Array & grad_u, ElementType el_type, GhostType ghost_type = _not_ghost); /// find max normalized equivalent stress void findMaxNormalizedEquivalentStress(ElementType el_type, GhostType ghost_type = _not_ghost); inline void computeDamageAndStressOnQuad(Matrix & sigma, Matrix & one_minus_D, Matrix & root_one_minus_D, Matrix & damage, Matrix & first_term, Matrix & third_term); /* ------------------------------------------------------------------------ */ /* DataAccessor inherited members */ /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get max normalized equivalent stress AKANTU_GET_MACRO(NormMaxEquivalentStress, norm_max_equivalent_stress, Real); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// resistance to damage RandomInternalField Sc; /// internal field to store equivalent stress on each Gauss point InternalField equivalent_stress; /// internal field to store the direction of the current damage frame InternalField stress_dir; /// damage increment Real prescribed_dam; /// maximum equivalent stress Real norm_max_equivalent_stress; /// define damage threshold at which damage will be set to 1 Real dam_threshold; /// quadrature point with highest equivalent Stress IntegrationPoint q_max; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_orthotropic_damage_iterative_inline_impl.hh" } // namespace akantu #endif /* AKANTU_MATERIAL_ORTHOTROPIC_DAMAGE_ITERATIVE_HH_ */ diff --git a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative_inline_impl.hh b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative_inline_impl.hh index bc2e35cd0..01a20c5f4 100644 --- a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative_inline_impl.hh +++ b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative_inline_impl.hh @@ -1,75 +1,75 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ template inline void MaterialOrthotropicDamageIterative:: computeDamageAndStressOnQuad(Matrix & sigma, Matrix & one_minus_D, Matrix & sqrt_one_minus_D, Matrix & damage, Matrix & first_term, Matrix & third_term) { // Real dmax = *(std::max_element(damage.data(), damage.data() + // spatial_dimension*spatial_dimension) ); Real eta_effective = 0; // if ( (1 - dmax*dmax) < (1 - this->eta / spatial_dimension * // damage.trace()) ) { // eta_effective = this->spatial_dimension * dmax * dmax / damage.trace(); // } // else eta_effective = this->eta; /// hydrostatic sensitivity parameter // Real eta = 3.; /// Definition of Cauchy stress based on second order damage tensor: /// "Anisotropic damage modelling of biaxial behaviour and rupture /// of concrete strucutres", Ragueneau et al., 2008, Eq. 7 first_term.mul(sqrt_one_minus_D, sigma); first_term *= sqrt_one_minus_D; Real second_term = 0; for (Int i = 0; i < this->spatial_dimension; ++i) { for (Int j = 0; j < this->spatial_dimension; ++j) second_term += sigma(i, j) * one_minus_D(i, j); } second_term /= (this->spatial_dimension - damage.trace()); // for (Int i = 0; i < this->spatial_dimension; ++i) { // for (Int j = 0; j < this->spatial_dimension; ++j) // one_minus_D(i,j) *= second_term; // } one_minus_D *= second_term; third_term.eye( 1. / this->spatial_dimension * sigma.trace() * (1 - std::min(eta_effective / (this->spatial_dimension) * damage.trace(), this->max_damage))); sigma.copy(first_term); sigma -= one_minus_D; sigma += third_term; } diff --git a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative_non_local.hh b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative_non_local.hh index 4d3f92629..51ee0bdbf 100644 --- a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative_non_local.hh +++ b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative_non_local.hh @@ -1,89 +1,89 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material_damage_non_local.hh" #include "material_orthotropic_damage_iterative.hh" /* -------------------------------------------------------------------------- */ #ifndef AKANTU_MATERIAL_ORTHOTROPIC_DAMAGE_ITERATIVE_NON_LOCAL_HH_ #define AKANTU_MATERIAL_ORTHOTROPIC_DAMAGE_ITERATIVE_NON_LOCAL_HH_ namespace akantu { /** * Material Damage Iterative Non local * * parameters in the material files : */ template class MaterialOrthotropicDamageIterativeNonLocal : public MaterialDamageNonLocal< spatial_dimension, MaterialOrthotropicDamageIterative> { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: typedef MaterialDamageNonLocal< spatial_dimension, MaterialOrthotropicDamageIterative> MaterialOrthotropicDamageIterativeNonLocalParent; MaterialOrthotropicDamageIterativeNonLocal(SolidMechanicsModel & model, const ID & id = ""); virtual ~MaterialOrthotropicDamageIterativeNonLocal(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void initMaterial(); protected: void computeStress(ElementType type, GhostType ghost_type); void computeNonLocalStress(ElementType type, GhostType ghost_type = _not_ghost); /// associate the non-local variables of the material to their neighborhoods virtual void nonLocalVariableToNeighborhood(); private: /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: InternalField grad_u_nl; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_orthotropic_damage_iterative_non_local_inline_impl.hh" } // namespace akantu #endif /* AKANTU_MATERIAL_ORTHOTROPIC_DAMAGE_ITERATIVE_NON_LOCAL_HH_ */ diff --git a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative_non_local_inline_impl.hh b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative_non_local_inline_impl.hh index a08076b1f..d4f4f4b3f 100644 --- a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative_non_local_inline_impl.hh +++ b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative_non_local_inline_impl.hh @@ -1,145 +1,145 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ } // namespace akantu #if defined(AKANTU_DEBUG_TOOLS) #include "aka_debug_tools.hh" #include #endif namespace akantu { /* -------------------------------------------------------------------------- */ template MaterialOrthotropicDamageIterativeNonLocal:: MaterialOrthotropicDamageIterativeNonLocal(SolidMechanicsModel & model, const ID & id) : Material(model, id), MaterialOrthotropicDamageIterativeNonLocalParent(model, id), grad_u_nl("grad_u non local", *this) { AKANTU_DEBUG_IN(); this->is_non_local = true; this->grad_u_nl.initialize(spatial_dimension * spatial_dimension); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialOrthotropicDamageIterativeNonLocal< spatial_dimension>::initMaterial() { AKANTU_DEBUG_IN(); this->model.getNonLocalManager().registerNonLocalVariable( this->gradu.getName(), grad_u_nl.getName(), spatial_dimension * spatial_dimension); MaterialOrthotropicDamageIterativeNonLocalParent::initMaterial(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialOrthotropicDamageIterativeNonLocal< spatial_dimension>::computeStress(ElementType type, GhostType ghost_type) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialOrthotropicDamageIterativeNonLocal< spatial_dimension>::computeNonLocalStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); MaterialOrthotropicDamage::computeStress(el_type, ghost_type); Array::matrix_iterator damage_iterator = this->damage(el_type, ghost_type) .begin(this->spatial_dimension, this->spatial_dimension); Array::matrix_iterator damage_dir_it = this->damage_dir_vecs(el_type, ghost_type) .begin(this->spatial_dimension, this->spatial_dimension); /// for the computation of the Cauchy stress the matrices (1-D) and /// (1-D)^(1/2) are needed. For the formulation see Engineering /// Damage Mechanics by Lemaitre and Desmorat. Matrix one_minus_D(this->spatial_dimension, this->spatial_dimension); Matrix sqrt_one_minus_D(this->spatial_dimension, this->spatial_dimension); Matrix one_minus_D_rotated(this->spatial_dimension, this->spatial_dimension); Matrix sqrt_one_minus_D_rotated(this->spatial_dimension, this->spatial_dimension); Matrix rotation_tmp(this->spatial_dimension, this->spatial_dimension); /// create matrix to store the first term of the computation of the /// Cauchy stress Matrix first_term(this->spatial_dimension, this->spatial_dimension); Matrix third_term(this->spatial_dimension, this->spatial_dimension); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); /// rotate the tensors from the damage principal coordinate system to the CS /// of the computation if (!(Math::are_float_equal((*damage_iterator).trace(), 0))) { /// compute (1-D) and (1-D)^1/2 this->computeOneMinusD(one_minus_D, *damage_iterator); this->computeSqrtOneMinusD(one_minus_D, sqrt_one_minus_D); this->rotateIntoComputationFrame(one_minus_D, one_minus_D_rotated, *damage_dir_it, rotation_tmp); this->rotateIntoComputationFrame(sqrt_one_minus_D, sqrt_one_minus_D_rotated, *damage_dir_it, rotation_tmp); } else { MaterialOrthotropicDamage::computeOneMinusD( one_minus_D_rotated, *damage_iterator); MaterialOrthotropicDamage::computeSqrtOneMinusD( one_minus_D_rotated, sqrt_one_minus_D_rotated); } this->computeDamageAndStressOnQuad(sigma, one_minus_D_rotated, sqrt_one_minus_D_rotated, *damage_iterator, first_term, third_term); ++damage_dir_it; ++damage_iterator; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; this->computeNormalizedEquivalentStress(this->grad_u_nl(el_type, ghost_type), el_type, ghost_type); this->norm_max_equivalent_stress = 0; this->findMaxNormalizedEquivalentStress(el_type, ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialOrthotropicDamageIterativeNonLocal< spatial_dimension>::nonLocalVariableToNeighborhood() { this->model.getNonLocalManager().nonLocalVariableToNeighborhood( grad_u_nl.getName(), this->name); } diff --git a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_non_local.hh b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_non_local.hh index 69544331a..ce2a79223 100644 --- a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_non_local.hh +++ b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_non_local.hh @@ -1,97 +1,97 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material_non_local.hh" /* -------------------------------------------------------------------------- */ #ifndef AKANTU_MATERIAL_ORTHOTROPIC_DAMAGE_NON_LOCAL_HH_ #define AKANTU_MATERIAL_ORTHOTROPIC_DAMAGE_NON_LOCAL_HH_ namespace akantu { template class MaterialOrthotropicDamageNonLocal : public MaterialOrthotropicDamageLocal, public MaterialNonLocal { public: typedef MaterialNonLocal MaterialNonLocalParent; typedef MaterialOrthotropicDamageLocal MaterialOrthotropicDamageParent; MaterialOrthotropicDamageNonLocal(SolidMechanicsModel & model, const ID & id) : Material(model, id), MaterialOrthotropicDamageParent(model, id), MaterialNonLocalParent(model, id){}; /* ------------------------------------------------------------------------ */ virtual void initMaterial() { MaterialOrthotropicDamageParent::initMaterial(); MaterialNonLocalParent::initMaterial(); } protected: /* -------------------------------------------------------------------------- */ virtual void computeNonLocalStress(ElementType type, GhostType ghost_type = _not_ghost) = 0; /* ------------------------------------------------------------------------ */ void computeNonLocalStresses(GhostType ghost_type) { AKANTU_DEBUG_IN(); Mesh::type_iterator it = this->model.getFEEngine().getMesh().firstType( spatial_dimension, ghost_type); Mesh::type_iterator last_type = this->model.getFEEngine().getMesh().lastType(spatial_dimension, ghost_type); for (; it != last_type; ++it) { computeNonLocalStress(*it, ghost_type); } AKANTU_DEBUG_OUT(); } public: /* ------------------------------------------------------------------------ */ virtual inline UInt getNbDataForElements(const Array & elements, SynchronizationTag tag) const { return MaterialNonLocalParent::getNbDataForElements(elements, tag) + MaterialOrthotropicDamageParent::getNbDataForElements(elements, tag); } virtual inline void packElementData(CommunicationBuffer & buffer, const Array & elements, SynchronizationTag tag) const { MaterialNonLocalParent::packElementData(buffer, elements, tag); MaterialOrthotropicDamageParent::packElementData(buffer, elements, tag); } virtual inline void unpackElementData(CommunicationBuffer & buffer, const Array & elements, SynchronizationTag tag) { MaterialNonLocalParent::unpackElementData(buffer, elements, tag); MaterialOrthotropicDamageParent::unpackElementData(buffer, elements, tag); } }; } // namespace akantu #endif /* AKANTU_MATERIAL_ORTHOTROPIC_DAMAGE_NON_LOCAL_HH_ */ diff --git a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_tmpl.hh b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_tmpl.hh index 2bc043e90..204c728d2 100644 --- a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_tmpl.hh +++ b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_tmpl.hh @@ -1,313 +1,313 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "material_orthotropic_damage.hh" #include "solid_mechanics_model.hh" namespace akantu { /* -------------------------------------------------------------------------- */ template class Parent> MaterialOrthotropicDamage::MaterialOrthotropicDamage( SolidMechanicsModel & model, const ID & id) : Parent(model, id), damage("damage", *this), dissipated_energy("damage dissipated energy", *this), int_sigma("integral of sigma", *this), damage_dir_vecs("damage_principal_directions", *this) { AKANTU_DEBUG_IN(); this->registerParam("eta", eta, 2., _pat_parsable | _pat_modifiable, "Damage sensitivity parameter"); this->registerParam("max_damage", max_damage, 0.99999, _pat_parsable | _pat_modifiable, "maximum damage value"); this->is_non_local = false; this->use_previous_stress = true; this->use_previous_gradu = true; /// use second order tensor for description of damage state this->damage.initialize(spatial_dimension * spatial_dimension); this->dissipated_energy.initialize(1); this->int_sigma.initialize(1); this->damage_dir_vecs.initialize(spatial_dimension * spatial_dimension); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template class Parent> void MaterialOrthotropicDamage::initMaterial() { AKANTU_DEBUG_IN(); Parent::initMaterial(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Compute the dissipated energy in each element by a trapezoidal approximation * of * @f$ Ed = \int_0^{\epsilon}\sigma(\omega)d\omega - * \frac{1}{2}\sigma:\epsilon@f$ */ template class Parent> void MaterialOrthotropicDamage::updateEnergies( ElementType el_type) { Parent::updateEnergies(el_type); this->computePotentialEnergy(el_type); auto epsilon_p = this->gradu.previous(el_type).begin(spatial_dimension, spatial_dimension); auto sigma_p = this->stress.previous(el_type).begin(spatial_dimension, spatial_dimension); auto epot = this->potential_energy(el_type).begin(); auto ints = this->int_sigma(el_type).begin(); auto ed = this->dissipated_energy(el_type).begin(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, _not_ghost); Matrix delta_gradu_it(grad_u); delta_gradu_it -= *epsilon_p; Matrix sigma_h(sigma); sigma_h += *sigma_p; Real dint = .5 * sigma_h.doubleDot(delta_gradu_it); *ints += dint; *ed = *ints - *epot; ++epsilon_p; ++sigma_p; ++epot; ++ints; ++ed; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; } /* -------------------------------------------------------------------------- */ template class Parent> void MaterialOrthotropicDamage::computeTangentModuli( ElementType el_type, Array & tangent_matrix, GhostType ghost_type) { AKANTU_DEBUG_IN(); Parent::computeTangentModuli(el_type, tangent_matrix, ghost_type); /// get the damage array for current element type Array & dam = this->damage(el_type); auto dam_it = dam.begin(this->spatial_dimension, this->spatial_dimension); /// get the directions of damage for the current element type Array & dam_dirs = this->damage_dir_vecs(el_type); auto damage_directions_it = dam_dirs.begin(this->spatial_dimension, this->spatial_dimension); /// for the computation of the Cauchy stress the matrices (1-D) and /// (1-D)^(1/2) are needed. For the formulation see Engineering /// Damage Mechanics by Lemaitre and Desmorat. Matrix one_minus_D(this->spatial_dimension, this->spatial_dimension); Matrix sqrt_one_minus_D(this->spatial_dimension, this->spatial_dimension); Matrix one_minus_D_rot(spatial_dimension, spatial_dimension); Matrix sqrt_one_minus_D_rot(spatial_dimension, spatial_dimension); Matrix rotation_tmp(spatial_dimension, spatial_dimension); MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix); if (!(Math::are_float_equal((*dam_it).trace(), 0))) computeTangentModuliOnQuad(tangent, tangent, *dam_it, *damage_directions_it, one_minus_D, sqrt_one_minus_D, one_minus_D_rot, sqrt_one_minus_D_rot, rotation_tmp); ++dam_it; ++damage_directions_it; MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template class Parent> void MaterialOrthotropicDamage:: computeTangentModuliOnQuad(Matrix & tangent, const Matrix C, const Matrix & dam, const Matrix & dam_directions, Matrix & O_prime, Matrix & S_prime, Matrix & O, Matrix & S, Matrix & rotation_tmp) { /// effect of damage on stiffness matrix: See Ragueneau et al. 2008, p. 423, /// ep. 7 Real trace_D = dam.trace(); this->computeOneMinusD(O_prime, dam); this->computeSqrtOneMinusD(O_prime, S_prime); this->rotateIntoComputationFrame(O_prime, O, dam_directions, rotation_tmp); this->rotateIntoComputationFrame(S_prime, S, dam_directions, rotation_tmp); /// compute new stiffness matrix in damage coordinate system if (spatial_dimension == 1) tangent *= (1 - dam(0, 0)); if (spatial_dimension == 2) { Real min_val = std::min((this->eta / spatial_dimension * trace_D), this->max_damage); /// first row tangent(0, 0) = (C(0, 0) * S(0, 0) * S(0, 0) + C(1, 0) * S(0, 1) * S(0, 1) - (min_val / 2. - 1. / 2) * (C(0, 0) + C(1, 0)) + (O(0, 0) * (C(0, 0) * O(0, 0) + C(1, 0) * O(1, 1))) / (trace_D - 2.)); tangent(0, 1) = (C(0, 1) * S(0, 0) * S(0, 0) + C(1, 1) * S(0, 1) * S(0, 1) - (min_val / 2. - 1. / 2) * (C(0, 1) + C(1, 1)) + (O(0, 0) * (C(0, 1) * O(0, 0) + C(1, 1) * O(1, 1))) / (trace_D - 2.)); tangent(0, 2) = (2. * C(2, 2) * S(0, 0) * S(0, 1) + (2. * C(2, 2) * O(0, 0) * O(0, 1)) / (trace_D - 2.)); /// second row tangent(1, 0) = (C(0, 0) * S(0, 1) * S(0, 1) + C(1, 0) * S(1, 1) * S(1, 1) - (min_val / 2. - 1. / 2) * (C(0, 0) + C(1, 0)) + (O(1, 1) * (C(0, 0) * O(0, 0) + C(1, 0) * O(1, 1))) / (trace_D - 2.)); tangent(1, 1) = (C(0, 1) * S(0, 1) * S(0, 1) + C(1, 1) * S(1, 1) * S(1, 1) - (min_val / 2. - 1. / 2) * (C(0, 1) + C(1, 1)) + (O(1, 1) * (C(0, 1) * O(0, 0) + C(1, 1) * O(1, 1))) / (trace_D - 2.)); tangent(1, 2) = (2. * C(2, 2) * S(0, 1) * S(1, 1) + (2. * C(2, 2) * O(0, 1) * O(1, 1)) / (trace_D - 2.)); /// third row tangent(2, 0) = ((O(0, 1) * (C(0, 0) * O(0, 0) + C(1, 0) * O(1, 1))) / (trace_D - 2.) + C(0, 0) * S(0, 0) * S(0, 1) + C(1, 0) * S(0, 1) * S(1, 1)); tangent(2, 1) = ((O(0, 1) * (C(0, 1) * O(0, 0) + C(1, 1) * O(1, 1))) / (trace_D - 2.) + C(0, 1) * S(0, 0) * S(0, 1) + C(1, 1) * S(0, 1) * S(1, 1)); tangent(2, 2) = ((2. * C(2, 2) * O(0, 1) * O(0, 1)) / (trace_D - 2.) + C(2, 2) * S(0, 1) * S(0, 1) + C(2, 2) * S(0, 0) * S(1, 1)); } if (spatial_dimension == 3) { } } /* -------------------------------------------------------------------------- */ template class Parent> inline void MaterialOrthotropicDamage:: computeDamageAndStressOnQuad(Matrix & sigma, Matrix & one_minus_D, Matrix & sqrt_one_minus_D, Matrix & damage, Matrix & first_term, Matrix & third_term) { /// Definition of Cauchy stress based on second order damage tensor: /// "Anisotropic damage modelling of biaxial behaviour and rupture /// of concrete strucutres", Ragueneau et al., 2008, Eq. 7 first_term.mul(sqrt_one_minus_D, sigma); first_term *= sqrt_one_minus_D; Real second_term = 0; for (UInt i = 0; i < this->spatial_dimension; ++i) { for (UInt j = 0; j < this->spatial_dimension; ++j) second_term += sigma(i, j) * one_minus_D(i, j); } second_term /= (this->spatial_dimension - damage.trace()); one_minus_D *= second_term; third_term.eye(1. / this->spatial_dimension * sigma.trace() * (1 - eta / (this->spatial_dimension) * damage.trace())); sigma.copy(first_term); sigma -= one_minus_D; sigma += third_term; } /* -------------------------------------------------------------------------- */ template class Parent> inline void MaterialOrthotropicDamage:: rotateIntoComputationFrame(const Matrix & to_rotate, Matrix & rotated, const Matrix & damage_directions, Matrix & rotation_tmp) { rotation_tmp.mul(to_rotate, damage_directions); rotated.mul(damage_directions, rotation_tmp); } /* -------------------------------------------------------------------------- */ template class Parent> inline void MaterialOrthotropicDamage::rotateIntoNewFrame( const Matrix & to_rotate, Matrix & rotated, const Matrix & damage_directions, Matrix & rotation_tmp) { rotation_tmp.mul(to_rotate, damage_directions); rotated.mul(damage_directions, rotation_tmp); } /* -------------------------------------------------------------------------- */ template class Parent> inline void MaterialOrthotropicDamage::computeOneMinusD( Matrix & one_minus_D, const Matrix & damage) { /// compute one minus one_minus_D.eye(); one_minus_D -= damage; } /* -------------------------------------------------------------------------- */ template class Parent> inline void MaterialOrthotropicDamage::computeSqrtOneMinusD( const Matrix & one_minus_D, Matrix & sqrt_one_minus_D) { /// To compute (1-D)^1/2 we need to check that we are in the /// principal coordinate system of the damage #ifndef AKANTU_NDEBUG for (Int i = 0; i < this->spatial_dimension; ++i) { for (Int j = 0; j < this->spatial_dimension; ++j) { if (i != j) AKANTU_DEBUG_ASSERT(Math::are_float_equal(one_minus_D(i, j), 0), "The damage tensor has off-diagonal parts"); } } #endif // AKANTU_NDEBUG /// compute (1-D)^1/2 sqrt_one_minus_D.copy(one_minus_D); for (Int i = 0; i < this->spatial_dimension; ++i) sqrt_one_minus_D(i, i) = std::sqrt(sqrt_one_minus_D(i, i)); } /* -------------------------------------------------------------------------- */ } // namespace akantu diff --git a/extra_packages/extra-materials/src/material_damage/material_vreepeerlings.hh b/extra_packages/extra-materials/src/material_damage/material_vreepeerlings.hh index 68805327e..c85dd4528 100644 --- a/extra_packages/extra-materials/src/material_damage/material_vreepeerlings.hh +++ b/extra_packages/extra-materials/src/material_damage/material_vreepeerlings.hh @@ -1,147 +1,147 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material_damage.hh" /* -------------------------------------------------------------------------- */ #ifndef AKANTU_MATERIAL_VREEPEERLINGS_HH_ #define AKANTU_MATERIAL_VREEPEERLINGS_HH_ namespace akantu { /** * Material vreepeerlings * * parameters in the material files : * - Kapaoi : (default: 0.0001) Initial threshold (of the equivalent strain) * >= Crate * - Kapac : (default: 0.0002) Final threshold (of the equivalent strain) * - Arate : (default: 1.) Fitting parameter (must be close to 1 to do tend * to 0 the stress in the damaged element) * - Brate : (default: 1.) This parameter determines the rate at which the * damage grows * - Crate : (default: 0.0001) This parameter determines the rate at which * the damage grows * - Kct : (default: 1.) Ratio between compressive and tensile strength */ template class MatParent = MaterialElastic> class MaterialVreePeerlings : public MaterialDamage { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: typedef MaterialDamage MaterialVreePeerlingsParent; MaterialVreePeerlings(SolidMechanicsModel & model, const ID & id = ""); virtual ~MaterialVreePeerlings(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void initMaterial(); /// constitutive law for all element of a type void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost); protected: /// constitutive law for a given quadrature point inline void computeStressOnQuad(Matrix & F, Matrix & sigma, Real & dam, Real & Equistrain_rate, Real & Equistrain, Real & Kapaq, Real dt, Matrix & strain_rate_vrpgls, Real & FullDam_ValStrain, Real & FullDam_ValStrain_rate, Real & Nb_damage); inline void computeDamageAndStressOnQuad(Matrix & sigma, Real & dam, Real & Equistrain_rate, Real & Equistrain, Real & Kapaq, Real dt, Real & FullDam_Valstrain, Real & FullDam_Valstrain_rate, Real & Nb_damage); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// Initial threshold (of the equivalent strain) (used in the initial step) Real Kapaoi; /// Final threshold (of the equivalent strain) (used in the initial step) Real Kapac; /// This parameter determines the rate at which the damage grows Real Arate; /// This parameter determines the rate at which the damage grows Real Brate; /// This parameter determines the rate at which the damage grows Real Crate; /// Ratio between compressive and tensile strength Real Kct; /// Randomness on Kapaoi Real Kapao_randomness; /// Kapa vector which contains the initial damage threshold RandomInternalField Kapa; /// Strain rate tensor to compute the rate dependent damage law InternalField strain_rate_vreepeerlings; /// Value of the equivalent strain when damage = 1 InternalField Full_dam_value_strain; /// Value of the equivalent strain rate when damage = 1 InternalField Full_dam_value_strain_rate; /// Count the number of times that the material is damaged to damage = 0 until /// damage = 1 InternalField Number_damage; /// Equivalent strain used to compute the damage evolution InternalField equi_strain; /// Equivalent strain rate used to compute the damage evolution InternalField equi_strain_rate; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_vreepeerlings_inline_impl.hh" #include "material_vreepeerlings_tmpl.hh" } // namespace akantu #endif /* AKANTU_MATERIAL_VREEPEERLINGS_HH_ */ diff --git a/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_inline_impl.hh b/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_inline_impl.hh index acb77dced..bff0496d9 100644 --- a/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_inline_impl.hh +++ b/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_inline_impl.hh @@ -1,190 +1,190 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ template class MatParent> inline void MaterialVreePeerlings::computeStressOnQuad( Matrix & grad_u, Matrix & sigma, Real & dam, Real & Equistrain, Real & Equistrain_rate, Real & Kapaq, Real dt, Matrix & strain_rate_vrplgs, Real & FullDam_ValStrain, Real & FullDam_ValStrain_rate, Real & Nb_damage) { Real I1 = 0.; /// trace initialization of the strain tensor Real J2 = 0.; /// J2 [J2=1/6(3 strain:strain - I1*I1)] initialization Real I1rate = 0.; /// trace initialization of the strain rate tensor Real J2rate = 0.; /// J2 [J2=1/3(3 strain:strainrate - I1*I1rate)] initialization if (spatial_dimension == 1) { I1 = grad_u.trace(); J2 = .5 * grad_u(0, 0) * grad_u(0, 0) - I1 * I1 / 6.; I1rate = strain_rate_vrplgs.trace(); J2rate = grad_u(0, 0) * strain_rate_vrplgs(0, 0) - I1 * I1rate / 6.; } else { // if(this->plane_stress) { // Real tmp = this->nu/(this->nu - 1); // tmp *= tmp; // I1 = (grad_u(0,0) + grad_u(1,1))*(1 - 2*this->nu)/(1 - this->nu); // J2 = .5*(grad_u(0,0)*grad_u(0,0) + // grad_u(1,1)*grad_u(1,1) + // tmp*(grad_u(0,0) + grad_u(1,1))*(grad_u(0,0) + grad_u(1,1)) + // .5*(grad_u(0,1) + grad_u(1,0))*(grad_u(0,1) + grad_u(1,0))) - // I1*I1/6.; // I1rate = (strain_rate_vrplgs(0,0) + strain_rate_vrplgs(1,1))*(1 - // 2*this->nu)/(1 - this->nu); // J2rate = (grad_u(0,0)*strain_rate_vrplgs(0,0) + // grad_u(1,1)*strain_rate_vrplgs(1,1) + // tmp*(grad_u(0,0) + grad_u(1,1))*(strain_rate_vrplgs(0,0) + // strain_rate_vrplgs(1,1)) + // (grad_u(0,1)*strain_rate_vrplgs(1,0)) + // (grad_u(0,1)*strain_rate_vrplgs(1,0))) - // I1*I1rate/3.; // } // else { I1 = grad_u.trace(); for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = i; j < spatial_dimension; ++j) J2 += 0.5 * ((i == j) * grad_u(i, i) * grad_u(i, i) + 0.5 * (1 - (i == j)) * ((grad_u(i, j) + grad_u(j, i)) * (grad_u(i, j) + grad_u(j, i)))); J2 -= I1 * I1 / 6.; I1rate = strain_rate_vrplgs.trace(); bool is3D = spatial_dimension == 3; J2rate = (grad_u(0, 0) * strain_rate_vrplgs(0, 0) + grad_u(1, 1) * strain_rate_vrplgs(1, 1) + is3D * grad_u(2, 2) * strain_rate_vrplgs(2, 2) + (grad_u(0, 1) * strain_rate_vrplgs(1, 0)) + (grad_u(0, 1) * strain_rate_vrplgs(1, 0)) + is3D * (grad_u(1, 2) * strain_rate_vrplgs(2, 1)) + is3D * (grad_u(1, 2) * strain_rate_vrplgs(2, 1)) + is3D * (grad_u(2, 0) * strain_rate_vrplgs(0, 2)) + is3D * (grad_u(2, 0) * strain_rate_vrplgs(0, 2))) - I1 * I1rate / 3.; // } } Real tmp_1 = (Kct - 1) / (1 - 2 * this->nu); Real tmp_2 = (12 * Kct) / ((1 + this->nu) * (1 + this->nu)); Equistrain = tmp_1 * I1 / (2 * Kct) + 1. / (2 * Kct) * std::sqrt(tmp_1 * tmp_1 * I1 * I1 + tmp_2 * J2); if (I1 * I1rate > 0 || J2rate > 0) { Equistrain_rate = tmp_1 * std::abs(I1rate) / (2 * Kct) + 1. / (4 * Kct) * (2 * tmp_1 * tmp_1 * I1 * I1rate + tmp_2 * J2rate) / std::sqrt(tmp_1 * tmp_1 * I1 * I1 + tmp_2 * J2); } else { AKANTU_ERROR("This instruction here was commented but has to be checked"); // Equistrain_rate = Equistrain_rate; } if (!this->is_non_local) { computeDamageAndStressOnQuad(sigma, dam, Equistrain, Equistrain_rate, Kapaq, dt, FullDam_ValStrain, FullDam_ValStrain_rate, Nb_damage); } } /* -------------------------------------------------------------------------- */ template class MatParent> inline void MaterialVreePeerlings:: computeDamageAndStressOnQuad(Matrix & sigma, Real & dam, Real & Equistrain, Real & Equistrain_rate, Real & Kapaq, Real dt, Real & FullDam_ValStrain, Real & FullDam_ValStrain_rate, Real & Nb_damage) { //--------------------------------------------------------------------------------------- // rate-dependence model // //--------------------------------------------------------------------------------------- Real Kapao = Crate * (1. + (std::pow(std::abs(Equistrain_rate) * Arate, Brate))) * (1. - Kapao_randomness) + Kapao_randomness * Kapaq; Real Kapac_99 = Kapac * .99; Real Kapaodyn = 0; if (Kapao > Kapaoi) { if (Kapao < Kapac_99) { Kapaodyn = Kapao; } else { Kapaodyn = Kapac_99; } } else { Kapaodyn = Kapaoi; } Real Fd1 = Equistrain - Kapaoi; if (Fd1 > 0) { Real dam1 = 1. - Kapaodyn / Equistrain * ((Kapac - Equistrain) / (Kapac - Kapaodyn)); if (dam1 > dam) { dam = std::min(dam1, 1.); Nb_damage = Nb_damage + 1.; if (dam >= 1.) { FullDam_ValStrain = Equistrain; FullDam_ValStrain_rate = Equistrain_rate; } } } //--------------------------------------------------------------------------------------- // delayed damage (see Marions thesis page 68) //--------------------------------------------------------------------------------------- // Real viscosity = 10.; // Real damRateInfini = 10000000.; // Real gequi = 1. - Kapaq/Equistrain * ((Kapac-Equistrain)/(Kapac - // Kapaq)); // if (gequi - dam > 0){ // // Real damRate = damRateInfini * (1. - std::exp(-1*viscosity * (gequi - // dam))); // if (damrate > 0){ // // if (dam < 1.){ // dam = dam + damRate*dt; // } else { // dam = 1.; // } // } // } // //--------------------------------------------------------------------------------------- sigma *= 1 - dam; } /* -------------------------------------------------------------------------- */ diff --git a/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_non_local.cc b/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_non_local.cc index 0c90d9244..faf6bf04c 100644 --- a/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_non_local.cc +++ b/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_non_local.cc @@ -1,30 +1,30 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "material_vreepeerlings_non_local.hh" #include "solid_mechanics_model.hh" namespace akantu { /* -------------------------------------------------------------------------- */ // INSTANTIATE_MATERIAL(MaterialVreePeerlingsNonLocal); } // namespace akantu diff --git a/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_non_local.hh b/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_non_local.hh index 51ee862ba..09566e87a 100644 --- a/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_non_local.hh +++ b/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_non_local.hh @@ -1,94 +1,94 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material_damage_non_local.hh" #include "material_vreepeerlings.hh" /* -------------------------------------------------------------------------- */ #ifndef AKANTU_MATERIAL_VREEPEERLINGS_NON_LOCAL_HH_ #define AKANTU_MATERIAL_VREEPEERLINGS_NON_LOCAL_HH_ namespace akantu { /** * Material VreePeerlings Non local * * parameters in the material files : */ template class MatParent = MaterialElastic> class MaterialVreePeerlingsNonLocal : public MaterialDamageNonLocal< spatial_dimension, MaterialVreePeerlings> { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: typedef MaterialVreePeerlings Parent; typedef MaterialDamageNonLocal MaterialVreePeerlingsNonLocalParent; MaterialVreePeerlingsNonLocal(SolidMechanicsModel & model, const ID & id = ""); virtual ~MaterialVreePeerlingsNonLocal(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void initMaterial(); /// constitutive law for all element of a type // void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost); /// constitutive law virtual void computeNonLocalStress(ElementType el_type, GhostType ghost_type = _not_ghost); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// non local version of equivalent strain InternalField equi_strain_non_local; /// non local version of equivalent strain rate InternalField equi_strain_rate_non_local; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_vreepeerlings_non_local_inline_impl.hh" } // namespace akantu #endif /* AKANTU_MATERIAL_VREEPEERLINGS_NON_LOCAL_HH_ */ diff --git a/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_non_local_inline_impl.hh b/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_non_local_inline_impl.hh index 7657e460e..ea24d18ad 100644 --- a/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_non_local_inline_impl.hh +++ b/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_non_local_inline_impl.hh @@ -1,163 +1,163 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ template class MatParent> MaterialVreePeerlingsNonLocal:: MaterialVreePeerlingsNonLocal(SolidMechanicsModel & model, const ID & id) : Material(model, id), MaterialVreePeerlingsNonLocalParent(model, id), equi_strain_non_local("equi-strain_non_local", *this), equi_strain_rate_non_local("equi-strain-rate_non_local", *this) { AKANTU_DEBUG_IN(); this->is_non_local = true; this->equi_strain_non_local.initialize(1); this->equi_strain_rate_non_local.initialize(1); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template class MatParent> void MaterialVreePeerlingsNonLocal::initMaterial() { AKANTU_DEBUG_IN(); this->registerNonLocalVariable(this->equi_strain, this->equi_strain_non_local, 1); this->registerNonLocalVariable(this->equi_strain_rate, this->equi_strain_rate_non_local, 1); MaterialVreePeerlingsNonLocalParent::initMaterial(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ // template class // MatParent> // void MaterialVreePeerlingsNonLocal::computeStress(ElementType el_type, // GhostType ghost_type) { // AKANTU_DEBUG_IN(); // // Real * dam = this->damage(el_type, ghost_type).data(); // Real * equi_straint = equi_strain(el_type, ghost_type).data(); // Real * equi_straint_rate = equi_strain_rate(el_type, ghost_type).data(); // Real * Kapaq = this->Kapa(el_type, ghost_type).data(); // Real * crit_strain = this->critical_strain(el_type, ghost_type).data(); // Real * crit_strain_rate = this->critical_strain_rate(el_type, // ghost_type).data(); // Real * rdr_damage = this->recorder_damage(el_type, ghost_type).data(); // Real * nb_damage = this->number_damage(el_type, ghost_type).data(); // Real dt = this->model.getTimeStep(); // // Vector & elem_filter = this->element_filter(el_type, ghost_type); // Vector & velocity = this->model.getVelocity(); // Vector & strain_rate_vrplgs = this->strain_rate_vreepeerlings(el_type, // ghost_type); // // // this->model.getFEEngine().gradientOnQuadraturePoints(velocity, // strain_rate_vrplgs, // spatial_dimension, // el_type, ghost_type, &elem_filter); // // Vector::iterator strain_rate_vrplgs_it = // strain_rate_vrplgs.begin(spatial_dimension, spatial_dimension); // // // MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); // // types::RMatrix & strain_rate = *strain_rate_vrplgs_it; // // // // MaterialVreePeerlings::computeStressOnQuad(grad_u, sigma, // *dam, // *equi_straint, // *equi_straint_rate, // *Kapaq, // dt, // strain_rate, // *crit_strain, // *crit_strain_rate, // *rdr_damage, // *nb_damage); // ++dam; // ++equi_straint; // ++equi_straint_rate; // ++Kapaq; // ++strain_rate_vrplgs_it; // ++crit_strain; // ++crit_strain_rate; // ++rdr_damage; // ++nb_damage; // // MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; // // AKANTU_DEBUG_OUT(); //} // /* -------------------------------------------------------------------------- */ template class MatParent> void MaterialVreePeerlingsNonLocal< spatial_dimension, MatParent>::computeNonLocalStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Real * dam = this->damage(el_type, ghost_type).data(); Real * Kapaq = this->Kapa(el_type, ghost_type).data(); Real * equi_strain_nl = this->equi_strain_non_local(el_type, ghost_type).data(); Real * equi_strain_rate_nl = this->equi_strain_rate_non_local(el_type, ghost_type).data(); // Real * equi_strain_rate_nl = this->equi_strain_rate(el_type, // ghost_type).data(); Real dt = this->model.getTimeStep(); Real * FullDam_Valstrain = this->Full_dam_value_strain(el_type, ghost_type).data(); Real * FullDam_Valstrain_rate = this->Full_dam_value_strain_rate(el_type, ghost_type).data(); Real * Nb_damage = this->Number_damage(el_type, ghost_type).data(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); this->computeDamageAndStressOnQuad( sigma, *dam, *equi_strain_nl, *equi_strain_rate_nl, *Kapaq, dt, *FullDam_Valstrain, *FullDam_Valstrain_rate, *Nb_damage); ++dam; ++equi_strain_nl; ++equi_strain_rate_nl; ++Kapaq; ++FullDam_Valstrain; ++FullDam_Valstrain_rate; ++Nb_damage; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } diff --git a/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_tmpl.hh b/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_tmpl.hh index 9b2c50d38..89fc35cc5 100644 --- a/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_tmpl.hh +++ b/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_tmpl.hh @@ -1,111 +1,111 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ template class MatParent> MaterialVreePeerlings::MaterialVreePeerlings( SolidMechanicsModel & model, const ID & id) : Material(model, id), MaterialVreePeerlingsParent(model, id), Kapa("Kapa", *this), strain_rate_vreepeerlings("strain-rate-vreepeerlings", *this), Full_dam_value_strain("fulldam-valstrain", *this), Full_dam_value_strain_rate("fulldam-valstrain-rate", *this), Number_damage("number-damage", *this), equi_strain("equi-strain", *this), equi_strain_rate("equi-strain-rate", *this) { AKANTU_DEBUG_IN(); this->registerParam("Kapaoi", Kapaoi, 0.0001, _pat_parsable); this->registerParam("Kapac", Kapac, 0.0002, _pat_parsable); this->registerParam("Arate", Arate, 0., _pat_parsable); this->registerParam("Brate", Brate, 1., _pat_parsable); this->registerParam("Crate", Brate, 1., _pat_parsable); this->registerParam("Kct", Kct, 1., _pat_parsable); this->registerParam("Kapao_randomness", Kapao_randomness, 0., _pat_parsable); this->Kapa.initialize(1); this->equi_strain.initialize(1); this->equi_strain_rate.initialize(1); this->Full_dam_value_strain.initialize(1); this->Full_dam_value_strain_rate.initialize(1); this->Number_damage.initialize(1); this->strain_rate_vreepeerlings.initialize(spatial_dimension * spatial_dimension); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template class MatParent> void MaterialVreePeerlings::initMaterial() { AKANTU_DEBUG_IN(); MaterialVreePeerlingsParent::initMaterial(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template class MatParent> void MaterialVreePeerlings::computeStress( ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); MaterialVreePeerlingsParent::computeStress(el_type, ghost_type); Real * dam = this->damage(el_type, ghost_type).data(); Real * equi_straint = equi_strain(el_type, ghost_type).data(); Real * equi_straint_rate = equi_strain_rate(el_type, ghost_type).data(); Real * Kapaq = Kapa(el_type, ghost_type).data(); Real * FullDam_Valstrain = Full_dam_value_strain(el_type, ghost_type).data(); Real * FullDam_Valstrain_rate = Full_dam_value_strain_rate(el_type, ghost_type).data(); Real * Nb_damage = Number_damage(el_type, ghost_type).data(); Real dt = this->model.getTimeStep(); Array & elem_filter = this->element_filter(el_type, ghost_type); Array & velocity = this->model.getVelocity(); Array & strain_rate_vrplgs = this->strain_rate_vreepeerlings(el_type, ghost_type); this->model.getFEEngine().gradientOnIntegrationPoints( velocity, strain_rate_vrplgs, spatial_dimension, el_type, ghost_type, elem_filter); Array::matrix_iterator strain_rate_vrplgs_it = strain_rate_vrplgs.begin(spatial_dimension, spatial_dimension); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); Matrix & strain_rate = *strain_rate_vrplgs_it; computeStressOnQuad(grad_u, sigma, *dam, *equi_straint, *equi_straint_rate, *Kapaq, dt, strain_rate, *FullDam_Valstrain, *FullDam_Valstrain_rate, *Nb_damage); ++dam; ++equi_straint; ++equi_straint_rate; ++Kapaq; ++strain_rate_vrplgs_it; ++FullDam_Valstrain; ++FullDam_Valstrain_rate; ++Nb_damage; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } diff --git a/extra_packages/extra-materials/src/material_extra_includes.hh b/extra_packages/extra-materials/src/material_extra_includes.hh index 77e22fd16..315747898 100644 --- a/extra_packages/extra-materials/src/material_extra_includes.hh +++ b/extra_packages/extra-materials/src/material_extra_includes.hh @@ -1,75 +1,75 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #ifndef AKANTU_MATERIAL_EXTRA_INCLUDES_HH_ #define AKANTU_MATERIAL_EXTRA_INCLUDES_HH_ #ifndef AKANTU_CMAKE_LIST_MATERIALS // visco-elastic materials #include "material_stiffness_proportional.hh" // damage materials #include "material_brittle.hh" #include "material_damage_iterative.hh" #include "material_damage_linear.hh" #include "material_iterative_stiffness_reduction.hh" #include "material_orthotropic_damage_iterative.hh" #include "material_vreepeerlings.hh" // plasticity #include "material_viscoplastic.hh" // multi-scale simulations #include "material_FE2.hh" #endif #if defined(AKANTU_DAMAGE_NON_LOCAL) #ifndef AKANTU_CMAKE_LIST_MATERIALS #include "material_brittle_non_local.hh" #include "material_damage_iterative_non_local.hh" #include "material_orthotropic_damage_iterative_non_local.hh" #include "material_orthotropic_damage_non_local.hh" #include "material_vreepeerlings_non_local.hh" #endif #define AKANTU_DAMAGE_NON_LOCAL_MATERIAL_EXTRA_LIST \ ((2, (brittle_non_local, MaterialBrittleNonLocal)))( \ (2, (damage_iterative_non_local, MaterialDamageIterativeNonLocal)))( \ (2, (damage_orthotropic_iterative_non_local, \ MaterialOrthotropicDamageIterativeNonLocal))) #else #define AKANTU_DAMAGE_NON_LOCAL_MATERIAL_EXTRA_LIST #endif #define AKANTU_EXTRA_MATERIAL_LIST \ ((2, (damage_linear, MaterialDamageLinear)))( \ (2, (brittle, MaterialBrittle)))((2, (material_FE2, MaterialFE2)))( \ (2, (damage_iterative, MaterialDamageIterative)))( \ (2, \ (iterative_stiffness_reduction, MaterialIterativeStiffnessReduction)))( \ (2, (vreepeerlings, MaterialVreePeerlings)))( \ (2, (ve_stiffness_prop, MaterialStiffnessProportional)))( \ (2, (visco_plastic, MaterialViscoPlastic)))( \ (2, (orthotropic_damage_iterative, MaterialOrthotropicDamageIterative))) #endif /* AKANTU_MATERIAL_EXTRA_INCLUDES_HH_ */ diff --git a/extra_packages/extra-materials/src/material_non_local_extra_includes.hh b/extra_packages/extra-materials/src/material_non_local_extra_includes.hh index 1cec007c8..e54aded7e 100644 --- a/extra_packages/extra-materials/src/material_non_local_extra_includes.hh +++ b/extra_packages/extra-materials/src/material_non_local_extra_includes.hh @@ -1,21 +1,21 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ diff --git a/extra_packages/extra-materials/src/material_plastic/material_viscoplastic.cc b/extra_packages/extra-materials/src/material_plastic/material_viscoplastic.cc index 82c7709a0..1ae83c8bb 100644 --- a/extra_packages/extra-materials/src/material_plastic/material_viscoplastic.cc +++ b/extra_packages/extra-materials/src/material_plastic/material_viscoplastic.cc @@ -1,112 +1,112 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "material_viscoplastic.hh" #include "solid_mechanics_model.hh" /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ template MaterialViscoPlastic::MaterialViscoPlastic(SolidMechanicsModel & model, const ID & id) : MaterialPlastic(model, id) { AKANTU_DEBUG_IN(); this->registerParam("rate", rate, 0., _pat_parsable | _pat_modifiable, "Rate sensitivity component"); this->registerParam("edot0", edot0, 0., _pat_parsable | _pat_modifiable, "Reference strain rate"); this->registerParam("ts", ts, 0., _pat_parsable | _pat_modifiable, "Time Step"); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialViscoPlastic::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Real * iso_hardening = this->iso_hardening(el_type, ghost_type).data(); auto previous_grad_u_it = this->gradu.previous(el_type, ghost_type).begin(dim, dim); auto previous_sigma_it = this->stress.previous(el_type, ghost_type).begin(dim, dim); auto inelastic_strain_it = this->inelastic_strain(el_type, ghost_type).begin(dim, dim); auto previous_inelastic_strain_it = this->inelastic_strain.previous(el_type, ghost_type).begin(dim, dim); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); computeStressOnQuad(grad_u, *previous_grad_u_it, sigma, *previous_sigma_it, *inelastic_strain_it, *previous_inelastic_strain_it, *iso_hardening); ++inelastic_strain_it; ++iso_hardening; ++previous_grad_u_it; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialViscoPlastic::computeTangentModuli( __attribute__((unused)) ElementType el_type, Array & tangent_matrix, __attribute__((unused)) GhostType ghost_type) { AKANTU_DEBUG_IN(); auto previous_sigma_it = this->stress.previous(el_type, ghost_type).begin(dim, dim); auto previous_strain_it = this->gradu.previous(el_type, ghost_type).begin(dim, dim); Real * iso_hardening = this->iso_hardening(el_type, ghost_type).data(); MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix); Matrix & previous_grad_u = *previous_strain_it; Matrix & previous_sigma_tensor = *previous_sigma_it; computeTangentModuliOnQuad(tangent, grad_u, previous_grad_u, sigma, previous_sigma_tensor, *iso_hardening); ++previous_sigma_it; ++previous_strain_it; ++iso_hardening; MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } INSTANTIATE_MATERIAL(visco_plastic, MaterialViscoPlastic); } // namespace akantu diff --git a/extra_packages/extra-materials/src/material_plastic/material_viscoplastic.hh b/extra_packages/extra-materials/src/material_plastic/material_viscoplastic.hh index 449975c66..360e04738 100644 --- a/extra_packages/extra-materials/src/material_plastic/material_viscoplastic.hh +++ b/extra_packages/extra-materials/src/material_plastic/material_viscoplastic.hh @@ -1,102 +1,102 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_voigthelper.hh" #include "material_plastic.hh" /* -------------------------------------------------------------------------- */ #ifndef AKANTU_MATERIAL_VISCOPLASTIC_HH_ #define AKANTU_MATERIAL_VISCOPLASTIC_HH_ namespace akantu { /** * Material plastic isotropic * * parameters in the material files : * - h : Hardening parameter (default: 0) * - sigmay : Yield stress * - rate : Rate sensitivity * - edot0 : Reference strain rate * * - ts: Time step */ template class MaterialViscoPlastic : public MaterialPlastic { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialViscoPlastic(SolidMechanicsModel & model, const ID & id = ""); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// constitutive law for all element of a type virtual void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost); /// compute the tangent stiffness matrix for an element type void computeTangentModuli(ElementType el_type, Array & tangent_matrix, GhostType ghost_type = _not_ghost); protected: inline void computeStressOnQuad(const Matrix & grad_u, const Matrix & previous_grad_u, Matrix & sigma, const Matrix & previous_sigma, Matrix & inelastic_strain, const Matrix & previous_inelastic_strain, Real & iso_hardening) const; inline void computeTangentModuliOnQuad( Matrix & tangent, const Matrix & grad_u, const Matrix & previous_grad_u, const Matrix & sigma_tensor, const Matrix & previous_sigma_tensor, const Real & iso_hardening) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// Rate sensitivity component (rate) Real rate; /// Reference strain rate (edot0) Real edot0; /// Time step (ts) Real ts; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_viscoplastic_inline_impl.hh" } // namespace akantu #endif /* AKANTU_MATERIAL_VISCOPLASTIC_HH_ */ diff --git a/extra_packages/extra-materials/src/material_plastic/material_viscoplastic_inline_impl.hh b/extra_packages/extra-materials/src/material_plastic/material_viscoplastic_inline_impl.hh index 7b5169801..8b29e96cd 100644 --- a/extra_packages/extra-materials/src/material_plastic/material_viscoplastic_inline_impl.hh +++ b/extra_packages/extra-materials/src/material_plastic/material_viscoplastic_inline_impl.hh @@ -1,95 +1,95 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ #include "material_viscoplastic.hh" #include /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ template inline void MaterialViscoPlastic::computeStressOnQuad( const Matrix & grad_u, const Matrix & previous_grad_u, Matrix & sigma, const Matrix & previous_sigma, Matrix & inelastic_strain, const Matrix & previous_inelastic_strain, Real & iso_hardening) const { // Infinitesimal plastic // Compute stress magnitude Real s = sigma.doubleDot(sigma); Real sigma_mag = sqrt(s); // Compute plastic strain increment Real factor = (this->ts * this->edot0 * pow(sigma_mag, (this->rate - 1.)) / pow(this->sigma_y + iso_hardening, this->rate)); Matrix delta_inelastic_strain(sigma); delta_inelastic_strain *= factor; // Compute plastic strain increment magnitude s = delta_inelastic_strain.doubleDot(delta_inelastic_strain); Real dep_mag = std::sqrt(s); Matrix grad_delta_u(grad_u); grad_delta_u -= previous_grad_u; // Update stress and plastic strain Matrix grad_u_elastic(dim, dim); grad_u_elastic = grad_delta_u; grad_u_elastic -= delta_inelastic_strain; Matrix sigma_elastic(dim, dim); MaterialElastic::computeStressOnQuad(grad_u_elastic, sigma_elastic); sigma += sigma_elastic; inelastic_strain += delta_inelastic_strain; // Update resistance stress iso_hardening = iso_hardening + this->h * dep_mag; MaterialPlastic::computeStressAndInelasticStrainOnQuad( grad_delta_u, sigma, previous_sigma, inelastic_strain, previous_inelastic_strain, delta_inelastic_strain); } /* -------------------------------------------------------------------------- */ template inline void MaterialViscoPlastic::computeTangentModuliOnQuad( Matrix & tangent, const Matrix & /*grad_u*/, const Matrix & /*previous_grad_u*/, const Matrix & /*sigma_tensor*/, const Matrix & /*previous_sigma_tensor*/, const Real & /*iso_hardening*/) const { UInt cols = tangent.cols(); UInt rows = tangent.rows(); for (Int m = 0; m < rows; ++m) { UInt i = VoigtHelper::vec[m][0]; UInt j = VoigtHelper::vec[m][1]; for (Int n = 0; n < cols; ++n) { UInt k = VoigtHelper::vec[n][0]; UInt l = VoigtHelper::vec[n][1]; tangent(m, n) = (i == k) * (j == l) * 2. * this->mu + (i == j) * (k == l) * this->lambda; tangent(m, n) -= (m == n) * (m >= dim) * this->mu; } } } diff --git a/extra_packages/extra-materials/src/material_viscoelastic/material_stiffness_proportional.cc b/extra_packages/extra-materials/src/material_viscoelastic/material_stiffness_proportional.cc index 4a0ff1ad1..3093e8cad 100644 --- a/extra_packages/extra-materials/src/material_viscoelastic/material_stiffness_proportional.cc +++ b/extra_packages/extra-materials/src/material_viscoelastic/material_stiffness_proportional.cc @@ -1,126 +1,126 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "material_stiffness_proportional.hh" #include "solid_mechanics_model.hh" namespace akantu { /* -------------------------------------------------------------------------- */ template MaterialStiffnessProportional::MaterialStiffnessProportional( SolidMechanicsModel & model, const ID & id) : MaterialElastic(model, id), stress_viscosity("stress_viscosity", *this), stress_elastic("stress_elastic", *this) { AKANTU_DEBUG_IN(); this->registerParam("Alpha", alpha, 0., _pat_parsable | _pat_modifiable, "Artificial viscous ratio"); this->stress_viscosity.initialize(spatial_dimension * spatial_dimension); this->stress_elastic.initialize(spatial_dimension * spatial_dimension); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialStiffnessProportional::initMaterial() { AKANTU_DEBUG_IN(); MaterialElastic::initMaterial(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialStiffnessProportional::computeStress( ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Array & elem_filter = this->element_filter(el_type, ghost_type); Array & stress_visc = stress_viscosity(el_type, ghost_type); Array & stress_el = stress_elastic(el_type, ghost_type); MaterialElastic::computeStress(el_type, ghost_type); Array & velocity = this->model.getVelocity(); Array strain_rate(0, spatial_dimension * spatial_dimension, "strain_rate"); this->model.getFEEngine().gradientOnIntegrationPoints( velocity, strain_rate, spatial_dimension, el_type, ghost_type, elem_filter); Array::matrix_iterator strain_rate_it = strain_rate.begin(spatial_dimension, spatial_dimension); Array::matrix_iterator stress_visc_it = stress_visc.begin(spatial_dimension, spatial_dimension); Array::matrix_iterator stress_el_it = stress_el.begin(spatial_dimension, spatial_dimension); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); Matrix & grad_v = *strain_rate_it; Matrix & sigma_visc = *stress_visc_it; Matrix & sigma_el = *stress_el_it; MaterialElastic::computeStressOnQuad(grad_v, sigma_visc); sigma_visc *= alpha; sigma_el.copy(sigma); sigma += sigma_visc; ++strain_rate_it; ++stress_visc_it; ++stress_el_it; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialStiffnessProportional::computePotentialEnergy( ElementType el_type) { AKANTU_DEBUG_IN(); Array & stress_el = stress_elastic(el_type); Array::matrix_iterator stress_el_it = stress_el.begin(spatial_dimension, spatial_dimension); Real * epot = this->potential_energy(el_type).data(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, _not_ghost); Matrix & sigma_el = *stress_el_it; MaterialElastic::computePotentialEnergyOnQuad( grad_u, sigma_el, *epot); epot++; ++stress_el_it; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ INSTANTIATE_MATERIAL(ve_stiffness_prop, MaterialStiffnessProportional); } // namespace akantu diff --git a/extra_packages/extra-materials/src/material_viscoelastic/material_stiffness_proportional.hh b/extra_packages/extra-materials/src/material_viscoelastic/material_stiffness_proportional.hh index c86857233..7d9a8195f 100644 --- a/extra_packages/extra-materials/src/material_viscoelastic/material_stiffness_proportional.hh +++ b/extra_packages/extra-materials/src/material_viscoelastic/material_stiffness_proportional.hh @@ -1,103 +1,103 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material.hh" #include "material_elastic.hh" /* -------------------------------------------------------------------------- */ #ifndef AKANTU_MATERIAL_STIFFNESS_PROPORTIONAL_HH_ #define AKANTU_MATERIAL_STIFFNESS_PROPORTIONAL_HH_ namespace akantu { /** * Material visco-elastic @f[\sigma = E\epsilon + \alpha E* * \frac{d\epsilon}{dt}@f] * it can be seen as a Kelvin-Voigt solid with @f[\eta = \alpha E @f] * * The material satisfies the Caughey condition, the visco-elastic solid has the * same eigen-modes as the elastic one. (T.K. Caughey 1960 - Journal of Applied * Mechanics 27, 269-271. Classical normal modes in damped linear systems.) * * parameters in the material files : * - rho : density (default: 0) * - E : Young's modulus (default: 0) * - nu : Poisson's ratio (default: 1/2) * - Plane_Stress : if 0: plane strain, else: plane stress (default: 0) * - alpha : viscous ratio */ template class MaterialStiffnessProportional : public MaterialElastic { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialStiffnessProportional(SolidMechanicsModel & model, const ID & id = ""); virtual ~MaterialStiffnessProportional(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void initMaterial() override; /// constitutive law for all element of a type void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost) override; /// compute the potential energy for all elements void computePotentialEnergy(ElementType el_type) override; protected: /// constitutive law for a given quadrature point // inline void computeStress(Real * F, Real * sigma); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// stress due to viscosity InternalField stress_viscosity; /// stress due to elasticity InternalField stress_elastic; /// viscous ratio Real alpha; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ //#include "material_elastic_caughey_inline_impl.hh" } // namespace akantu #endif /* AKANTU_MATERIAL_STIFFNESS_PROPORTIONAL_HH_ */ diff --git a/src/fe_engine/integrator_gauss_inline_impl.hh b/src/fe_engine/integrator_gauss_inline_impl.hh index ffebdec38..cb98b9716 100644 --- a/src/fe_engine/integrator_gauss_inline_impl.hh +++ b/src/fe_engine/integrator_gauss_inline_impl.hh @@ -1,625 +1,626 @@ /** * Copyright (©) 2011-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu - * + * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. - * + * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . */ /* -------------------------------------------------------------------------- */ #include "fe_engine.hh" #include "mesh_iterators.hh" /* -------------------------------------------------------------------------- */ namespace akantu { namespace debug { struct IntegratorGaussException : public Exception {}; } // namespace debug /* -------------------------------------------------------------------------- */ template template inline void IntegratorGauss::integrateOnElement( const Array & f, Real * intf, Int nb_degree_of_freedom, const Idx elem, GhostType ghost_type) const { auto & jac_loc = jacobians(type, ghost_type); auto nb_quadrature_points = ElementClass::getNbQuadraturePoints(); AKANTU_DEBUG_ASSERT(f.getNbComponent() == nb_degree_of_freedom, "The vector f do not have the good number of component."); auto * f_val = f.data() + elem * f.getNbComponent(); auto * jac_val = jac_loc.data() + elem * nb_quadrature_points; integrate(f_val, jac_val, intf, nb_degree_of_freedom, nb_quadrature_points); } /* -------------------------------------------------------------------------- */ template template inline Real IntegratorGauss::integrate( const Vector & in_f, Idx index, GhostType ghost_type) const { const Array & jac_loc = jacobians(type, ghost_type); auto nb_quadrature_points = GaussIntegrationElement::getNbQuadraturePoints(); AKANTU_DEBUG_ASSERT(in_f.size() == nb_quadrature_points, "The vector f do not have nb_quadrature_points entries."); auto * jac_val = jac_loc.data() + index * nb_quadrature_points; Real intf; integrate(in_f.data(), jac_val, &intf, 1, nb_quadrature_points); return intf; } /* -------------------------------------------------------------------------- */ template inline void IntegratorGauss::integrate( const Real * f, const Real * jac, Real * inte, Int nb_degree_of_freedom, Int nb_quadrature_points) const { Eigen::Map inte_v(inte, nb_quadrature_points); Eigen::Map cjac(jac, nb_quadrature_points); Eigen::Map fq(f, nb_degree_of_freedom, nb_quadrature_points); inte_v.zero(); inte_v = fq * cjac; } /* -------------------------------------------------------------------------- */ template template inline const Matrix & IntegratorGauss::getIntegrationPoints( GhostType ghost_type) const { AKANTU_DEBUG_ASSERT( quadrature_points.exists(type, ghost_type), "Quadrature points for type " << quadrature_points.printType(type, ghost_type) << " have not been initialized." << " Did you use 'computeQuadraturePoints' function ?"); return (quadrature_points(type, ghost_type)); } /* -------------------------------------------------------------------------- */ template template inline Int IntegratorGauss::getNbIntegrationPoints( GhostType ghost_type) const { AKANTU_DEBUG_ASSERT( quadrature_points.exists(type, ghost_type), "Quadrature points for type " << quadrature_points.printType(type, ghost_type) << " have not been initialized." << " Did you use 'computeQuadraturePoints' function ?"); return quadrature_points(type, ghost_type).cols(); } /* -------------------------------------------------------------------------- */ template template inline Matrix IntegratorGauss::getIntegrationPoints() const { return GaussIntegrationElement::getQuadraturePoints(); } /* -------------------------------------------------------------------------- */ template template inline Vector IntegratorGauss::getIntegrationWeights() const { return GaussIntegrationElement::getWeights(); } /* -------------------------------------------------------------------------- */ template template inline void IntegratorGauss::computeQuadraturePoints( GhostType ghost_type) { auto & quads = quadrature_points(type, ghost_type); constexpr auto polynomial_degree = IntegrationOrderFunctor::template getOrder(); quads = GaussIntegrationElement::getQuadraturePoints(); } /* -------------------------------------------------------------------------- */ template template inline void IntegratorGauss:: computeJacobianOnQuadPointsByElement( const Eigen::MatrixBase & node_coords, const Eigen::MatrixBase & quad, Eigen::MatrixBase & jacobians) const { // jacobian ElementClass::computeJacobian(quad, node_coords, jacobians); } /* -------------------------------------------------------------------------- */ template IntegratorGauss::IntegratorGauss( const Mesh & mesh, Int spatial_dimension, const ID & id) : Integrator(mesh, spatial_dimension, id) {} /* -------------------------------------------------------------------------- */ template template void IntegratorGauss::checkJacobians( GhostType ghost_type) const { auto nb_quadrature_points = this->quadrature_points(type, ghost_type).cols(); auto nb_element = mesh.getConnectivity(type, ghost_type).size(); auto * jacobians_val = jacobians(type, ghost_type).data(); for (Idx i = 0; i < nb_element * nb_quadrature_points; ++i, ++jacobians_val) { if (*jacobians_val < 0) { AKANTU_CUSTOM_EXCEPTION_INFO(debug::IntegratorGaussException{}, "Negative jacobian computed," << " possible problem in the element " "node ordering (Quadrature Point " << i % nb_quadrature_points << ":" << i / nb_quadrature_points << ":" << type << ":" << ghost_type << ")"); } } } /* -------------------------------------------------------------------------- */ template template void IntegratorGauss:: computeJacobiansOnIntegrationPoints( const Array & nodes, const Matrix & quad_points, Array & jacobians, GhostType ghost_type, const Array & filter_elements) const { auto spatial_dimension = mesh.getSpatialDimension(); auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type); auto nb_quadrature_points = quad_points.cols(); auto nb_element = mesh.getNbElement(type, ghost_type); jacobians.resize(nb_element * nb_quadrature_points); auto jacobians_it = make_view(jacobians, nb_quadrature_points).begin(); auto jacobians_begin = jacobians_it; Array x_el(0, spatial_dimension * nb_nodes_per_element); FEEngine::extractNodalToElementField(mesh, nodes, x_el, type, ghost_type, filter_elements); auto x_it = make_view(x_el, spatial_dimension, nb_nodes_per_element).begin(); nb_element = x_el.size(); // Matrix local_coord(spatial_dimension, nb_nodes_per_element); for (Idx elem = 0; elem < nb_element; ++elem, ++x_it) { const auto & x = *x_it; if (filter_elements != empty_filter) { jacobians_it = jacobians_begin + filter_elements(elem); } computeJacobianOnQuadPointsByElement(x, quad_points, *jacobians_it); if (filter_elements == empty_filter) { ++jacobians_it; } } } /* -------------------------------------------------------------------------- */ #if defined(AKANTU_STRUCTURAL_MECHANICS) template <> template void IntegratorGauss<_ek_structural, DefaultIntegrationOrderFunctor>:: computeJacobiansOnIntegrationPoints( const Array & nodes, const Matrix & quad_points, Array & jacobians, GhostType ghost_type, const Array & filter_elements) const { const auto spatial_dimension = mesh.getSpatialDimension(); const auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type); const auto nb_quadrature_points = quad_points.cols(); const auto nb_dofs = ElementClass::getNbDegreeOfFreedom(); auto nb_element = mesh.getNbElement(type, ghost_type); jacobians.resize(nb_element * nb_quadrature_points); auto jacobians_it = make_view(jacobians, nb_quadrature_points).begin(); auto jacobians_begin = jacobians_it; Array x_el(0, spatial_dimension * nb_nodes_per_element); FEEngine::extractNodalToElementField(mesh, nodes, x_el, type, ghost_type, filter_elements); auto x_it = make_view(x_el, spatial_dimension, nb_nodes_per_element).begin(); nb_element = x_el.size(); Array zeros(nb_element, spatial_dimension, 0.); const auto has_extra_normal = mesh.hasData("extra_normal", type, ghost_type); auto extra_normal_begin = make_const_view(zeros, spatial_dimension).begin(); if (has_extra_normal) { extra_normal_begin = make_const_view(mesh.getData("extra_normal", type, ghost_type), spatial_dimension) .begin(); } auto extra_normal = extra_normal_begin; // Matrix local_coord(spatial_dimension, nb_nodes_per_element); for (Idx elem = 0; elem < nb_element; ++elem, ++x_it) { if (filter_elements != empty_filter) { jacobians_it = jacobians_begin + filter_elements(elem); if (has_extra_normal) { extra_normal = extra_normal_begin + filter_elements(elem); } } const auto & X = *x_it; auto & J = *jacobians_it; Matrix R; ElementClass::computeRotationMatrix(R, X, *extra_normal); const Int natural_space = ElementClass::getNaturalSpaceDimension(); const Int nb_nodes = ElementClass::getNbNodesPerElement(); // Extracting relevant lines Matrix RX = R.block(0, 0, spatial_dimension, spatial_dimension) * X; auto x = RX.template block(0, 0); computeJacobianOnQuadPointsByElement(x, quad_points, J); if (filter_elements == empty_filter) { ++jacobians_it; if (has_extra_normal) { ++extra_normal; } } } } #endif /* -------------------------------------------------------------------------- */ #if defined(AKANTU_COHESIVE_ELEMENT) template <> template void IntegratorGauss<_ek_cohesive, DefaultIntegrationOrderFunctor>:: computeJacobiansOnIntegrationPoints( const Array & nodes, const Matrix & quad_points, Array & jacobians, GhostType ghost_type, const Array & filter_elements) const { auto spatial_dimension = mesh.getSpatialDimension(); auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type); auto nb_quadrature_points = quad_points.cols(); auto nb_element = mesh.getNbElement(type, ghost_type); jacobians.resize(nb_element * nb_quadrature_points); auto jacobians_begin = make_view(jacobians, nb_quadrature_points).begin(); Array x_el(0, spatial_dimension * nb_nodes_per_element); FEEngine::extractNodalToElementField(mesh, nodes, x_el, type, ghost_type, filter_elements); auto x_it = make_view(x_el, spatial_dimension, nb_nodes_per_element).begin(); auto nb_nodes_per_subelement = nb_nodes_per_element / 2; Matrix x(spatial_dimension, nb_nodes_per_subelement); nb_element = x_el.size(); Idx l_el = 0; auto compute = [&](const auto & el) { auto && J = jacobians_begin[el]; auto && X = x_it[l_el]; ++l_el; for (Int n = 0; n < nb_nodes_per_subelement; ++n) x(n) = (X(n) + X(n + nb_nodes_per_subelement)) / 2.; if (type == _cohesive_1d_2) { J(0) = 1; } else { this->computeJacobianOnQuadPointsByElement(x, quad_points, J); } }; for_each_element(nb_element, filter_elements, compute); } #endif /* -------------------------------------------------------------------------- */ template template void IntegratorGauss:: precomputeJacobiansOnQuadraturePoints(const Array & nodes, GhostType ghost_type) { auto & jacobians_tmp = jacobians.alloc(0, 1, type, ghost_type); this->computeJacobiansOnIntegrationPoints( nodes, quadrature_points(type, ghost_type), jacobians_tmp, ghost_type); } /* -------------------------------------------------------------------------- */ template template void IntegratorGauss::multiplyJacobiansByWeights( Array & jacobians, const Array & filter_elements) const { constexpr auto nb_quadrature_points = GaussIntegrationElement::getNbQuadraturePoints(); auto && weights = GaussIntegrationElement::getWeights(); auto && view = make_view(jacobians); if (filter_elements != empty_filter) { for (auto && J : filter(filter_elements, view)) J.array() *= weights.array(); } else { for (auto && J : view) J.array() *= weights.array(); } } /* -------------------------------------------------------------------------- */ template void IntegratorGauss::integrate( const Array & in_f, Array & intf, Int nb_degree_of_freedom, const Array & jacobians, Int nb_element) const { intf.resize(nb_element); if (nb_element == 0) { return; } auto nb_points = jacobians.size() / nb_element; for (auto && data : zip(make_view(in_f, nb_degree_of_freedom, nb_points), make_view(intf, nb_degree_of_freedom), make_view(jacobians, nb_points))) { + // MatrixProxy f() auto && f = std::get<0>(data); auto && int_f = std::get<1>(data); auto && J = std::get<2>(data); int_f = f * J; } } /* -------------------------------------------------------------------------- */ template template void IntegratorGauss::integrate( const Array & in_f, Array & intf, Int nb_degree_of_freedom, GhostType ghost_type, const Array & filter_elements) const { AKANTU_DEBUG_ASSERT(jacobians.exists(type, ghost_type), "No jacobians for the type " << jacobians.printType(type, ghost_type)); const auto & jac_loc = jacobians(type, ghost_type); if (filter_elements != empty_filter) { auto nb_element = filter_elements.size(); Array filtered_J(0, jac_loc.getNbComponent()); FEEngine::filterElementalData(mesh, jac_loc, filtered_J, type, ghost_type, filter_elements); this->integrate(in_f, intf, nb_degree_of_freedom, filtered_J, nb_element); } else { auto nb_element = mesh.getNbElement(type, ghost_type); this->integrate(in_f, intf, nb_degree_of_freedom, jac_loc, nb_element); } } /* -------------------------------------------------------------------------- */ template template void IntegratorGauss::integrate( const Array & in_f, Array & intf, Int nb_degree_of_freedom, GhostType ghost_type) const { auto quads = this->getIntegrationPoints(); Array jacobians; this->computeJacobiansOnIntegrationPoints(mesh.getNodes(), quads, jacobians, ghost_type); this->multiplyJacobiansByWeights(jacobians); this->integrate(in_f, intf, nb_degree_of_freedom, jacobians, mesh.getNbElement(type, ghost_type)); } /* -------------------------------------------------------------------------- */ template template Real IntegratorGauss::integrate( const Array & in_f, GhostType ghost_type) const { Array intfv(0, 1); integrate(in_f, intfv, 1, ghost_type); auto res = Math::reduce(intfv); return res; } /* -------------------------------------------------------------------------- */ template template Real IntegratorGauss::integrate( const Array & in_f, GhostType ghost_type, const Array & filter_elements) const { AKANTU_DEBUG_ASSERT(jacobians.exists(type, ghost_type), "No jacobians for the type " << jacobians.printType(type, ghost_type)); Array intfv(0, 1); integrate(in_f, intfv, 1, ghost_type, filter_elements); auto res = Math::reduce(intfv); return res; } /* -------------------------------------------------------------------------- */ template void IntegratorGauss:: integrateOnIntegrationPoints(const Array & in_f, Array & intf, Int nb_degree_of_freedom, const Array & jacobians, Int nb_element) const { auto nb_points = jacobians.size() / nb_element; intf.resize(nb_element * nb_points); auto J_it = jacobians.begin(); auto f_it = in_f.begin(nb_degree_of_freedom); auto inte_it = intf.begin(nb_degree_of_freedom); for (Idx el = 0; el < nb_element; ++el, ++J_it, ++f_it, ++inte_it) { const auto & J = *J_it; const auto & f = *f_it; auto & inte_f = *inte_it; inte_f = f; inte_f *= J; } } /* -------------------------------------------------------------------------- */ template template void IntegratorGauss:: integrateOnIntegrationPoints(const Array & in_f, Array & intf, Int nb_degree_of_freedom, GhostType ghost_type, const Array & filter_elements) const { AKANTU_DEBUG_ASSERT(jacobians.exists(type, ghost_type), "No jacobians for the type " << jacobians.printType(type, ghost_type)); const auto & jac_loc = this->jacobians(type, ghost_type); if (filter_elements != empty_filter) { auto nb_element = filter_elements.size(); auto filtered_J = std::make_shared>(0, jac_loc.getNbComponent()); FEEngine::filterElementalData(mesh, jac_loc, *filtered_J, type, ghost_type, filter_elements); this->integrateOnIntegrationPoints(in_f, intf, nb_degree_of_freedom, *filtered_J, nb_element); } else { auto nb_element = mesh.getNbElement(type, ghost_type); this->integrateOnIntegrationPoints(in_f, intf, nb_degree_of_freedom, jac_loc, nb_element); } } /* -------------------------------------------------------------------------- */ template template inline void IntegratorGauss::onElementsAddedByType( const Array & elements, GhostType ghost_type) { const auto & nodes = mesh.getNodes(); computeQuadraturePoints(ghost_type); if (not jacobians.exists(type, ghost_type)) { jacobians.alloc(0, 1, type, ghost_type); } this->computeJacobiansOnIntegrationPoints( nodes, quadrature_points(type, ghost_type), jacobians(type, ghost_type), type, ghost_type, elements); constexpr auto polynomial_degree = IntegrationOrderFunctor::template getOrder(); this->multiplyJacobiansByWeights( this->jacobians(type, ghost_type), elements); } /* -------------------------------------------------------------------------- */ template void IntegratorGauss::onElementsAdded( const Array & new_elements) { for (auto elements_range : MeshElementsByTypes(new_elements)) { auto type = elements_range.getType(); auto ghost_type = elements_range.getGhostType(); if (mesh.getSpatialDimension(type) != _spatial_dimension) { continue; } if (Mesh::getKind(type) != kind) { continue; } tuple_dispatch>( [&](auto && enum_type) { constexpr auto type = aka::decay_v; this->template onElementsAddedByType( elements_range.getElements(), ghost_type); }, type); } } /* -------------------------------------------------------------------------- */ template template inline void IntegratorGauss::initIntegrator( const Array & nodes, GhostType ghost_type) { computeQuadraturePoints(ghost_type); precomputeJacobiansOnQuadraturePoints(nodes, ghost_type); checkJacobians(ghost_type); constexpr auto polynomial_degree = IntegrationOrderFunctor::template getOrder(); multiplyJacobiansByWeights( this->jacobians(type, ghost_type)); } /* -------------------------------------------------------------------------- */ template inline void IntegratorGauss::initIntegrator( const Array & nodes, ElementType type, GhostType ghost_type) { tuple_dispatch>( [&](auto && enum_type) { constexpr auto type = aka::decay_v; this->template initIntegrator(nodes, ghost_type); }, type); } /* -------------------------------------------------------------------------- */ template void IntegratorGauss:: computeJacobiansOnIntegrationPoints( const Array & nodes, const Matrix & quad_points, Array & jacobians, ElementType type, GhostType ghost_type, const Array & filter_elements) const { tuple_dispatch>( [&](auto && enum_type) { constexpr auto type = aka::decay_v; this->template computeJacobiansOnIntegrationPoints( nodes, quad_points, jacobians, ghost_type, filter_elements); }, type); } } // namespace akantu