diff --git a/.gitlab-ci.d/templates.yaml b/.gitlab-ci.d/templates.yaml index e59c4ef9d..b65156cc2 100644 --- a/.gitlab-ci.d/templates.yaml +++ b/.gitlab-ci.d/templates.yaml @@ -1,135 +1,135 @@ # yaml-language-server: $format.enable=false, $schemaStore.enable=true, $schemas=gitlab-ci # Configuration template .configure: stage: configure variables: BLA_VENDOR: "Generic" CMAKE_GENERATOR: "Unix Makefiles" # CMAKE_GENERATOR: 'Ninja' script: # Create the build folder - cmake -E make_directory build - cd build - echo BUILD_TYPE=${BUILD_TYPE} # Configure the project - cmake -DAKANTU_COHESIVE_ELEMENT:BOOL=TRUE -DAKANTU_IMPLICIT:BOOL=TRUE -DAKANTU_PARALLEL:BOOL=TRUE -DAKANTU_STRUCTURAL_MECHANICS:BOOL=TRUE -DAKANTU_HEAT_TRANSFER:BOOL=TRUE -DAKANTU_DAMAGE_NON_LOCAL:BOOL=TRUE -DAKANTU_PHASE_FIELD:BOOL=TRUE -DAKANTU_PYTHON_INTERFACE:BOOL=TRUE -DAKANTU_CONTACT_MECHANICS:BOOL=TRUE -DAKANTU_EXAMPLES:BOOL=TRUE -DAKANTU_BUILD_ALL_EXAMPLES:BOOL=TRUE -DAKANTU_TESTS:BOOL=TRUE -DAKANTU_RUN_IN_DOCKER:BOOL=TRUE -DAKANTU_TEST_EXAMPLES:BOOL=${TEST_EXAMPLES} -DCMAKE_BUILD_TYPE:STRING=${BUILD_TYPE} -G "${CMAKE_GENERATOR}" .. # Copie the compile commands for the code quality - if [ -e compile_commands.json ]; then - cp compile_commands.json .. - fi artifacts: when: on_success paths: - build - compile_commands.json expire_in: 10h # Build the libraries .build_libs: stage: build_libs script: - echo BUILD_TYPE=${BUILD_TYPE} - - cmake --build build --target akantu -j1 + - cmake --build build --target akantu -j2 > >(tee -a build-${output}-out.log) 2> >(tee -a build-${output}-err.log >&2) - - cmake --build build --target py11_akantu -j1 + - cmake --build build --target py11_akantu -j2 > >(tee -a build-${output}-out.log) 2> >(tee -a build-${output}-err.log >&2) artifacts: when: on_success paths: - build/ - build-${output}-err.log - compile_commands.json expire_in: 10h # build the tests .build_tests: stage: build_tests script: - - cmake --build build -j1 + - cmake --build build -j2 > >(tee -a build-${output}-out.log) 2> >(tee -a build-${output}-err.log >&2) artifacts: when: on_success paths: - build/ - build-${output}-err.log - compile_commands.json exclude: - build/**/*.o expire_in: 10h # Build all .build_all: stage: build_libs script: - cmake --build build/src > >(tee -a build-${output}-out.log) 2> >(tee -a build-${output}-err.log >&2) - cmake --build build/python > >(tee -a build-${output}-out.log) 2> >(tee -a build-${output}-err.log >&2) - cmake --build build/test/ > >(tee -a build-${output}-out.log) 2> >(tee -a build-${output}-err.log >&2) - cmake --build build/examples > >(tee -a build-${output}-out.log) 2> >(tee -a build-${output}-err.log >&2) artifacts: when: on_success paths: - build/ - build-${output}-err.log - compile_commands.json exclude: - build/**/*.o expire_in: 10h # Run the tests .tests: stage: test script: - cd build - ctest -T test --output-on-failure --no-compress-output --timeout 1800 after_script: - cd build - tag=$(head -n 1 < Testing/TAG) - if [ -e Testing/${tag}/Test.xml ]; then - xsltproc -o ./juint.xml ${CI_PROJECT_DIR}/test/ci/ctest2junit.xsl Testing/${tag}/Test.xml; - fi - if [ ${BUILD_TYPE} = "Coverage" ]; then - gcovr --xml --gcov-executable "${GCOV_EXECUTABLE}" --output coverage.xml --object-directory ${CI_PROJECT_DIR}/build --root ${CI_PROJECT_DIR} -s || true - fi artifacts: when: always paths: - build/juint.xml - build/coverage.xml reports: junit: - build/juint.xml cobertura: - build/coverage.xml diff --git a/examples/cohesive_element/cohesive_extrinsic/cohesive_extrinsic.cc b/examples/cohesive_element/cohesive_extrinsic/cohesive_extrinsic.cc index 7177c8cab..6a4419271 100644 --- a/examples/cohesive_element/cohesive_extrinsic/cohesive_extrinsic.cc +++ b/examples/cohesive_element/cohesive_extrinsic/cohesive_extrinsic.cc @@ -1,129 +1,129 @@ /** * @file cohesive_extrinsic.cc * * @author Zineb Fouad * @author Nicolas Richart * @author Seyedeh Mohadeseh Taheri Mousavi * @author Marco Vocialta * * @date creation: Tue May 08 2012 * @date last modification: Wed Feb 06 2019 * * @brief Cohesive element examples in extrinsic * * * @section LICENSE * * Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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[]) { +int main(int argc, char *argv[]) { initialize("material.dat", argc, argv); const Int spatial_dimension = 2; - const UInt max_steps = 1000; + 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(); + 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(); + Array &position = mesh.getNodes(); + Array &velocity = model.getVelocity(); + Array &boundary = model.getBlockedDOFs(); + Array &displacement = model.getDisplacement(); - UInt nb_nodes = mesh.getNbNodes(); + 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 ae3fbfc39..e19bc4b06 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,154 +1,153 @@ /** * @file cohesive_extrinsic_ig_tg.cc * * @author Seyedeh Mohadeseh Taheri Mousavi * @author Marco Vocialta * * @date creation: Sun Oct 19 2014 * @date last modification: Tue Jan 19 2021 * * @brief Cohesive element examples in extrinsic with 2 different bulk * materials * * * @section LICENSE * * Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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) + 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 { + 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; + SolidMechanicsModel &model; Real vel, disp; }; /* -------------------------------------------------------------------------- */ -int main(int argc, char * argv[]) { +int main(int argc, char *argv[]) { initialize("material.dat", argc, argv); const Int spatial_dimension = 2; - const UInt max_steps = 1000; + 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(); + auto &¤t_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(); + 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))) { + 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 b7d043f80..d440dc143 100644 --- a/examples/cohesive_element/cohesive_intrinsic/cohesive_intrinsic.cc +++ b/examples/cohesive_element/cohesive_intrinsic/cohesive_intrinsic.cc @@ -1,139 +1,139 @@ /** * @file cohesive_intrinsic.cc * * @author Seyedeh Mohadeseh Taheri Mousavi * @author Marco Vocialta * * @date creation: Tue May 08 2012 * @date last modification: Fri Jul 19 2019 * * @brief Cohesive element example in intrinsic * * * @section LICENSE * * Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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[]) { +int main(int argc, char *argv[]) { initialize("material.dat", argc, argv); const Int spatial_dimension = 2; - const UInt max_steps = 350; + 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(); + Array &boundary = model.getBlockedDOFs(); - UInt nb_nodes = mesh.getNbNodes(); + 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"); + auto &&elements = mesh.createElementGroup("diplacement"); Vector barycenter(spatial_dimension); for_each_element( mesh, - [&](auto && el) { + [&](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(); +static void updateDisplacement(SolidMechanicsModelCohesive &model, + const ElementGroup &group, Real increment) { + Array &displacement = model.getDisplacement(); - for (auto && node : group.getNodeGroup().getNodes()) { + for (auto &&node : group.getNodeGroup().getNodes()) { displacement(node, 0) += increment; } } diff --git a/examples/explicit/explicit_dynamic.cc b/examples/explicit/explicit_dynamic.cc index ce3410cbc..05f00f1ae 100644 --- a/examples/explicit/explicit_dynamic.cc +++ b/examples/explicit/explicit_dynamic.cc @@ -1,110 +1,110 @@ /** * @file explicit_dynamic.cc * * @author Nicolas Richart * @author Seyedeh Mohadeseh Taheri Mousavi * * @date creation: Sun Oct 19 2014 * @date last modification: Thu Jan 28 2021 * * @brief Example of explicit dynamic simulation in solid mechanics * * * @section LICENSE * * Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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[]) { +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; - UInt max_steps = 1000; + 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(); + 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_static_2d.cc b/examples/heat_transfer/heat_transfer_static_2d.cc index 393c1a8d9..46fc1c406 100644 --- a/examples/heat_transfer/heat_transfer_static_2d.cc +++ b/examples/heat_transfer/heat_transfer_static_2d.cc @@ -1,95 +1,95 @@ /** * @file heat_transfer_static_2d.cc * * @author Nicolas Richart * * @date creation: Sun May 01 2011 * @date last modification: Fri Mar 16 2018 * * @brief Heat transfer model example in 2D * * * @section LICENSE * * Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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[]) { +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(); + const Array &nodes = mesh.getNodes(); + Array &blocked_dofs = model.getBlockedDOFs(); + Array &temperature = model.getTemperature(); double length = 1.; UInt 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 -= length / 4.; + 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/io/dumper/dumpable_interface.cc b/examples/io/dumper/dumpable_interface.cc index 4d85c93fb..17dc113d9 100644 --- a/examples/io/dumper/dumpable_interface.cc +++ b/examples/io/dumper/dumpable_interface.cc @@ -1,192 +1,192 @@ /** * @file dumpable_interface.cc * * @author Fabian Barras * @author Nicolas Richart * * @date creation: Mon Aug 17 2015 * @date last modification: Tue Sep 29 2020 * * @brief Example usnig the dumper interface directly * * * @section LICENSE * * Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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[]) { +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 = + 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 = + const Array &lnode_1 = (mesh.getElementGroup("lwheel_1")).getNodeGroup().getNodes(); - const Array & lnode_2 = + const Array &lnode_2 = (mesh.getElementGroup("lwheel_2")).getNodeGroup().getNodes(); - const Array & rnode_1 = + const Array &rnode_1 = (mesh.getElementGroup("rwheel_1")).getNodeGroup().getNodes(); - const Array & rnode_2 = + const Array &rnode_2 = (mesh.getElementGroup("rwheel_2")).getNodeGroup().getNodes(); - Array & node = mesh.getNodes(); - UInt nb_nodes = mesh.getNbNodes(); + 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"); + 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 = + 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"); + 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()); + ElementTypeMapArrayFilter filtered_colour(colour, + wheels_elements.getElements()); auto colour_field_wheel = - std::make_shared>( + 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.; UInt 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 00e010841..a18dc7b5f 100644 --- a/examples/io/dumper/dumper_low_level.cc +++ b/examples/io/dumper/dumper_low_level.cc @@ -1,200 +1,200 @@ /** * @file dumper_low_level.cc * * @author Fabian Barras * @author Nicolas Richart * * @date creation: Mon Aug 17 2015 * @date last modification: Tue Sep 29 2020 * * @brief Example using the low level dumper interface * * * @section LICENSE * * Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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[]) { +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(); - UInt nb_nodes = mesh.getNbNodes(); + 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 = + 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 = + const Array &lnode_1 = (mesh.getElementGroup("lwheel_1")).getNodeGroup().getNodes(); - const Array & lnode_2 = + const Array &lnode_2 = (mesh.getElementGroup("lwheel_2")).getNodeGroup().getNodes(); - const Array & rnode_1 = + const Array &rnode_1 = (mesh.getElementGroup("rwheel_1")).getNodeGroup().getNodes(); - const Array & rnode_2 = + 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; + 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); + 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()); + ElementTypeMapArrayFilter filtered_colour(colour, + wheels_elements.getElements()); auto colour_field_wheel = - std::make_shared>( + 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.; - UInt nb_steps = 100; + 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 1f0f6addb..f34b69173 100644 --- a/examples/io/dumper/locomotive_tools.cc +++ b/examples/io/dumper/locomotive_tools.cc @@ -1,92 +1,92 @@ /** * @file locomotive_tools.cc * * @author Fabian Barras * * @date creation: Mon Aug 17 2015 * @date last modification: Fri Feb 28 2020 * * @brief Small helper code for the dumper examples * * * @section LICENSE * * Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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) { +void applyRotation(const Vector ¢er, 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()); - Array::const_scalar_iterator node_num_it = node_group.begin(); - Array::const_scalar_iterator node_num_end = node_group.end(); + 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 = +void fillColour(const Mesh &mesh, ElementTypeMapArray &colour) { + const ElementTypeMapArray &phys_data = mesh.getData("physical_names"); - const Array & txt_colour = phys_data(_triangle_3); - Array & id_colour = colour(_triangle_3); + 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 cdf6d2c40..65effb69a 100644 --- a/examples/io/dumper/locomotive_tools.hh +++ b/examples/io/dumper/locomotive_tools.hh @@ -1,40 +1,40 @@ /** * @file locomotive_tools.hh * * @author Nicolas Richart * * @date creation: Fri Apr 13 2012 * @date last modification: Mon Aug 24 2015 * * @brief Header for the locomotive helper for the dumpers * * * @section LICENSE * * Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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> & center, +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::UInt> & node_group); + 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::UInt> & colour); +void fillColour(const ::akantu::Mesh &mesh, + ::akantu::ElementTypeMapArray<::akantu::Int> &colour); diff --git a/examples/new_material/local_material_damage.hh b/examples/new_material/local_material_damage.hh index 914d4f98e..d0c7faa87 100644 --- a/examples/new_material/local_material_damage.hh +++ b/examples/new_material/local_material_damage.hh @@ -1,119 +1,122 @@ /** * @file local_material_damage.hh * * @author Guillaume Anciaux * @author Marion Estelle Chambart * @author Nicolas Richart * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Sep 29 2020 * * @brief Material isotropic elastic * * * @section LICENSE * * Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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 = ""); + 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 - inline void computeStressOnQuad(Matrix & grad_u, Matrix & sigma, - Real & damage); + template + inline void computeStressOnQuad(Eigen::MatrixBase &grad_u, + Eigen::MatrixBase &sigma, Real &damage); /// compute the potential energy for on element - inline void computePotentialEnergyOnQuad(Matrix & grad_u, - Matrix & sigma, Real & epot); + 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; + 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 07cda0f77..cad8a1b70 100644 --- a/examples/new_material/local_material_damage_inline_impl.hh +++ b/examples/new_material/local_material_damage_inline_impl.hh @@ -1,92 +1,93 @@ /** * @file local_material_damage_inline_impl.hh * * @author Guillaume Anciaux * @author Marion Estelle Chambart * @author Nicolas Richart * * @date creation: Wed Aug 04 2010 * @date last modification: Tue Sep 29 2020 * * @brief Implementation of the inline functions of the material damage * * * @section LICENSE * * Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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 { /* -------------------------------------------------------------------------- */ -inline void LocalMaterialDamage::computeStressOnQuad(Matrix & grad_u, - Matrix & sigma, - Real & dam) { +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( - Matrix & grad_u, Matrix & sigma, Real & epot) { + 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 { + 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 4fed0215b..4f09dff99 100644 --- a/examples/new_material/new_local_material.cc +++ b/examples/new_material/new_local_material.cc @@ -1,104 +1,104 @@ /** * @file new_local_material.cc * * @author Guillaume Anciaux * @author Marion Estelle Chambart * @author Nicolas Richart * * @date creation: Wed Aug 04 2010 * @date last modification: Wed Jan 15 2020 * * @brief test of the class SolidMechanicsModel * * * @section LICENSE * * Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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[]) { +int main(int argc, char *argv[]) { akantu::initialize("material.dat", argc, argv); - UInt max_steps = 10000; + 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 eeb38e04a..f1fa2184a 100644 --- a/examples/new_material/viscoelastic_maxwell/material_viscoelastic_maxwell_energies.cc +++ b/examples/new_material/viscoelastic_maxwell/material_viscoelastic_maxwell_energies.cc @@ -1,179 +1,179 @@ /** * @file material_viscoelastic_maxwell_energies.cc * * @author Emil Gallyamov * * @date creation: Tue Nov 20 2018 * @date last modification: Sun Dec 30 2018 * * @brief Example of using viscoelastic material and computing energies * * * @section LICENSE * * Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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[]) { +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); + Material &mat = model.getMaterial(0); Real time_step = 0.1; - UInt nb_nodes = mesh.getNbNodes(); - const Array & coordinate = mesh.getNodes(); - Array & displacement = model.getDisplacement(); - Array & blocked = model.getBlockedDOFs(); + Int nb_nodes = mesh.getNbNodes(); + 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"); - UInt max_steps = sim_time / time_step + 1; + Int max_steps = sim_time / time_step + 1; Real time = 0.; - auto & solver = model.getNonLinearSolver(); + 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 (Int n = 0; n < nb_nodes; ++n) { if (Math::are_float_equal(coordinate(n, 0), 0.0)) { displacement(n, 0) = 0; blocked(n, 0) = true; displacement(n, 1) = epsilon * coordinate(n, 1); blocked(n, 1) = true; } else if (Math::are_float_equal(coordinate(n, 1), 0.0)) { displacement(n, 0) = epsilon * coordinate(n, 0); blocked(n, 0) = true; displacement(n, 1) = 0; blocked(n, 1) = true; } else if (Math::are_float_equal(coordinate(n, 0), 0.001)) { displacement(n, 0) = epsilon * coordinate(n, 0); blocked(n, 0) = true; displacement(n, 1) = epsilon * coordinate(n, 1); blocked(n, 1) = true; } else if (Math::are_float_equal(coordinate(n, 1), 0.001)) { displacement(n, 0) = epsilon * coordinate(n, 0); blocked(n, 0) = true; displacement(n, 1) = epsilon * coordinate(n, 1); blocked(n, 1) = true; } } try { model.solveStep(); - } catch (debug::Exception & e) { + } catch (debug::Exception &e) { } // for debugging // auto int_force = model.getInternalForce(); // auto &K = model.getDOFManager().getMatrix("K"); // K.saveMatrix("K.mtx"); Int nb_iter = solver.get("nb_iterations"); Real error = solver.get("error"); bool converged = solver.get("converged"); if (converged) { std::cout << "Converged in " << nb_iter << " iterations" << std::endl; } else { std::cout << "Didn't converge after " << nb_iter << " iterations. Error is " << error << std::endl; return EXIT_FAILURE; } 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 1eab05725..d511c0e59 100644 --- a/examples/parallel/parallel_2d.cc +++ b/examples/parallel/parallel_2d.cc @@ -1,108 +1,108 @@ /** * @file parallel_2d.cc * * @author Nicolas Richart * * @date creation: Mon Aug 09 2010 * @date last modification: Thu Mar 22 2018 * * @brief Parallel example * * * @section LICENSE * * Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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[]) { +int main(int argc, char *argv[]) { initialize("material.dat", argc, argv); Int spatial_dimension = 2; - UInt max_steps = 10000; + Int max_steps = 10000; Real time_factor = 0.8; Real max_disp = 1e-6; Mesh mesh(spatial_dimension); - const auto & comm = Communicator::getStaticCommunicator(); + 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(); + 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/structural_mechanics/bernoulli_beam_2_example.cc b/examples/structural_mechanics/bernoulli_beam_2_example.cc index be255f5c3..ce60ca9d1 100644 --- a/examples/structural_mechanics/bernoulli_beam_2_example.cc +++ b/examples/structural_mechanics/bernoulli_beam_2_example.cc @@ -1,142 +1,142 @@ /** * @file bernoulli_beam_2_example.cc * * @author Fabian Barras * * @date creation: Fri Jul 15 2011 * @date last modification: Mon Mar 15 2021 * * @brief Computation of the analytical exemple 1.1 in the TGC vol 6 * * * @section LICENSE * * Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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[]) { +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(); + Array &nodes = mesh_accessor.getNodes(); nodes.resize(nb_nodes); beams.addConnectivityType(_bernoulli_beam_2); - Array & connectivity = mesh_accessor.getConnectivity(_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 &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); + 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/packages/core.cmake b/packages/core.cmake index 1793a72c8..41ee388ba 100644 --- a/packages/core.cmake +++ b/packages/core.cmake @@ -1,444 +1,444 @@ #=============================================================================== # @file core.cmake # # @author Guillaume Anciaux # @author Nicolas Richart # # @date creation: Mon Nov 21 2011 # @date last modification: Fri Apr 09 2021 # # @brief package description for core # # # @section LICENSE # # Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # 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 . # #=============================================================================== package_declare(core NOT_OPTIONAL DESCRIPTION "core package for Akantu" FEATURES_PUBLIC cxx_strong_enums cxx_defaulted_functions cxx_deleted_functions cxx_auto_type cxx_decltype_auto FEATURES_PRIVATE cxx_lambdas cxx_nullptr cxx_range_for cxx_delegating_constructors DEPENDS INTERFACE akantu_iterators Boost Eigen3 ) if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") package_set_compile_flags(core CXX "-Wall -Wextra -pedantic") else() package_set_compile_flags(core CXX "-Wall") endif() if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.0.0) package_set_compile_flags(core CXX "-Wall -Wextra -pedantic -Wno-attributes") endif() if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.9)) - package_set_compile_flags(core CXX "-Wall -Wextra -pedantic -Wno-undefined-var-template") + package_set_compile_flags(core CXX "-Wall -Wextra -pedantic -Wno-undefined-var-template -Wno-unknown-attributes") endif() package_declare_sources(core common/aka_array.cc common/aka_array.hh common/aka_array_filter.hh common/aka_array_tmpl.hh common/aka_array_printer.hh common/aka_bbox.hh common/aka_blas_lapack.hh common/aka_circular_array.hh common/aka_circular_array_inline_impl.hh common/aka_common.cc common/aka_common.hh common/aka_common_inline_impl.hh common/aka_csr.hh common/aka_element_classes_info_inline_impl.hh common/aka_enum_macros.hh common/aka_error.cc common/aka_error.hh common/aka_event_handler_manager.hh common/aka_extern.cc common/aka_factory.hh common/aka_fwd.hh common/aka_grid_dynamic.hh common/aka_math.cc common/aka_math.hh common/aka_math_tmpl.hh common/aka_named_argument.hh common/aka_random_generator.hh common/aka_safe_enum.hh common/aka_tensor.hh common/aka_types.hh common/aka_types_eigen_matrix_plugin.hh common/aka_types_eigen_matrix_base_plugin.hh common/aka_types_eigen_plain_object_base_plugin.hh common/aka_view_iterators.hh common/aka_voigthelper.hh common/aka_voigthelper_tmpl.hh common/aka_voigthelper.cc common/aka_warning.hh common/aka_warning_restore.hh fe_engine/element_class.hh fe_engine/element_class_helper.hh fe_engine/element_class_tmpl.hh fe_engine/element_classes/element_class_hexahedron_8_inline_impl.hh fe_engine/element_classes/element_class_hexahedron_20_inline_impl.hh fe_engine/element_classes/element_class_pentahedron_6_inline_impl.hh fe_engine/element_classes/element_class_pentahedron_15_inline_impl.hh fe_engine/element_classes/element_class_point_1_inline_impl.hh fe_engine/element_classes/element_class_quadrangle_4_inline_impl.hh fe_engine/element_classes/element_class_quadrangle_8_inline_impl.hh fe_engine/element_classes/element_class_segment_2_inline_impl.hh fe_engine/element_classes/element_class_segment_3_inline_impl.hh fe_engine/element_classes/element_class_tetrahedron_10_inline_impl.hh fe_engine/element_classes/element_class_tetrahedron_4_inline_impl.hh fe_engine/element_classes/element_class_triangle_3_inline_impl.hh fe_engine/element_classes/element_class_triangle_6_inline_impl.hh fe_engine/element_type_conversion.hh fe_engine/fe_engine.cc fe_engine/fe_engine.hh fe_engine/fe_engine_inline_impl.hh fe_engine/fe_engine_template.hh fe_engine/fe_engine_template_tmpl_field.hh fe_engine/fe_engine_template_tmpl.hh fe_engine/geometrical_element_property.hh fe_engine/geometrical_element_property.cc fe_engine/gauss_integration.cc fe_engine/gauss_integration_tmpl.hh fe_engine/integrator.hh fe_engine/integrator_gauss.hh fe_engine/integrator_gauss_inline_impl.hh fe_engine/interpolation_element_tmpl.hh fe_engine/integration_point.hh fe_engine/shape_functions.hh fe_engine/shape_functions.cc fe_engine/shape_functions_inline_impl.hh fe_engine/shape_lagrange_base.cc fe_engine/shape_lagrange_base.hh fe_engine/shape_lagrange_base_inline_impl.hh fe_engine/shape_lagrange.hh fe_engine/shape_lagrange_inline_impl.hh fe_engine/element.hh io/dumper/dumpable.hh io/dumper/dumpable.cc io/dumper/dumpable_dummy.hh io/dumper/dumpable_inline_impl.hh io/dumper/dumper_field.hh io/dumper/dumper_material_padders.hh io/dumper/dumper_filtered_connectivity.hh io/dumper/dumper_element_partition.hh io/mesh_io.cc io/mesh_io.hh io/mesh_io/mesh_io_diana.cc io/mesh_io/mesh_io_diana.hh io/mesh_io/mesh_io_msh.cc io/mesh_io/mesh_io_msh.hh #io/model_io.cc #io/model_io.hh io/parser/algebraic_parser.hh io/parser/input_file_parser.hh io/parser/parsable.cc io/parser/parsable.hh io/parser/parser.cc io/parser/parser_real.cc io/parser/parser_random.cc io/parser/parser_types.cc io/parser/parser_input_files.cc io/parser/parser.hh io/parser/parser_tmpl.hh io/parser/parser_grammar_tmpl.hh io/parser/cppargparse/cppargparse.hh io/parser/cppargparse/cppargparse.cc io/parser/cppargparse/cppargparse_tmpl.hh io/parser/parameter_registry.cc io/parser/parameter_registry.hh io/parser/parameter_registry_tmpl.hh mesh/element_group.cc mesh/element_group.hh mesh/element_group_inline_impl.hh mesh/element_type_map.cc mesh/element_type_map.hh mesh/element_type_map_tmpl.hh mesh/element_type_map_filter.hh mesh/group_manager.cc mesh/group_manager.hh mesh/group_manager_inline_impl.hh mesh/mesh.cc mesh/mesh.hh mesh/mesh_periodic.cc mesh/mesh_accessor.hh mesh/mesh_events.hh mesh/mesh_filter.hh mesh/mesh_global_data_updater.hh mesh/mesh_data.cc mesh/mesh_data.hh mesh/mesh_data_tmpl.hh mesh/mesh_inline_impl.hh mesh/node_group.cc mesh/node_group.hh mesh/node_group_inline_impl.hh mesh/mesh_iterators.hh mesh_utils/mesh_partition.cc mesh_utils/mesh_partition.hh mesh_utils/mesh_partition/mesh_partition_mesh_data.cc mesh_utils/mesh_partition/mesh_partition_mesh_data.hh mesh_utils/mesh_partition/mesh_partition_scotch.hh mesh_utils/mesh_utils_pbc.cc mesh_utils/mesh_utils.cc mesh_utils/mesh_utils.hh mesh_utils/mesh_utils_distribution.cc mesh_utils/mesh_utils_distribution.hh mesh_utils/mesh_utils.hh mesh_utils/mesh_utils_inline_impl.hh mesh_utils/global_ids_updater.hh mesh_utils/global_ids_updater.cc mesh_utils/global_ids_updater_inline_impl.hh model/common/boundary_condition/boundary_condition.hh model/common/boundary_condition/boundary_condition_functor.hh model/common/boundary_condition/boundary_condition_functor_inline_impl.hh model/common/boundary_condition/boundary_condition_tmpl.hh model/common/non_local_toolbox/neighborhood_base.hh model/common/non_local_toolbox/neighborhood_base.cc model/common/non_local_toolbox/neighborhood_base_inline_impl.hh model/common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.hh model/common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc model/common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion_inline_impl.hh model/common/non_local_toolbox/non_local_manager.hh model/common/non_local_toolbox/non_local_manager.cc model/common/non_local_toolbox/non_local_manager_inline_impl.hh model/common/non_local_toolbox/non_local_manager_callback.hh model/common/non_local_toolbox/non_local_neighborhood_base.hh model/common/non_local_toolbox/non_local_neighborhood_base.cc model/common/non_local_toolbox/non_local_neighborhood.hh model/common/non_local_toolbox/non_local_neighborhood_tmpl.hh model/common/non_local_toolbox/non_local_neighborhood_inline_impl.hh model/common/non_local_toolbox/base_weight_function.hh model/common/non_local_toolbox/base_weight_function.cc model/common/non_local_toolbox/base_weight_function_inline_impl.hh model/common/model_solver.cc model/common/model_solver.hh model/common/solver_callback.hh model/common/solver_callback.cc model/common/dof_manager/dof_manager.cc model/common/dof_manager/dof_manager.hh model/common/dof_manager/dof_manager_default.cc model/common/dof_manager/dof_manager_default.hh model/common/dof_manager/dof_manager_default_inline_impl.hh model/common/dof_manager/dof_manager_inline_impl.hh model/common/non_linear_solver/non_linear_solver.cc model/common/non_linear_solver/non_linear_solver.hh model/common/non_linear_solver/non_linear_solver_default.hh model/common/non_linear_solver/non_linear_solver_lumped.cc model/common/non_linear_solver/non_linear_solver_lumped.hh model/common/time_step_solvers/time_step_solver.hh model/common/time_step_solvers/time_step_solver.cc model/common/time_step_solvers/time_step_solver_default.cc model/common/time_step_solvers/time_step_solver_default.hh model/common/time_step_solvers/time_step_solver_default_explicit.hh model/common/integration_scheme/generalized_trapezoidal.cc model/common/integration_scheme/generalized_trapezoidal.hh model/common/integration_scheme/integration_scheme.cc model/common/integration_scheme/integration_scheme.hh model/common/integration_scheme/integration_scheme_1st_order.cc model/common/integration_scheme/integration_scheme_1st_order.hh model/common/integration_scheme/integration_scheme_2nd_order.cc model/common/integration_scheme/integration_scheme_2nd_order.hh model/common/integration_scheme/newmark-beta.cc model/common/integration_scheme/newmark-beta.hh model/common/integration_scheme/pseudo_time.cc model/common/integration_scheme/pseudo_time.hh model/model.cc model/model.hh model/model_inline_impl.hh model/model_options.hh solver/solver_vector.hh solver/solver_vector_default.hh solver/solver_vector_default_tmpl.hh solver/solver_vector_distributed.cc solver/solver_vector_distributed.hh solver/sparse_matrix.cc solver/sparse_matrix.hh solver/sparse_matrix_aij.cc solver/sparse_matrix_aij.hh solver/sparse_matrix_aij_inline_impl.hh solver/sparse_matrix_inline_impl.hh solver/sparse_solver.cc solver/sparse_solver.hh solver/sparse_solver_inline_impl.hh solver/terms_to_assemble.hh synchronizer/communication_buffer_inline_impl.hh synchronizer/communication_descriptor.hh synchronizer/communication_descriptor_tmpl.hh synchronizer/communication_request.hh synchronizer/communication_tag.hh synchronizer/communications.hh synchronizer/communications_tmpl.hh synchronizer/communicator.cc synchronizer/communicator.hh synchronizer/communicator_dummy_inline_impl.hh synchronizer/communicator_event_handler.hh synchronizer/communicator_inline_impl.hh synchronizer/data_accessor.cc synchronizer/data_accessor.hh synchronizer/dof_synchronizer.cc synchronizer/dof_synchronizer.hh synchronizer/dof_synchronizer_inline_impl.hh synchronizer/element_info_per_processor.cc synchronizer/element_info_per_processor.hh synchronizer/element_info_per_processor_tmpl.hh synchronizer/element_synchronizer.cc synchronizer/element_synchronizer.hh synchronizer/facet_synchronizer.cc synchronizer/facet_synchronizer.hh synchronizer/facet_synchronizer_inline_impl.hh synchronizer/grid_synchronizer.cc synchronizer/grid_synchronizer.hh synchronizer/grid_synchronizer_tmpl.hh synchronizer/master_element_info_per_processor.cc synchronizer/node_info_per_processor.cc synchronizer/node_info_per_processor.hh synchronizer/node_synchronizer.cc synchronizer/node_synchronizer.hh synchronizer/node_synchronizer_inline_impl.hh synchronizer/periodic_node_synchronizer.cc synchronizer/periodic_node_synchronizer.hh synchronizer/slave_element_info_per_processor.cc synchronizer/synchronizer.cc synchronizer/synchronizer.hh synchronizer/synchronizer_impl.hh synchronizer/synchronizer_impl_tmpl.hh synchronizer/synchronizer_registry.cc synchronizer/synchronizer_registry.hh synchronizer/synchronizer_tmpl.hh synchronizer/communication_buffer.hh ) set(AKANTU_SPIRIT_SOURCES io/mesh_io/mesh_io_abaqus.cc io/parser/parser_real.cc io/parser/parser_random.cc io/parser/parser_types.cc io/parser/parser_input_files.cc PARENT_SCOPE ) package_declare_elements(core ELEMENT_TYPES _point_1 _segment_2 _segment_3 _triangle_3 _triangle_6 _quadrangle_4 _quadrangle_8 _tetrahedron_4 _tetrahedron_10 _pentahedron_6 _pentahedron_15 _hexahedron_8 _hexahedron_20 KIND regular GEOMETRICAL_TYPES _gt_point _gt_segment_2 _gt_segment_3 _gt_triangle_3 _gt_triangle_6 _gt_quadrangle_4 _gt_quadrangle_8 _gt_tetrahedron_4 _gt_tetrahedron_10 _gt_hexahedron_8 _gt_hexahedron_20 _gt_pentahedron_6 _gt_pentahedron_15 INTERPOLATION_TYPES _itp_lagrange_point_1 _itp_lagrange_segment_2 _itp_lagrange_segment_3 _itp_lagrange_triangle_3 _itp_lagrange_triangle_6 _itp_lagrange_quadrangle_4 _itp_serendip_quadrangle_8 _itp_lagrange_tetrahedron_4 _itp_lagrange_tetrahedron_10 _itp_lagrange_hexahedron_8 _itp_serendip_hexahedron_20 _itp_lagrange_pentahedron_6 _itp_lagrange_pentahedron_15 GEOMETRICAL_SHAPES _gst_point _gst_triangle _gst_square _gst_prism GAUSS_INTEGRATION_TYPES _git_point _git_segment _git_triangle _git_tetrahedron _git_pentahedron INTERPOLATION_KIND _itk_lagrangian FE_ENGINE_LISTS gradient_on_integration_points interpolate_on_integration_points interpolate compute_normals_on_integration_points inverse_map contains compute_shapes compute_shapes_derivatives get_N compute_dnds compute_d2nds2 compute_jmat get_shapes_derivatives lagrange_base assemble_fields ) find_program(READLINK_COMMAND readlink) find_program(ADDR2LINE_COMMAND addr2line) find_program(PATCH_COMMAND patch) mark_as_advanced(READLINK_COMMAND) mark_as_advanced(ADDR2LINE_COMMAND) package_declare_extra_files_to_package(core SOURCES common/aka_element_classes_info.hh.in common/aka_config.hh.in ) diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 4c76a6e89..f03678e28 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -1,144 +1,149 @@ #=============================================================================== # @file CMakeLists.txt # # @author Guillaume Anciaux # @author Nicolas Richart # # @date creation: Fri Dec 12 2014 # @date last modification: Fri May 07 2021 # # @brief CMake file for the python wrapping of akantu # # # @section LICENSE # # Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # 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 . # #=============================================================================== set(PYBIND11_PYTHON_VERSION ${AKANTU_PREFERRED_PYTHON_VERSION} CACHE INTERNAL "") if(NOT SKBUILD) package_get_all_include_directories( AKANTU_LIBRARY_INCLUDE_DIRS ) package_get_all_external_informations( PRIVATE_INCLUDE AKANTU_PRIVATE_EXTERNAL_INCLUDE_DIR INTERFACE_INCLUDE AKANTU_INTERFACE_EXTERNAL_INCLUDE_DIR LIBRARIES AKANTU_EXTERNAL_LIBRARIES ) endif() set(PYAKANTU_SRCS py_aka_common.cc py_aka_error.cc py_akantu.cc py_boundary_conditions.cc py_dof_manager.cc py_fe_engine.cc py_group_manager.cc py_mesh.cc py_model.cc py_parser.cc py_solver.cc py_dumpable.cc ) package_is_activated(solid_mechanics _is_activated) if (_is_activated) list(APPEND PYAKANTU_SRCS py_solid_mechanics_model.cc py_material.cc py_material_selector.cc ) endif() package_is_activated(cohesive_element _is_activated) if (_is_activated) list(APPEND PYAKANTU_SRCS py_solid_mechanics_model_cohesive.cc py_fragment_manager.cc ) endif() package_is_activated(heat_transfer _is_activated) if (_is_activated) list(APPEND PYAKANTU_SRCS py_heat_transfer_model.cc ) endif() package_is_activated(contact_mechanics _is_activated) if(_is_activated) list(APPEND PYAKANTU_SRCS py_contact_mechanics_model.cc py_model_couplers.cc ) endif() package_is_activated(phase_field _is_activated) if (_is_activated) list(APPEND PYAKANTU_SRCS py_phase_field_model.cc ) endif() package_is_activated(structural_mechanics _is_activated) if (_is_activated) list(APPEND PYAKANTU_SRCS py_structural_mechanics_model.cc ) endif() pybind11_add_module(py11_akantu ${PYAKANTU_SRCS}) # to avoid compilation warnings from pybind11 target_include_directories(py11_akantu SYSTEM BEFORE PRIVATE ${PYBIND11_INCLUDE_DIR} PRIVATE ${pybind11_INCLUDE_DIR} PRIVATE ${Python_INCLUDE_DIRS}) target_link_libraries(py11_akantu PUBLIC akantu) set_target_properties(py11_akantu PROPERTIES DEBUG_POSTFIX "" LIBRARY_OUTPUT_DIRECTORY akantu) +if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + target_compile_options(py11_akantu PUBLIC -fsized-deallocation) +endif() + + file(COPY akantu DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) if(NOT Python_MAJOR) set(Python_VERSION_MAJOR ${PYTHON_VERSION_MAJOR}) set(Python_VERSION_MINOR ${PYTHON_VERSION_MINOR}) endif() if(NOT SKBUILD) set(_python_install_dir ${CMAKE_INSTALL_LIBDIR}/python${Python_VERSION_MAJOR}.${Python_VERSION_MINOR}/site-packages/akantu) else() set(_python_install_dir python/akantu) endif() install(TARGETS py11_akantu LIBRARY DESTINATION ${_python_install_dir}) if(NOT SKBUILD) install(DIRECTORY akantu DESTINATION ${_python_install_dir} FILES_MATCHING PATTERN "*.py") endif() diff --git a/src/common/aka_math.hh b/src/common/aka_math.hh index 3ca8766b1..46ab379da 100644 --- a/src/common/aka_math.hh +++ b/src/common/aka_math.hh @@ -1,173 +1,169 @@ /** * @file aka_math.hh * * @author Ramin Aghababaei * @author Guillaume Anciaux * @author Marion Estelle Chambart * @author David Simon Kammer * @author Daniel Pino Muñoz * @author Nicolas Richart * @author Leonardo Snozzi * @author Peter Spijker * @author Marco Vocialta * * @date creation: Wed Aug 04 2010 * @date last modification: Tue Feb 09 2021 * * @brief mathematical operations * * * @section LICENSE * * Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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_types.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #ifndef AKANTU_AKA_MATH_H_ #define AKANTU_AKA_MATH_H_ namespace akantu { /* -------------------------------------------------------------------------- */ namespace Math { - /// tolerance for functions that need one - extern Real tolerance; // NOLINT - - /* ------------------------------------------------------------------------ */ - /* Geometry */ - /* ------------------------------------------------------------------------ */ - /// compute normal a normal to a vector - template ::value> * = nullptr> - inline Vector normal(const Eigen::MatrixBase & vec); - - template ::value> * = nullptr> - inline Vector normal(const Eigen::MatrixBase & /*vec*/) { - AKANTU_TO_IMPLEMENT(); - } - - /// compute normal a normal to a vector - template ::value> * = nullptr> - inline Vector normal(const Eigen::MatrixBase & vec1, - const Eigen::MatrixBase & vec2); - - /// compute the tangents to an array of normal vectors - void compute_tangents(const Array & normals, Array & tangents); - - /// radius of the in-circle of a triangle in 2d space - template - static constexpr inline Real - triangle_inradius(const Eigen::MatrixBase & coord1, - const Eigen::MatrixBase & coord2, - const Eigen::MatrixBase & coord3); - - /// radius of the in-circle of a tetrahedron - template - static constexpr inline Real - tetrahedron_inradius(const Eigen::MatrixBase & coord1, - const Eigen::MatrixBase & coord2, - const Eigen::MatrixBase & coord3, - const Eigen::MatrixBase & coord4); - /// volume of a tetrahedron - template - static constexpr inline Real - tetrahedron_volume(const Eigen::MatrixBase & coord1, - const Eigen::MatrixBase & coord2, - const Eigen::MatrixBase & coord3, - const Eigen::MatrixBase & coord4); - - /// compute the barycenter of n points - template - inline void barycenter(const Eigen::MatrixBase & coord, - Eigen::MatrixBase & barycenter); - - /// test if two scalar are equal within a given tolerance - inline bool are_float_equal(Real x, Real y); - - /// test if two vectors are equal within a given tolerance - inline bool are_vector_equal(Int n, Real * x, Real * y); +/// tolerance for functions that need one +extern Real tolerance; // NOLINT + +/* ------------------------------------------------------------------------ */ +/* Geometry */ +/* ------------------------------------------------------------------------ */ +/// compute normal a normal to a vector +template ::value> * = nullptr> +inline Vector normal(const Eigen::MatrixBase &vec); + +template ::value> * = nullptr> +inline Vector normal(const Eigen::MatrixBase & /*vec*/) { + AKANTU_TO_IMPLEMENT(); +} + +/// compute normal a normal to a vector +template ::value> * = nullptr> +inline Vector normal(const Eigen::MatrixBase &vec1, + const Eigen::MatrixBase &vec2); + +/// compute the tangents to an array of normal vectors +void compute_tangents(const Array &normals, Array &tangents); + +/// radius of the in-circle of a triangle in 2d space +template +static inline Real triangle_inradius(const Eigen::MatrixBase &coord1, + const Eigen::MatrixBase &coord2, + const Eigen::MatrixBase &coord3); + +/// radius of the in-circle of a tetrahedron +template +static inline Real tetrahedron_inradius(const Eigen::MatrixBase &coord1, + const Eigen::MatrixBase &coord2, + const Eigen::MatrixBase &coord3, + const Eigen::MatrixBase &coord4); +/// volume of a tetrahedron +template +static inline Real tetrahedron_volume(const Eigen::MatrixBase &coord1, + const Eigen::MatrixBase &coord2, + const Eigen::MatrixBase &coord3, + const Eigen::MatrixBase &coord4); + +/// compute the barycenter of n points +template +inline void barycenter(const Eigen::MatrixBase &coord, + Eigen::MatrixBase &barycenter); + +/// test if two scalar are equal within a given tolerance +inline bool are_float_equal(Real x, Real y); + +/// test if two vectors are equal within a given tolerance +inline bool are_vector_equal(Int n, Real *x, Real *y); #ifdef isnan #error \ "You probably included which is incompatible with aka_math please use\ or add a \"#undef isnan\" before akantu includes" #endif - /// test if a real is a NaN - inline bool isnan(Real x); +/// test if a real is a NaN +inline bool isnan(Real x); - /// test if the line x and y intersects each other - inline bool intersects(Real x_min, Real x_max, Real y_min, Real y_max); +/// test if the line x and y intersects each other +inline bool intersects(Real x_min, Real x_max, Real y_min, Real y_max); - /// test if a is in the range [x_min, x_max] - inline bool is_in_range(Real a, Real x_min, Real x_max); +/// test if a is in the range [x_min, x_max] +inline bool is_in_range(Real a, Real x_min, Real x_max); - inline Real getTolerance() { return Math::tolerance; } - inline void setTolerance(Real tol) { Math::tolerance = tol; } +inline Real getTolerance() { return Math::tolerance; } +inline void setTolerance(Real tol) { Math::tolerance = tol; } - template inline T pow(T x); +template inline T pow(T x); - template ::value and - std::is_integral::value> * = nullptr> - inline Real kronecker(T1 i, T2 j) { - return static_cast(i == j); - } - /* -------------------------------------------------------------------------- - */ - template static inline constexpr T pow(T x, int p) { - return p == 0 ? T(1) : (pow(x, p - 1) * x); - } +template ::value and + std::is_integral::value> * = nullptr> +inline Real kronecker(T1 i, T2 j) { + return static_cast(i == j); +} +/* -------------------------------------------------------------------------- + */ +template static inline constexpr T pow(T x, int p) { + return p == 0 ? T(1) : (pow(x, p - 1) * x); +} - /// reduce all the values of an array, the summation is done in place and the - /// array is modified - Real reduce(Array & array); +/// reduce all the values of an array, the summation is done in place and the +/// array is modified +Real reduce(Array &array); - template class NewtonRaphson { - public: - NewtonRaphson(Real tolerance, Int max_iteration) - : tolerance(tolerance), max_iteration(max_iteration) {} +template class NewtonRaphson { +public: + NewtonRaphson(Real tolerance, Int max_iteration) + : tolerance(tolerance), max_iteration(max_iteration) {} - template T solve(const Functor & funct, const T & x_0); + template T solve(const Functor &funct, const T &x_0); - private: - Real tolerance; - Int max_iteration; - }; +private: + Real tolerance; + Int max_iteration; +}; - template struct NewtonRaphsonFunctor { - explicit NewtonRaphsonFunctor(const std::string & name) : name(name) {} +template struct NewtonRaphsonFunctor { + explicit NewtonRaphsonFunctor(const std::string &name) : name(name) {} - virtual T f(const T & x) const = 0; - virtual T f_prime(const T & x) const = 0; + virtual T f(const T &x) const = 0; + virtual T f_prime(const T &x) const = 0; - std::string name; - }; + std::string name; +}; } // namespace Math } // namespace akantu /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "aka_math_tmpl.hh" #endif /* AKANTU_AKA_MATH_H_ */ diff --git a/src/common/aka_math_tmpl.hh b/src/common/aka_math_tmpl.hh index 27e801822..ba5f7cb33 100644 --- a/src/common/aka_math_tmpl.hh +++ b/src/common/aka_math_tmpl.hh @@ -1,241 +1,238 @@ /** * @file aka_math_tmpl.hh * * @author Ramin Aghababaei * @author Guillaume Anciaux * @author Alejandro M. Aragón * @author Emil Gallyamov * @author David Simon Kammer * @author Daniel Pino Muñoz * @author Mohit Pundir * @author Mathilde Radiguet * @author Nicolas Richart * @author Leonardo Snozzi * @author Peter Spijker * @author Marco Vocialta * * @date creation: Wed Aug 04 2010 * @date last modification: Fri Dec 11 2020 * * @brief Implementation of the inline functions of the math toolkit * * * @section LICENSE * * Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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_blas_lapack.hh" #include "aka_math.hh" #include "aka_types.hh" /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ namespace akantu { namespace Math { - /* ------------------------------------------------------------------------ */ - template ::value> *> - inline Vector normal(const Eigen::MatrixBase & vec) { - Vector normal_; - AKANTU_DEBUG_ASSERT(vec.cols() == 1 and vec.rows() == 2, - "Vec is not of the proper size"); - Vector vec_(vec); - normal_[0] = vec_[1]; - normal_[1] = -vec_[0]; - normal_ /= normal_.norm(); - return normal_; +/* ------------------------------------------------------------------------ */ +template ::value> *> +inline Vector normal(const Eigen::MatrixBase &vec) { + Vector normal_; + AKANTU_DEBUG_ASSERT(vec.cols() == 1 and vec.rows() == 2, + "Vec is not of the proper size"); + Vector vec_(vec); + normal_[0] = vec_[1]; + normal_[1] = -vec_[0]; + normal_ /= normal_.norm(); + return normal_; +} + +/* ------------------------------------------------------------------------ */ +template *> +inline Vector normal(const Eigen::MatrixBase &vec1, + const Eigen::MatrixBase &vec2) { + AKANTU_DEBUG_ASSERT(vec1.cols() == 1 and vec1.rows() == 3, + "Vec is not of the proper size"); + AKANTU_DEBUG_ASSERT(vec2.cols() == 1 and vec2.rows() == 3, + "Vec is not of the proper size"); + Vector vec1_(vec1); + Vector vec2_(vec2); + auto &&normal = vec1_.cross(vec2_); + normal /= normal.norm(); + return normal.eval(); +} + +/* ------------------------------------------------------------------------ */ +template +inline Real triangle_inradius(const Eigen::MatrixBase &coord1, + const Eigen::MatrixBase &coord2, + const Eigen::MatrixBase &coord3) { + auto a = coord1.distance(coord2); + auto b = coord2.distance(coord3); + auto c = coord1.distance(coord3); + + auto s = (a + b + c) / 2.; + + return std::sqrt((s - a) * (s - b) * (s - c) / s); +} + +/* ------------------------------------------------------------------------ */ +template +inline Real tetrahedron_volume(const Eigen::MatrixBase &coord1, + const Eigen::MatrixBase &coord2, + const Eigen::MatrixBase &coord3, + const Eigen::MatrixBase &coord4) { + Matrix xx; + + xx.col(0) = coord2; + xx.col(1) = coord3; + xx.col(2) = coord4; + auto vol = xx.determinant(); + + xx.col(0) = coord1; + vol -= xx.determinant(); + + xx.col(1) = coord2; + vol += xx.determinant(); + + xx.col(2) = coord3; + vol -= xx.determinant(); + + vol /= 6; + + return vol; +} + +/* ------------------------------------------------------------------------ */ +template +inline Real tetrahedron_inradius(const Eigen::MatrixBase &coord1, + const Eigen::MatrixBase &coord2, + const Eigen::MatrixBase &coord3, + const Eigen::MatrixBase &coord4) { + auto l12 = coord1.distance(coord2); + auto l13 = coord1.distance(coord3); + auto l14 = coord1.distance(coord4); + auto l23 = coord2.distance(coord3); + auto l24 = coord2.distance(coord4); + auto l34 = coord3.distance(coord4); + + auto s1 = (l12 + l23 + l13) * 0.5; + s1 = std::sqrt(s1 * (s1 - l12) * (s1 - l23) * (s1 - l13)); + + auto s2 = (l12 + l24 + l14) * 0.5; + s2 = std::sqrt(s2 * (s2 - l12) * (s2 - l24) * (s2 - l14)); + + auto s3 = (l23 + l34 + l24) * 0.5; + s3 = std::sqrt(s3 * (s3 - l23) * (s3 - l34) * (s3 - l24)); + + auto s4 = (l13 + l34 + l14) * 0.5; + s4 = std::sqrt(s4 * (s4 - l13) * (s4 - l34) * (s4 - l14)); + + auto volume = Math::tetrahedron_volume(coord1, coord2, coord3, coord4); + + return 3 * volume / (s1 + s2 + s3 + s4); +} + +/* ------------------------------------------------------------------------ */ +template +inline void barycenter(const Eigen::MatrixBase &coord, + Eigen::MatrixBase &barycenter) { + barycenter.zero(); + for (auto &&x : coord) { + barycenter += x; } - - /* ------------------------------------------------------------------------ */ - template *> - inline Vector normal(const Eigen::MatrixBase & vec1, - const Eigen::MatrixBase & vec2) { - AKANTU_DEBUG_ASSERT(vec1.cols() == 1 and vec1.rows() == 3, - "Vec is not of the proper size"); - AKANTU_DEBUG_ASSERT(vec2.cols() == 1 and vec2.rows() == 3, - "Vec is not of the proper size"); - Vector vec1_(vec1); - Vector vec2_(vec2); - auto && normal = vec1_.cross(vec2_); - normal /= normal.norm(); - return normal.eval(); - } - - /* ------------------------------------------------------------------------ */ - template - constexpr inline Real - triangle_inradius(const Eigen::MatrixBase & coord1, - const Eigen::MatrixBase & coord2, - const Eigen::MatrixBase & coord3) { - auto a = coord1.distance(coord2); - auto b = coord2.distance(coord3); - auto c = coord1.distance(coord3); - - auto s = (a + b + c) / 2.; - - return std::sqrt((s - a) * (s - b) * (s - c) / s); - } - - /* ------------------------------------------------------------------------ */ - template - constexpr inline Real - tetrahedron_volume(const Eigen::MatrixBase & coord1, - const Eigen::MatrixBase & coord2, - const Eigen::MatrixBase & coord3, - const Eigen::MatrixBase & coord4) { - Matrix xx; - - xx.col(0) = coord2; - xx.col(1) = coord3; - xx.col(2) = coord4; - auto vol = xx.determinant(); - - xx.col(0) = coord1; - vol -= xx.determinant(); - - xx.col(1) = coord2; - vol += xx.determinant(); - - xx.col(2) = coord3; - vol -= xx.determinant(); - - vol /= 6; - - return vol; - } - - /* ------------------------------------------------------------------------ */ - template - constexpr inline Real - tetrahedron_inradius(const Eigen::MatrixBase & coord1, - const Eigen::MatrixBase & coord2, - const Eigen::MatrixBase & coord3, - const Eigen::MatrixBase & coord4) { - auto l12 = coord1.distance(coord2); - auto l13 = coord1.distance(coord3); - auto l14 = coord1.distance(coord4); - auto l23 = coord2.distance(coord3); - auto l24 = coord2.distance(coord4); - auto l34 = coord3.distance(coord4); - - auto s1 = (l12 + l23 + l13) * 0.5; - s1 = std::sqrt(s1 * (s1 - l12) * (s1 - l23) * (s1 - l13)); - - auto s2 = (l12 + l24 + l14) * 0.5; - s2 = std::sqrt(s2 * (s2 - l12) * (s2 - l24) * (s2 - l14)); - - auto s3 = (l23 + l34 + l24) * 0.5; - s3 = std::sqrt(s3 * (s3 - l23) * (s3 - l34) * (s3 - l24)); - - auto s4 = (l13 + l34 + l14) * 0.5; - s4 = std::sqrt(s4 * (s4 - l13) * (s4 - l34) * (s4 - l14)); - - auto volume = Math::tetrahedron_volume(coord1, coord2, coord3, coord4); - - return 3 * volume / (s1 + s2 + s3 + s4); - } - - /* ------------------------------------------------------------------------ */ - template - inline void barycenter(const Eigen::MatrixBase & coord, - Eigen::MatrixBase & barycenter) { - barycenter.zero(); - for (auto && x : coord) { - barycenter += x; - } - barycenter /= (Real)coord.cols(); - } - - /* ------------------------------------------------------------------------ */ - /// Combined absolute and relative tolerance test proposed in - /// Real-time collision detection by C. Ericson (2004) - inline bool are_float_equal(const Real x, const Real y) { - Real abs_max = std::max(std::abs(x), std::abs(y)); - abs_max = std::max(abs_max, Real(1.)); - return std::abs(x - y) <= (tolerance * abs_max); - } - - /* ------------------------------------------------------------------------ */ - inline bool isnan(Real x) { + barycenter /= (Real)coord.cols(); +} + +/* ------------------------------------------------------------------------ */ +/// Combined absolute and relative tolerance test proposed in +/// Real-time collision detection by C. Ericson (2004) +inline bool are_float_equal(const Real x, const Real y) { + Real abs_max = std::max(std::abs(x), std::abs(y)); + abs_max = std::max(abs_max, Real(1.)); + return std::abs(x - y) <= (tolerance * abs_max); +} + +/* ------------------------------------------------------------------------ */ +inline bool isnan(Real x) { #if defined(__INTEL_COMPILER) #pragma warning(push) #pragma warning(disable : 1572) #endif // defined(__INTEL_COMPILER) - // x = x return false means x = quiet_NaN - return !(x == x); + // x = x return false means x = quiet_NaN + return !(x == x); #if defined(__INTEL_COMPILER) #pragma warning(pop) #endif // defined(__INTEL_COMPILER) - } +} - /* ------------------------------------------------------------------------ */ - inline bool are_vector_equal(Int n, Real * x, Real * y) { - bool test = true; - for (Int i = 0; i < n; ++i) { - test &= are_float_equal(x[i], y[i]); - } - - return test; +/* ------------------------------------------------------------------------ */ +inline bool are_vector_equal(Int n, Real *x, Real *y) { + bool test = true; + for (Int i = 0; i < n; ++i) { + test &= are_float_equal(x[i], y[i]); } - /* ------------------------------------------------------------------------ */ - inline bool intersects(Real x_min, Real x_max, Real y_min, Real y_max) { - return not((x_max < y_min) or (x_min > y_max)); + return test; +} + +/* ------------------------------------------------------------------------ */ +inline bool intersects(Real x_min, Real x_max, Real y_min, Real y_max) { + return not((x_max < y_min) or (x_min > y_max)); +} + +/* ------------------------------------------------------------------------ */ +inline bool is_in_range(Real a, Real x_min, Real x_max) { + return ((a >= x_min) and (a <= x_max)); +} + +/* ------------------------------------------------------------------------ */ +template inline T pow(T x) { + return (pow

(x) * x); +} +template <> inline Int pow<0, Int>(Int /*x*/) { return (1); } +template <> inline Real pow<0, Real>(Real /*x*/) { return (1.); } + +/* ------------------------------------------------------------------------ */ +template +template +T NewtonRaphson::solve(const Functor &funct, const T &x_0) { + T x = x_0; + T f_x = funct.f(x); + Int iter = 0; + while (std::abs(f_x) > this->tolerance && iter < this->max_iteration) { + x -= f_x / funct.f_prime(x); + f_x = funct.f(x); + iter++; } - /* ------------------------------------------------------------------------ */ - inline bool is_in_range(Real a, Real x_min, Real x_max) { - return ((a >= x_min) and (a <= x_max)); - } + AKANTU_DEBUG_ASSERT(iter < this->max_iteration, + "Newton Raphson (" + << funct.name << ") solve did not converge in " + << this->max_iteration << " iterations (tolerance: " + << this->tolerance << ")"); - /* ------------------------------------------------------------------------ */ - template inline T pow(T x) { - return (pow

(x) * x); - } - template <> inline Int pow<0, Int>(Int /*x*/) { return (1); } - template <> inline Real pow<0, Real>(Real /*x*/) { return (1.); } - - /* ------------------------------------------------------------------------ */ - template - template - T NewtonRaphson::solve(const Functor & funct, const T & x_0) { - T x = x_0; - T f_x = funct.f(x); - Int iter = 0; - while (std::abs(f_x) > this->tolerance && iter < this->max_iteration) { - x -= f_x / funct.f_prime(x); - f_x = funct.f(x); - iter++; - } - - AKANTU_DEBUG_ASSERT(iter < this->max_iteration, - "Newton Raphson (" - << funct.name << ") solve did not converge in " - << this->max_iteration << " iterations (tolerance: " - << this->tolerance << ")"); - - return x; - } + return x; +} } // namespace Math } // namespace akantu diff --git a/src/common/aka_tensor.hh b/src/common/aka_tensor.hh index 61746d601..854221b0b 100644 --- a/src/common/aka_tensor.hh +++ b/src/common/aka_tensor.hh @@ -1,462 +1,458 @@ /** * @file aka_tensor.hh * * @author Nicolas Richart * * @date creation dim jan 23 2022 * * @brief A Documented file. * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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 AKA_TENSOR_HH_ #define AKA_TENSOR_HH_ namespace akantu { /* -------------------------------------------------------------------------- */ /* TensorBase */ /* -------------------------------------------------------------------------- */ template class TensorBase : public TensorTrait { using RetType = TensorBase; static_assert(ndim > 2, "TensorBase cannot by used for dimensions < 3"); protected: using idx_t = Idx; template using valid_args_t = typename std::enable_if< aka::conjunction, std::is_enum>...>::value and ndim == sizeof...(Args), int>::type; public: using proxy = TensorBase; using size_type = Idx; template = 0> TensorBase() { n.fill(0); } TensorBase() { n.fill(0); } template = 0> constexpr TensorBase(Args... args) : n{idx_t(args)...}, _size(detail::product_all(args...)) {} - constexpr TensorBase(const TensorBase & other) + constexpr TensorBase(const TensorBase &other) : n(other.n), _size(other._size), values(other.values) {} - constexpr TensorBase(TensorBase && other) noexcept + constexpr TensorBase(TensorBase &&other) noexcept : n(std::move(other.n)), _size(std::exchange(other._size, 0)), values(std::exchange(other.values, nullptr)) {} protected: template constexpr auto check_indices( - const Array & idx, + const Array &idx, std::integer_sequence /* for_template_deduction */) const { bool result = true; (void)std::initializer_list{(result &= idx[I] < n[I], 0)...}; return result; } template constexpr auto compute_index(Args... args) const { std::array idx{idx_t(args)...}; - AKANTU_DEBUG_ASSERT( - check_indices(idx, - std::make_integer_sequence{}), - "The indexes are out of bound"); + assert(check_indices( + idx, std::make_integer_sequence{}) && + "The indexes are out of bound"); idx_t index = 0, i = (sizeof...(Args)) - 1; for (; i > 0; i--) { index += idx[i]; if (i > 0) { index *= n[i - 1]; } } return index + idx[0]; } template constexpr auto get_slice(idx_t s, std::index_sequence) { return S(this->values + s * detail::product_all(n[I]...), n[I]...); } template constexpr auto get_slice(idx_t s, std::index_sequence) const { return S(this->values + s * detail::product_all(n[I]...), n[I]...); } public: template = 0> inline auto operator()(Args... args) -> T & { return *(this->values + compute_index(std::move(args)...)); } template = 0> inline auto operator()(Args... args) const -> const T & { return *(this->values + compute_index(std::move(args)...)); } template < class R = T, idx_t _ndim = ndim, std::enable_if_t<(_ndim > 3) and not std::is_const::value> * = nullptr> inline auto operator()(idx_t s) { return get_slice>( s, std::make_index_sequence()); } template 3)> * = nullptr> inline auto operator()(idx_t s) const { return get_slice>( s, std::make_index_sequence()); } template ::value> * = nullptr> inline auto operator()(idx_t s) { return get_slice< Eigen::Map>>( s, std::make_index_sequence()); } template * = nullptr> inline auto operator()(idx_t s) const { return get_slice, Eigen::Dynamic, Eigen::Dynamic>>>( s, std::make_index_sequence()); } protected: - template auto transform(Operator && op) -> RetType & { + template auto transform(Operator &&op) -> RetType & { std::transform(this->values, this->values + this->_size, this->values, std::forward(op)); return *(static_cast(this)); } template - auto transform(Other && other, Operator && op) -> RetType & { + auto transform(Other &&other, Operator &&op) -> RetType & { AKANTU_DEBUG_ASSERT(_size == other.size(), "The two tensors do not have the same size " << this->_size << " != " << other._size); std::transform(this->values, this->values + this->_size, other.values, this->values, std::forward(op)); return *(static_cast(this)); } - template auto accumulate(T init, Operator && op) -> T { + template auto accumulate(T init, Operator &&op) -> T { return std::accumulate(this->values, this->values + this->_size, std::move(init), std::forward(op)); } template - auto transform_reduce(Other && other, T init, Accumulate && acc, - Operator && op) -> T { + auto transform_reduce(Other &&other, T init, Accumulate &&acc, Operator &&op) + -> T { return std::inner_product( this->values, this->values + this->_size, other.data(), std::move(init), std::forward(acc), std::forward(op)); } // element wise arithmetic operators ----------------------------------------- public: - inline decltype(auto) operator+=(const TensorBase & other) { - return transform(other, [](auto && a, auto && b) { return a + b; }); + inline decltype(auto) operator+=(const TensorBase &other) { + return transform(other, [](auto &&a, auto &&b) { return a + b; }); } /* ------------------------------------------------------------------------ */ - inline auto operator-=(const TensorBase & other) -> TensorBase & { - return transform(other, [](auto && a, auto && b) { return a - b; }); + inline auto operator-=(const TensorBase &other) -> TensorBase & { + return transform(other, [](auto &&a, auto &&b) { return a - b; }); } /* ------------------------------------------------------------------------ */ - inline auto operator+=(const T & x) -> TensorBase & { - return transform([&x](auto && a) { return a + x; }); + inline auto operator+=(const T &x) -> TensorBase & { + return transform([&x](auto &&a) { return a + x; }); } /* ------------------------------------------------------------------------ */ - inline auto operator-=(const T & x) -> TensorBase & { - return transform([&x](auto && a) { return a - x; }); + inline auto operator-=(const T &x) -> TensorBase & { + return transform([&x](auto &&a) { return a - x; }); } /* ------------------------------------------------------------------------ */ - inline auto operator*=(const T & x) -> TensorBase & { - return transform([&x](auto && a) { return a * x; }); + inline auto operator*=(const T &x) -> TensorBase & { + return transform([&x](auto &&a) { return a * x; }); } /* ---------------------------------------------------------------------- */ - inline auto operator/=(const T & x) -> TensorBase & { - return transform([&x](auto && a) { return a / x; }); + inline auto operator/=(const T &x) -> TensorBase & { + return transform([&x](auto &&a) { return a / x; }); } /// Y = \alpha X + Y - inline auto aXplusY(const TensorBase & other, const T alpha = 1.) + inline auto aXplusY(const TensorBase &other, const T alpha = 1.) -> TensorBase & { return transform(other, - [&alpha](auto && a, auto && b) { return alpha * a + b; }); + [&alpha](auto &&a, auto &&b) { return alpha * a + b; }); } /* ------------------------------------------------------------------------ */ auto data() -> T * { return values; } auto data() const -> const T * { return values; } // clang-format off [[deprecated("use data instead to be stl compatible")]] auto storage() -> T*{ return values; } [[deprecated("use data instead to be stl compatible")]] auto storage() const -> const T * { return values; } // clang-format on auto size() const { return _size; } auto size(idx_t i) const { AKANTU_DEBUG_ASSERT(i < ndim, "This tensor has only " << ndim << " dimensions, not " << (i + 1)); return n[i]; }; - inline void set(const T & t) { std::fill_n(values, _size, t); }; + inline void set(const T &t) { std::fill_n(values, _size, t); }; inline void clear() { set(T()); }; public: /// "Entrywise" norm norm @f[ \|\boldsymbol{T}\|_p = \left( /// \sum_i^{n[0]}\sum_j^{n[1]}\sum_k^{n[2]} |T_{ijk}|^p \right)^{\frac{1}{p}} /// @f] template * = nullptr> auto lpNorm() const -> T { - return accumulate( - T(), [](auto && init, auto && a) { return init + std::abs(a); }); + return accumulate(T(), + [](auto &&init, auto &&a) { return init + std::abs(a); }); } template * = nullptr> auto lpNorm() const -> T { - return accumulate(T(), [](auto && init, auto && a) { - return std::max(init, std::abs(a)); - }); + return accumulate( + T(), [](auto &&init, auto &&a) { return std::max(init, std::abs(a)); }); } template * = nullptr> auto norm() const -> T { return std::sqrt( - accumulate(T(), [](auto && init, auto && a) { return init + a * a; })); + accumulate(T(), [](auto &&init, auto &&a) { return init + a * a; })); } template 2)> * = nullptr> auto norm() const -> T { - return std::pow(accumulate(T(), - [](auto && init, auto && a) { - return init + std::pow(a, norm_type); - }), - 1. / norm_type); + return std::pow( + accumulate(T(), [](auto &&init, + auto &&a) { return init + std::pow(a, norm_type); }), + 1. / norm_type); } auto norm() const -> T { return lpNorm<2>(); } protected: template = 0> - void serialize(std::ostream & stream, Args... args) const { + void serialize(std::ostream &stream, Args... args) const { stream << this->operator()(std::move(args)...); } template = 0> - void serialize(std::ostream & stream, Args... args) const { + void serialize(std::ostream &stream, Args... args) const { stream << "["; for (idx_t i = 0; i < n[N]; ++i) { if (i != 0) { stream << ","; } serialize(stream, std::move(args)..., i); } stream << "]"; } public: - void printself(std::ostream & stream) const { serialize<0>(stream); }; + void printself(std::ostream &stream) const { serialize<0>(stream); }; protected: template constexpr decltype(auto) begin(std::index_sequence) { return view_iterator>(values, n[I]...); } template constexpr decltype(auto) end(std::index_sequence) { return view_iterator>(values + _size, n[I]...); } template constexpr decltype(auto) begin(std::index_sequence) const { return const_view_iterator>(values, n[I]...); } template constexpr decltype(auto) end(std::index_sequence) const { return const_view_iterator>( values + _size, n[I]...); } public: decltype(auto) begin() { return begin(std::make_index_sequence{}); } decltype(auto) end() { return end(std::make_index_sequence{}); } decltype(auto) begin() const { return begin(std::make_index_sequence{}); } decltype(auto) end() const { return end(std::make_index_sequence{}); } protected: // size per dimension std::array n; // total storage size idx_t _size{0}; // actual data location - T * values{nullptr}; + T *values{nullptr}; }; /* -------------------------------------------------------------------------- */ /* TensorProxy */ /* -------------------------------------------------------------------------- */ template class TensorProxy : public TensorBase { private: using parent = TensorBase; public: // proxy constructor template - constexpr TensorProxy(T * data, Args... args) : parent(args...) { + constexpr TensorProxy(T *data, Args... args) : parent(args...) { this->values = data; } - constexpr TensorProxy(const TensorProxy & other) : parent(other) { + constexpr TensorProxy(const TensorProxy &other) : parent(other) { this->values = other.values; } - constexpr TensorProxy(const Tensor & other) : parent(other) { + constexpr TensorProxy(const Tensor &other) : parent(other) { this->values = other.values; } // move constructors --------------------------------------------------------- // proxy -> proxy - TensorProxy(TensorProxy && other) noexcept : parent(other) {} + TensorProxy(TensorProxy &&other) noexcept : parent(other) {} - auto operator=(const TensorBase & other) -> TensorProxy & { + auto operator=(const TensorBase &other) -> TensorProxy & { AKANTU_DEBUG_ASSERT( other.size() == this->size(), "You are trying to copy too a tensors proxy with the wrong size " << this->_size << " != " << other._size); static_assert(std::is_trivially_copyable{}, "Cannot copy a tensor on non trivial types"); std::copy(other.values, other.values + this->_size, this->values); return *this; } }; /* -------------------------------------------------------------------------- */ /* Tensor */ /* -------------------------------------------------------------------------- */ template class Tensor : public TensorBase { private: using parent = TensorBase; public: template constexpr Tensor(Args... args) : parent(args...) { static_assert( std::is_trivially_constructible{}, "Cannot create a tensor on non trivially constructible types"); this->values = new T[this->_size]; } /* ------------------------------------------------------------------------ */ virtual ~Tensor() { delete[] this->values; } // copy constructors --------------------------------------------------------- - constexpr Tensor(const Tensor & other) : parent(other) { + constexpr Tensor(const Tensor &other) : parent(other) { this->values = new T[this->_size]; std::copy(other.values, other.values + this->_size, this->values); } - constexpr explicit Tensor(const TensorProxy & other) - : parent(other) { + constexpr explicit Tensor(const TensorProxy &other) : parent(other) { // static_assert(false, "Copying data are you sure"); this->values = new T[this->_size]; std::copy(other.values, other.values + this->_size, this->values); } // move constructors --------------------------------------------------------- // proxy -> proxy, non proxy -> non proxy - Tensor(Tensor && other) noexcept : parent(other) {} + Tensor(Tensor &&other) noexcept : parent(other) {} // copy operator ------------------------------------------------------------- /// operator= copy-and-swap - auto operator=(const TensorBase & other) -> Tensor & { + auto operator=(const TensorBase &other) -> Tensor & { if (&other == this) return *this; std::cout << "Warning: operator= delete data" << std::endl; delete[] this->values; this->n = other.n; this->_size = other._size; static_assert( std::is_trivially_constructible{}, "Cannot create a tensor on non trivially constructible types"); this->values = new T[this->_size]; static_assert(std::is_trivially_copyable{}, "Cannot copy a tensor on non trivial types"); std::copy(other.values, other.values + this->_size, this->values); return *this; } }; /* -------------------------------------------------------------------------- */ template using Tensor3 = Tensor; template using Tensor3Proxy = TensorProxy; template using Tensor3Base = TensorBase; } // namespace akantu #endif // AKA_TENSOR_HH_ diff --git a/src/common/aka_types.hh b/src/common/aka_types.hh index a180e5f2e..105e6c110 100644 --- a/src/common/aka_types.hh +++ b/src/common/aka_types.hh @@ -1,536 +1,523 @@ /** * @file aka_types.hh * * @author Nicolas Richart * * @date creation: Thu Feb 17 2011 * @date last modification: Wed Dec 09 2020 * * @brief description of the "simple" types * * * @section LICENSE * * Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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_compatibilty_with_cpp_standard.hh" #include "aka_error.hh" /* -------------------------------------------------------------------------- */ #include #include #include #include #include #ifndef AKANTU_AKA_TYPES_HH #define AKANTU_AKA_TYPES_HH -namespace Eigen { -template -struct Map; - -template -struct Matrix; - -template struct MatrixBase; - -} // namespace Eigen - /* -------------------------------------------------------------------------- */ +#define EIGEN_DEFAULT_DENSE_INDEX_TYPE akantu::Idx +#define EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION Eigen::ColMajor +#define EIGEN_DEFAULT_IO_FORMAT \ + Eigen::IOFormat(Eigen::StreamPrecision, Eigen::DontAlignCols, ", ", ", ", \ + "[", "]", "[", "]") +/* -------------------------------------------------------------------------- */ +#define EIGEN_MATRIXBASE_PLUGIN "aka_types_eigen_matrix_base_plugin.hh" +#define EIGEN_MATRIX_PLUGIN "aka_types_eigen_matrix_plugin.hh" +#define EIGEN_PLAINOBJECTBASE_PLUGIN \ + "aka_types_eigen_plain_object_base_plugin.hh" +#include +#include +/* -------------------------------------------------------------------------- */ + namespace aka { template struct is_eigen_map : public std::false_type {}; template struct is_eigen_map> : public std::true_type {}; /* -------------------------------------------------------------------------- */ template struct is_eigen_matrix : public std::false_type {}; template struct is_eigen_matrix< Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>> : public std::true_type {}; /* -------------------------------------------------------------------------- */ template struct is_eigen_matrix_base : public std::false_type {}; template struct is_eigen_matrix_base> : public std::true_type {}; } // namespace aka -#define EIGEN_DEFAULT_DENSE_INDEX_TYPE akantu::Idx -#define EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION Eigen::ColMajor -#define EIGEN_DEFAULT_IO_FORMAT \ - Eigen::IOFormat(Eigen::StreamPrecision, Eigen::DontAlignCols, ", ", ", ", \ - "[", "]", "[", "]") -/* -------------------------------------------------------------------------- */ -#define EIGEN_MATRIXBASE_PLUGIN "aka_types_eigen_matrix_base_plugin.hh" -#define EIGEN_MATRIX_PLUGIN "aka_types_eigen_matrix_plugin.hh" -#define EIGEN_PLAINOBJECTBASE_PLUGIN \ - "aka_types_eigen_plain_object_base_plugin.hh" -#include -#include -/* -------------------------------------------------------------------------- */ - namespace akantu { using Eigen::Ref; template using Vector = Eigen::Matrix; template using Matrix = Eigen::Matrix; template using VectorProxy = Eigen::Map::value, const Vector, n>, Vector, n>>>; template using MatrixProxy = Eigen::Map::value, const Matrix, m, n>, Matrix, m, n>>>; using VectorXr = Vector; using MatrixXr = Matrix; enum NormType : int8_t { L_1 = 1, L_2 = 2, L_inf = -1 }; struct TensorTraitBase {}; template struct TensorTrait : public TensorTraitBase {}; } // namespace akantu namespace aka { template using is_vector = aka::bool_constant< std::remove_reference_t>::IsVectorAtCompileTime>; template using is_matrix = aka::negation>; template using are_vectors = aka::conjunction...>; template using are_matrices = aka::conjunction...>; template using enable_if_matrices_t = std::enable_if_t::value>; template using enable_if_vectors_t = std::enable_if_t::value>; /* -------------------------------------------------------------------------- */ template struct is_tensor : public std::is_base_of {}; template struct is_tensor> : public std::true_type {}; template struct is_tensor> : public std::true_type {}; template struct is_tensor> : public std::true_type {}; template using is_tensor_n = std::is_base_of, T>; template using enable_if_tensors_n = std::enable_if< aka::conjunction< is_tensor_n..., std::is_same< std::common_type_t...>, std::decay_t>...>::value, T>; template using enable_if_tensors_n_t = typename enable_if_tensors_n::type; } // namespace aka namespace akantu { // fwd declaration template class TensorBase; template class TensorProxy; template class Tensor; } // namespace akantu /* -------------------------------------------------------------------------- */ #include "aka_view_iterators.hh" /* -------------------------------------------------------------------------- */ #include "aka_tensor.hh" /* -------------------------------------------------------------------------- */ namespace akantu { class ArrayBase; /* -------------------------------------------------------------------------- */ namespace details { - template struct MapPlainObjectType { using type = T; }; - - template - struct MapPlainObjectType< - Eigen::Map> { - using type = PlainObjectType; - }; - - template - using MapPlainObjectType_t = typename MapPlainObjectType::type; - - template struct EigenMatrixViewHelper {}; - - template - struct EigenMatrixViewHelper { - using type = Eigen::Matrix; - }; - - template - struct EigenMatrixViewHelper { - using type = Eigen::Matrix; - }; - - template - using EigenMatrixViewHelper_t = - typename EigenMatrixViewHelper::type; - - template class EigenView { - static_assert(sizeof...(sizes) == 1 or sizeof...(sizes) == 2, - "Eigen only supports Vector and Matrices"); - - public: - using size_type = typename std::decay_t::size_type; - using value_type = typename std::decay_t::value_type; - - EigenView(Array && array, decltype(sizes)... sizes_) - : array(array), sizes_(sizes_...) {} - - EigenView(Array && array) : array(array), sizes_(sizes...) {} - - EigenView(const EigenView & other) = default; - EigenView(EigenView && other) noexcept = default; - - auto operator=(const EigenView & other) -> EigenView & = default; - auto operator=(EigenView && other) noexcept -> EigenView & = default; - - template ().data())>, - std::enable_if_t::value> * = nullptr> - decltype(auto) begin() { - return aka::make_from_tuple<::akantu::view_iterator< - Eigen::Map>>>( - std::tuple_cat(std::make_tuple(array.get().data()), sizes_)); - } - - template ().data())>, - std::enable_if_t::value> * = nullptr> - decltype(auto) end() { - return aka::make_from_tuple<::akantu::view_iterator< - Eigen::Map>>>( - std::tuple_cat(std::make_tuple(array.get().data() + array_size()), - sizes_)); - } - - decltype(auto) begin() const { - return aka::make_from_tuple<::akantu::view_iterator< - Eigen::Map>>>( - std::tuple_cat(std::make_tuple(array.get().data()), sizes_)); - } - decltype(auto) end() const { - return aka::make_from_tuple<::akantu::view_iterator< - Eigen::Map>>>( - std::tuple_cat(std::make_tuple(array.get().data() + array_size()), - sizes_)); - } - - private: - template < - class A = Array, - std::enable_if_t>::value> * = - nullptr> - auto array_size() { - return array.get().size() * array.get().getNbComponent(); - } - - template >::value> * = nullptr> - auto array_size() { - return array.get().size(); - } - - private: - std::reference_wrapper> array; - std::tuple sizes_; - }; +template struct MapPlainObjectType { using type = T; }; + +template +struct MapPlainObjectType> { + using type = PlainObjectType; +}; + +template +using MapPlainObjectType_t = typename MapPlainObjectType::type; + +template struct EigenMatrixViewHelper {}; + +template +struct EigenMatrixViewHelper { + using type = Eigen::Matrix; +}; + +template +struct EigenMatrixViewHelper { + using type = Eigen::Matrix; +}; + +template +using EigenMatrixViewHelper_t = + typename EigenMatrixViewHelper::type; + +template class EigenView { + static_assert(sizeof...(sizes) == 1 or sizeof...(sizes) == 2, + "Eigen only supports Vector and Matrices"); + +public: + using size_type = typename std::decay_t::size_type; + using value_type = typename std::decay_t::value_type; + + EigenView(Array &&array, decltype(sizes)... sizes_) + : array(array), sizes_(sizes_...) {} + + EigenView(Array &&array) : array(array), sizes_(sizes...) {} + + EigenView(const EigenView &other) = default; + EigenView(EigenView &&other) noexcept = default; + + auto operator=(const EigenView &other) -> EigenView & = default; + auto operator=(EigenView &&other) noexcept -> EigenView & = default; + + template ().data())>, + std::enable_if_t::value> * = nullptr> + decltype(auto) begin() { + return aka::make_from_tuple<::akantu::view_iterator< + Eigen::Map>>>( + std::tuple_cat(std::make_tuple(array.get().data()), sizes_)); + } + + template ().data())>, + std::enable_if_t::value> * = nullptr> + decltype(auto) end() { + return aka::make_from_tuple<::akantu::view_iterator< + Eigen::Map>>>( + std::tuple_cat(std::make_tuple(array.get().data() + array_size()), + sizes_)); + } + + decltype(auto) begin() const { + return aka::make_from_tuple<::akantu::view_iterator< + Eigen::Map>>>( + std::tuple_cat(std::make_tuple(array.get().data()), sizes_)); + } + decltype(auto) end() const { + return aka::make_from_tuple<::akantu::view_iterator< + Eigen::Map>>>( + std::tuple_cat(std::make_tuple(array.get().data() + array_size()), + sizes_)); + } + +private: + template >::value> + * = nullptr> + auto array_size() { + return array.get().size() * array.get().getNbComponent(); + } + + template < + class A = Array, + std::enable_if_t>::value> + * = nullptr> + auto array_size() { + return array.get().size(); + } + +private: + std::reference_wrapper> array; + std::tuple sizes_; +}; } // namespace details template -decltype(auto) make_view(Array && array, Idx rows = RowsAtCompileTime) { +decltype(auto) make_view(Array &&array, Idx rows = RowsAtCompileTime) { return details::EigenView( std::forward(array), rows); } template -decltype(auto) make_view(Array && array, Idx rows = RowsAtCompileTime, +decltype(auto) make_view(Array &&array, Idx rows = RowsAtCompileTime, Idx cols = ColsAtCompileTime) { return details::EigenView( std::forward(array), rows, cols); } } // namespace akantu namespace Eigen { template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void MatrixBase::zero() { return this->fill(0.); } /* -------------------------------------------------------------------------- */ /* Vector */ /* -------------------------------------------------------------------------- */ template template ::value and ED::IsVectorAtCompileTime> *> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto) MatrixBase::begin() { return ::akantu::view_iterator( this->derived().data()); } template template ::value and ED::IsVectorAtCompileTime> *> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto) MatrixBase::end() { return ::akantu::view_iterator( this->derived().data() + this->size()); } template template *> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto) MatrixBase::begin() const { using Scalar = typename Derived::Scalar; return ::akantu::const_view_iterator(this->derived().data()); } template template *> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto) MatrixBase::end() const { using Scalar = typename Derived::Scalar; return ::akantu::const_view_iterator(this->derived().data() + this->size()); } /* -------------------------------------------------------------------------- */ /* Matrix */ /* -------------------------------------------------------------------------- */ template template ::value and not ED::IsVectorAtCompileTime> *> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto) MatrixBase::begin() { return ::akantu::view_iterator< Map>>( this->derived().data(), this->rows()); } template template ::value and not ED::IsVectorAtCompileTime> *> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto) MatrixBase::end() { return ::akantu::view_iterator< Map>>( this->derived().data() + this->size(), this->rows()); } template template *> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto) MatrixBase::begin() const { using Scalar = typename Derived::Scalar; return ::akantu::const_view_iterator< Map>>( const_cast(this->derived().data()), this->rows()); } template template *> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto) MatrixBase::end() const { using Scalar = typename Derived::Scalar; return ::akantu::const_view_iterator< Map>>( const_cast(this->derived().data()) + this->size(), this->rows()); } template template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void -MatrixBase::eig(MatrixBase & values) const { +MatrixBase::eig(MatrixBase &values) const { EigenSolver>> solver(*this, false); using OtherScalar = typename OtherDerived::Scalar; // as advised by the Eigen developers even though this is a UB // auto & values = const_cast &>(values_); akantu::static_if(std::is_floating_point{}) - .then([&](auto && solver) { values = solver.eigenvalues().real(); }) - .else_([&](auto && solver) { values = solver.eigenvalues(); })( + .then([&](auto &&solver) { values = solver.eigenvalues().real(); }) + .else_([&](auto &&solver) { values = solver.eigenvalues(); })( std::forward(solver)); } template template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void -MatrixBase::eig(MatrixBase & values, MatrixBase & vectors, +MatrixBase::eig(MatrixBase &values, MatrixBase &vectors, bool sort) const { EigenSolver>> solver(*this, true); // as advised by the Eigen developers even though this is a UB // auto & values = const_cast &>(values_); // auto & vectors = const_cast &>(vectors_); auto norm = this->norm(); using OtherScalar = typename D1::Scalar; if ((solver.eigenvectors().imag().template lpNorm() > 1e-15 * norm) and std::is_floating_point::value) { AKANTU_EXCEPTION("This matrix has complex eigenvectors()"); } if (not sort) { akantu::static_if(std::is_floating_point{}) - .then([&](auto && solver) { + .then([&](auto &&solver) { values = solver.eigenvalues().real(); vectors = solver.eigenvectors().real(); }) - .else_([&](auto && solver) { + .else_([&](auto &&solver) { values = solver.eigenvalues(); vectors = solver.eigenvectors(); })(std::forward(solver)); return; } if (not std::is_floating_point::value) { AKANTU_EXCEPTION("Cannot sort complex eigen values"); } values = solver.eigenvalues().real(); PermutationMatrix P(values.size()); P.setIdentity(); std::sort(P.indices().data(), P.indices().data() + P.indices().size(), - [&values](const Index & a, const Index & b) { + [&values](const Index &a, const Index &b) { return (values(a) - values(b)) > 0; }); akantu::static_if(std::is_floating_point{}) - .then([&](auto && solver) { + .then([&](auto &&solver) { values = P.transpose() * values; vectors = solver.eigenvectors().real() * P; })(std::forward(solver)); return; } template template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void -MatrixBase::eigh(const MatrixBase & values_) const { +MatrixBase::eigh(const MatrixBase &values_) const { SelfAdjointEigenSolver< akantu::details::MapPlainObjectType_t>> solver(*this, EigenvaluesOnly); // as advised by the Eigen developers even though this is a UB - auto & values = const_cast &>(values_); + auto &values = const_cast &>(values_); values = solver.eigenvalues(); } template template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void -MatrixBase::eigh(const MatrixBase & values_, - const MatrixBase & vectors_, bool sort) const { +MatrixBase::eigh(const MatrixBase &values_, + const MatrixBase &vectors_, bool sort) const { SelfAdjointEigenSolver< akantu::details::MapPlainObjectType_t>> solver(*this, ComputeEigenvectors); // as advised by the Eigen developers, even though this is a UB - auto & values = const_cast &>(values_); - auto & vectors = const_cast &>(vectors_); + auto &values = const_cast &>(values_); + auto &vectors = const_cast &>(vectors_); if (not sort) { values = solver.eigenvalues(); vectors = solver.eigenvectors(); return; } values = solver.eigenvalues(); PermutationMatrix P(values.size()); P.setIdentity(); std::sort(P.indices().data(), P.indices().data() + P.indices().size(), - [&values](const Index & a, const Index & b) { + [&values](const Index &a, const Index &b) { return (values(a) - values(b)) > 0; }); values = P.transpose() * values(); vectors = solver.eigenvectors() * P; } } // namespace Eigen namespace std { template struct is_convertible, Eigen::Map> : aka::bool_constant::value> {}; } // namespace std #endif /* AKANTU_AKA_TYPES_HH */ diff --git a/src/common/aka_types_eigen_plain_object_base_plugin.hh b/src/common/aka_types_eigen_plain_object_base_plugin.hh index 8b1cf920a..858c64667 100644 --- a/src/common/aka_types_eigen_plain_object_base_plugin.hh +++ b/src/common/aka_types_eigen_plain_object_base_plugin.hh @@ -1,53 +1,51 @@ template ::value> * = nullptr> -EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE + std::enable_if_t<_is_vector> * = nullptr> +EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE PlainObjectBase(std::initializer_list list) { static_assert(std::is_trivially_copyable{}, "Cannot create a tensor on non trivial types"); _check_template_params(); this->template _init1(list.size()); Index i = 0; for (auto val : list) { this->operator()(i++) = val; } } template ::value> * = nullptr> -EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE + std::enable_if_t * = nullptr> +EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE PlainObjectBase(std::initializer_list> list) { static_assert(std::is_trivially_copyable{}, "Cannot create a tensor on non trivial types"); Index m = list.size(); Index n = 0; for (auto row : list) { n = std::max(n, Index(row.size())); } if (RowsAtCompileTime != -1 and RowsAtCompileTime != m) { - AKANTU_EXCEPTION( + throw std::range_error( "The size of the matrix does not correspond to the initializer_list"); } if (ColsAtCompileTime != -1 and ColsAtCompileTime != n) { - AKANTU_EXCEPTION( + throw std::range_error( "The size of the matrix does not correspond to the initializer_list"); } _check_template_params(); this->template _init2(m, n); this->fill(Scalar{}); Index i = 0, j = 0; - for (auto & row : list) { - for (auto & val : row) { + for (auto &row : list) { + for (auto &val : row) { this->operator()(i, j++) = val; } ++i; j = 0; } } diff --git a/src/common/aka_view_iterators.hh b/src/common/aka_view_iterators.hh index b6bfef25c..b601c9e4d 100644 --- a/src/common/aka_view_iterators.hh +++ b/src/common/aka_view_iterators.hh @@ -1,591 +1,591 @@ /** * @file aka_view_iterators.hh * * @author Nicolas Richart * * @date creation Thu Nov 15 2018 * * @brief View iterators * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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_types.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_AKA_VIEW_ITERATORS_HH__ #define __AKANTU_AKA_VIEW_ITERATORS_HH__ namespace akantu { template class TensorBase; } namespace akantu { /* -------------------------------------------------------------------------- */ /* Iterators */ /* -------------------------------------------------------------------------- */ namespace detail { template constexpr auto product_all(V &&...v) { std::common_type_t result = 1; (void)std::initializer_list{(result *= v, 0)...}; return result; } template struct IteratorHelper { static constexpr Int dim = 0; }; template struct IteratorHelper> { private: using T = typename Derived::Scalar; static constexpr Int m = Derived::RowsAtCompileTime; static constexpr Int n = Derived::ColsAtCompileTime; public: static constexpr Int dim = Eigen::MatrixBase::IsVectorAtCompileTime ? 1 : 2; using pointer = T *; using proxy = Eigen::Map>; using const_proxy = Eigen::Map>; }; template struct IteratorHelper> { private: using T = typename Derived::Scalar; static constexpr Int m = Derived::RowsAtCompileTime; static constexpr Int n = Derived::ColsAtCompileTime; public: static constexpr Int dim = Derived::IsVectorAtCompileTime and m != 1 ? 1 : 2; using pointer = T *; using proxy = Eigen::Map; using const_proxy = Eigen::Map; }; template struct IteratorHelper> { static constexpr Int dim = _dim; using pointer = T *; using proxy = TensorProxy; using const_proxy = TensorProxy; }; template struct IteratorHelper> { static constexpr Int dim = _dim; using pointer = T *; using proxy = TensorProxy; using const_proxy = TensorProxy; }; /* ------------------------------------------------------------------------ */ template >::dim> class internal_view_iterator { protected: using helper = IteratorHelper>; using internal_value_type = IR; using internal_pointer = IR *; using scalar_pointer = typename helper::pointer; using proxy_t = typename helper::proxy; static constexpr int dim_ = dim; public: using pointer = proxy_t *; using value_type = proxy_t; using reference = proxy_t &; using difference_type = Int; using iterator_category = std::random_access_iterator_tag; private: template constexpr auto get_new_proxy(scalar_pointer data, std::index_sequence) const { return ProxyType(data, dims[I]...); } constexpr auto get_new_proxy(scalar_pointer data) { return this->template get_new_proxy( data, std::make_index_sequence()); } template constexpr void reset_proxy(std::index_sequence) { new (&proxy) proxy_t(ret_ptr, dims[I]...); } constexpr auto reset_proxy() { return reset_proxy(std::make_index_sequence()); } protected: template ().data()), decltype(std::declval().data())>::value> * = nullptr> explicit internal_view_iterator(internal_view_iterator &it) : dims(it.dims), _offset(it._offset), initial(it.initial), ret_ptr(it.ret_ptr), proxy(get_new_proxy(it.ret_ptr)) {} template friend class internal_view_iterator; template using valid_args_t = std::enable_if_t< aka::conjunction, std::is_enum>...>::value and dim == sizeof...(Args), int>; public: /// Generic constructor dor any tensor dimension template = 0> internal_view_iterator(scalar_pointer data, Ns... ns) : dims({Int(ns)...}), _offset(detail::product_all(std::forward(ns)...)), initial(data), ret_ptr(data), proxy(data, ns...) {} // Specific constructor for Vector of static size 1 template , std::enable_if_t::value and RD::RowsAtCompileTime == 1 and RD::ColsAtCompileTime == 1> * = nullptr> constexpr internal_view_iterator(scalar_pointer data, Idx rows) : dims({rows, 1}), _offset(rows), initial(data), ret_ptr(data), proxy(data, rows, 1) { - AKANTU_DEBUG_ASSERT(rows == 1, "1x1 Matrix"); + assert(rows == 1 && "1x1 Matrix"); } /// Specific constructor for Eigen::Map that look like /// Eigen::Map template , std::enable_if_t<(RD::RowsAtCompileTime != 1) and RD::ColsAtCompileTime == 1> * = nullptr> constexpr internal_view_iterator(scalar_pointer data, Idx rows, [[gnu::unused]] Idx cols) : dims({rows}), _offset(rows), initial(data), ret_ptr(data), proxy(data, rows, 1) { - AKANTU_DEBUG_ASSERT(cols == 1, "nx1 Matrix"); + assert(cols == 1 && "nx1 Matrix"); } /// Default constructor for Eigen::Map template , std::enable_if_t<_dim == 1> * = nullptr> internal_view_iterator() : proxy(reinterpret_cast(0xdeadbeaf), RD::RowsAtCompileTime == Eigen::Dynamic ? 1 : RD::RowsAtCompileTime) { // initialized to a fake pointer to pass the static_assert in Eigen // this proxy should not be returned } /// Default constructor for Eigen::Map template , std::enable_if_t<_dim == 2> * = nullptr> internal_view_iterator() : proxy(reinterpret_cast(0xdeadbeaf), RD::RowsAtCompileTime == Eigen::Dynamic ? 1 : RD::RowsAtCompileTime, RD::ColsAtCompileTime == Eigen::Dynamic ? 1 : RD::ColsAtCompileTime) { // initialized to a fake pointer to pass the `static_assert` in `Eigen // this proxy should not be returned } internal_view_iterator(const internal_view_iterator &it) : dims(it.dims), _offset(it._offset), initial(it.initial), ret_ptr(it.ret_ptr), proxy(get_new_proxy(it.ret_ptr)) {} internal_view_iterator & operator=(internal_view_iterator &&it) noexcept = default; internal_view_iterator(internal_view_iterator &&it) noexcept = default; virtual ~internal_view_iterator() = default; template ().data()), decltype(std::declval().data())>::value> * = nullptr> inline internal_view_iterator & operator=(const internal_view_iterator &it) { this->dims = it.dims; this->_offset = it._offset; this->initial = it.initial; this->ret_ptr = it.ret_ptr; reset_proxy(); return *this; } inline internal_view_iterator &operator=(const internal_view_iterator &it) { if (this != &it) { this->dims = it.dims; this->_offset = it._offset; this->initial = it.initial; this->ret_ptr = it.ret_ptr; reset_proxy(); } return *this; } public: Idx getCurrentIndex() { return (this->ret_ptr - this->initial) / this->_offset; } inline reference operator*() { this->reset_proxy(); return proxy; } inline pointer operator->() { reset_proxy(); return &proxy; } inline daughter &operator++() { ret_ptr += _offset; return static_cast(*this); } inline daughter &operator--() { ret_ptr -= _offset; return static_cast(*this); } inline daughter &operator+=(Idx n) { ret_ptr += _offset * n; return static_cast(*this); } inline daughter &operator-=(Idx n) { ret_ptr -= _offset * n; return static_cast(*this); } inline auto operator[](Idx n) { return get_new_proxy(ret_ptr + n * _offset); } inline bool operator==(const internal_view_iterator &other) const { return this->ret_ptr == other.ret_ptr; } inline bool operator!=(const internal_view_iterator &other) const { return this->ret_ptr != other.ret_ptr; } inline bool operator<(const internal_view_iterator &other) const { return this->ret_ptr < other.ret_ptr; } inline bool operator<=(const internal_view_iterator &other) const { return this->ret_ptr <= other.ret_ptr; } inline bool operator>(const internal_view_iterator &other) const { return this->ret_ptr > other.ret_ptr; } inline bool operator>=(const internal_view_iterator &other) const { return this->ret_ptr >= other.ret_ptr; } inline auto operator+(difference_type n) { auto tmp(static_cast(*this)); tmp += n; return tmp; } inline auto operator-(difference_type n) { auto tmp(static_cast(*this)); tmp -= n; return tmp; } inline difference_type operator-(const internal_view_iterator &b) { return (this->ret_ptr - b.ret_ptr) / _offset; } inline scalar_pointer data() const { return ret_ptr; } inline difference_type offset() const { return _offset; } inline decltype(auto) getDims() const { return dims; } protected: std::array dims; difference_type _offset{0}; scalar_pointer initial{nullptr}; scalar_pointer ret_ptr{nullptr}; proxy_t proxy; }; /* ------------------------------------------------------------------------ */ /** * Specialization for scalar types */ template class internal_view_iterator { public: using value_type = R; using pointer = R *; using reference = R &; using const_reference = const R &; using difference_type = Idx; // std::ptrdiff_t; using iterator_category = std::random_access_iterator_tag; static constexpr int dim_ = 0; protected: using internal_value_type = IR; using internal_pointer = IR *; public: internal_view_iterator(pointer data = nullptr) : ret(data), initial(data){}; internal_view_iterator(const internal_view_iterator &it) = default; internal_view_iterator(internal_view_iterator &&it) = default; virtual ~internal_view_iterator() = default; inline internal_view_iterator & operator=(const internal_view_iterator &it) = default; Idx getCurrentIndex() { return (this->ret - this->initial); }; inline reference operator*() { return *ret; } inline pointer operator->() { return ret; }; inline daughter &operator++() { ++ret; return static_cast(*this); } inline daughter &operator--() { --ret; return static_cast(*this); } inline daughter &operator+=(const Idx n) { ret += n; return static_cast(*this); } inline daughter &operator-=(const Idx n) { ret -= n; return static_cast(*this); } inline reference operator[](const Idx n) { return ret[n]; } inline bool operator==(const internal_view_iterator &other) const { return ret == other.ret; } inline bool operator!=(const internal_view_iterator &other) const { return ret != other.ret; } inline bool operator<(const internal_view_iterator &other) const { return ret < other.ret; } inline bool operator<=(const internal_view_iterator &other) const { return ret <= other.ret; } inline bool operator>(const internal_view_iterator &other) const { return ret > other.ret; } inline bool operator>=(const internal_view_iterator &other) const { return ret >= other.ret; } inline daughter operator-(difference_type n) { return daughter(ret - n); } inline daughter operator+(difference_type n) { return daughter(ret + n); } inline difference_type operator-(const internal_view_iterator &b) { return ret - b.ret; } inline pointer data() const { return ret; } inline decltype(auto) getDims() const { return dims; } protected: std::array dims; pointer ret{nullptr}; pointer initial{nullptr}; }; } // namespace detail /* -------------------------------------------------------------------------- */ template class view_iterator; template class const_view_iterator : public detail::internal_view_iterator, R> { public: using parent = detail::internal_view_iterator; using value_type = typename parent::value_type; using pointer = typename parent::pointer; using reference = typename parent::reference; using difference_type = typename parent::difference_type; using iterator_category = typename parent::iterator_category; protected: template static inline auto convert_helper(const Iterator &it, std::index_sequence) { return const_view_iterator(it.data(), it.getDims()[I]...); } template static inline auto convert(const Iterator &it) { return convert_helper(it, std::make_index_sequence()); } public: const_view_iterator() : parent(){}; const_view_iterator(const const_view_iterator &it) = default; const_view_iterator(const_view_iterator &&it) noexcept = default; template const_view_iterator(P *data, Ns... ns) : parent(data, ns...) {} const_view_iterator &operator=(const const_view_iterator &it) = default; template ::value> * = nullptr> const_view_iterator(const const_view_iterator &it) : parent(convert(it)) {} template ::value> * = nullptr> const_view_iterator(const view_iterator &it) : parent(convert(it)) {} template ::value and std::is_convertible::value> * = nullptr> const_view_iterator &operator=(const const_view_iterator &it) { return dynamic_cast(parent::operator=(it)); } template ::value> * = nullptr> const_view_iterator operator=(const view_iterator &it) { return convert(it); } }; template ::value> struct ConstConverterIteratorHelper { protected: template static inline auto convert_helper(const view_iterator &it, std::index_sequence) { return const_view_iterator(it.data(), it.getDims()[I]...); } public: static inline auto convert(const view_iterator &it) { return convert_helper( it, std::make_index_sequence< std::tuple_size::value>()); } }; template struct ConstConverterIteratorHelper { static inline auto convert(const view_iterator &it) { return const_view_iterator(it.data()); } }; template class view_iterator : public detail::internal_view_iterator> { public: using parent = detail::internal_view_iterator; using value_type = typename parent::value_type; using pointer = typename parent::pointer; using reference = typename parent::reference; using difference_type = typename parent::difference_type; using iterator_category = typename parent::iterator_category; public: view_iterator() : parent(){}; view_iterator(const view_iterator &it) = default; view_iterator(view_iterator &&it) = default; template view_iterator(P *data, Ns... ns) : parent(data, ns...) {} view_iterator &operator=(const view_iterator &it) = default; operator const_view_iterator() { return ConstConverterIteratorHelper::convert(*this); } }; namespace { template struct ViewIteratorHelper { using type = TensorProxy; }; template struct ViewIteratorHelper<0, T> { using type = T; }; template struct ViewIteratorHelper<1, T> { using type = Eigen::Map>; }; template struct ViewIteratorHelper<1, const T> { using type = Eigen::Map>; }; template struct ViewIteratorHelper<2, T> { using type = Eigen::Map>; }; template struct ViewIteratorHelper<2, const T> { using type = Eigen::Map>; }; template using ViewIteratorHelper_t = typename ViewIteratorHelper::type; } // namespace } // namespace akantu #include namespace std { template struct iterator_traits<::akantu::const_view_iterator> { protected: using iterator = ::akantu::const_view_iterator; public: using iterator_category = typename iterator::iterator_category; using value_type = typename iterator::value_type; using difference_type = typename iterator::difference_type; using pointer = typename iterator::pointer; using reference = typename iterator::reference; }; template struct iterator_traits<::akantu::view_iterator> { protected: using iterator = ::akantu::view_iterator; public: using iterator_category = typename iterator::iterator_category; using value_type = typename iterator::value_type; using difference_type = typename iterator::difference_type; using pointer = typename iterator::pointer; using reference = typename iterator::reference; }; } // namespace std #endif /* !__AKANTU_AKA_VIEW_ITERATORS_HH__ */ diff --git a/src/fe_engine/element_class.hh b/src/fe_engine/element_class.hh index c1eaeab6a..956911032 100644 --- a/src/fe_engine/element_class.hh +++ b/src/fe_engine/element_class.hh @@ -1,503 +1,503 @@ /** * @file element_class.hh * * @author Guillaume Anciaux * @author Aurelia Isabel Cuba Ramos * @author Mohit Pundir * @author Nicolas Richart * * @date creation: Fri Jun 18 2010 * @date last modification: Fri Dec 11 2020 * * @brief Declaration of the ElementClass main class and the * Integration and Interpolation elements * * * @section LICENSE * * Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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_types.hh" /* -------------------------------------------------------------------------- */ #ifndef AKANTU_ELEMENT_CLASS_HH_ #define AKANTU_ELEMENT_CLASS_HH_ namespace akantu { /* -------------------------------------------------------------------------- */ /// default element class structure template struct ElementClassProperty { static constexpr GeometricalType geometrical_type{_gt_not_defined}; static constexpr InterpolationType interpolation_type{_itp_not_defined}; static constexpr ElementKind element_kind{_ek_regular}; static constexpr Int spatial_dimension{0}; static constexpr GaussIntegrationType gauss_itegration_type{_git_not_defined}; static constexpr Int polynomial_degree{0}; }; #if !defined(DOXYGEN) /// Macro to generate the element class structures for different element types #define AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(elem_type, geom_type, \ interp_type, elem_kind, sp, \ gauss_int_type, min_int_order) \ template <> struct ElementClassProperty { \ static constexpr GeometricalType geometrical_type{geom_type}; \ static constexpr InterpolationType interpolation_type{interp_type}; \ static constexpr ElementKind element_kind{elem_kind}; \ static constexpr Int spatial_dimension{sp}; \ static constexpr GaussIntegrationType gauss_integration_type{ \ gauss_int_type}; \ static constexpr Int polynomial_degree{min_int_order}; \ } #else #define AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(elem_type, geom_type, \ interp_type, elem_kind, sp, \ gauss_int_type, min_int_order) #endif /* -------------------------------------------------------------------------- */ /* Geometry */ /* -------------------------------------------------------------------------- */ /// Default GeometricalShape structure template struct GeometricalShape { static constexpr GeometricalShapeType shape{_gst_point}; }; /// Templated GeometricalShape with function contains template struct GeometricalShapeContains { /// Check if the point (vector in 2 and 3D) at natural coordinate coord template static inline bool contains(const Eigen::MatrixBase &coord); }; #if !defined(DOXYGEN) /// Macro to generate the GeometricalShape structures for different geometrical /// types #define AKANTU_DEFINE_SHAPE(geom_type, geom_shape) \ template <> struct GeometricalShape { \ static constexpr GeometricalShapeType shape{geom_shape}; \ } AKANTU_DEFINE_SHAPE(_gt_hexahedron_20, _gst_square); AKANTU_DEFINE_SHAPE(_gt_hexahedron_8, _gst_square); AKANTU_DEFINE_SHAPE(_gt_pentahedron_15, _gst_prism); AKANTU_DEFINE_SHAPE(_gt_pentahedron_6, _gst_prism); AKANTU_DEFINE_SHAPE(_gt_point, _gst_point); AKANTU_DEFINE_SHAPE(_gt_quadrangle_4, _gst_square); AKANTU_DEFINE_SHAPE(_gt_quadrangle_8, _gst_square); AKANTU_DEFINE_SHAPE(_gt_segment_2, _gst_square); AKANTU_DEFINE_SHAPE(_gt_segment_3, _gst_square); AKANTU_DEFINE_SHAPE(_gt_tetrahedron_10, _gst_triangle); AKANTU_DEFINE_SHAPE(_gt_tetrahedron_4, _gst_triangle); AKANTU_DEFINE_SHAPE(_gt_triangle_3, _gst_triangle); AKANTU_DEFINE_SHAPE(_gt_triangle_6, _gst_triangle); #endif /* -------------------------------------------------------------------------- */ template struct GeometricalElementProperty {}; template struct ElementClassExtraGeometryProperties {}; /* -------------------------------------------------------------------------- */ /// Templated GeometricalElement with function getInradius template ::shape> class GeometricalElement { using geometrical_property = GeometricalElementProperty; public: /// compute the in-radius: \todo should be renamed for characteristic length template - static constexpr inline Real getInradius(const Eigen::MatrixBase & /*X*/) { - AKANTU_TO_IMPLEMENT(); + static inline Real getInradius(const Eigen::MatrixBase & /*X*/) { + return 0.; } /// compute the normal to the element template - static constexpr inline void getNormal(const Eigen::MatrixBase & /*X*/, - Eigen::MatrixBase & /*n*/) { - AKANTU_TO_IMPLEMENT(); + static inline void getNormal(const Eigen::MatrixBase & /*X*/, + Eigen::MatrixBase &n) { + n.zero(); } /// true if the natural coordinates are in the element template static inline bool contains(const Eigen::MatrixBase &coord); public: static constexpr auto getSpatialDimension() { return geometrical_property::spatial_dimension; } static constexpr auto getNbNodesPerElement() { return geometrical_property::nb_nodes_per_element; } static inline constexpr auto getNbFacetTypes() { return geometrical_property::nb_facet_types; }; static inline constexpr Int getNbFacetsPerElement(Idx t); static inline constexpr Int getNbFacetsPerElement(); static inline constexpr decltype(auto) getFacetLocalConnectivityPerElement(Idx t = 0); template ::value, std::enable_if_t<(t < size)> * = nullptr> static inline constexpr decltype(auto) getFacetLocalConnectivityPerElement(); template ::value, std::enable_if_t * = nullptr> static inline constexpr decltype(auto) getFacetLocalConnectivityPerElement(); }; /* -------------------------------------------------------------------------- */ /* Interpolation */ /* -------------------------------------------------------------------------- */ /// default InterpolationProperty structure template struct InterpolationProperty {}; #if !defined(DOXYGEN) /// Macro to generate the InterpolationProperty structures for different /// interpolation types #define AKANTU_DEFINE_INTERPOLATION_TYPE_PROPERTY(itp_type, itp_kind, \ nb_nodes, ndim) \ template <> struct InterpolationProperty { \ static constexpr InterpolationKind kind{itp_kind}; \ static constexpr Int nb_nodes_per_element{nb_nodes}; \ static constexpr Int natural_space_dimension{ndim}; \ } #else #define AKANTU_DEFINE_INTERPOLATION_TYPE_PROPERTY(itp_type, itp_kind, \ nb_nodes, ndim) #endif /* -------------------------------------------------------------------------- */ /// Generic (templated by the enum InterpolationType which specifies the order /// and the dimension of the interpolation) class handling the elemental /// interpolation template ::kind> class InterpolationElement { public: using interpolation_property = InterpolationProperty; /// compute the shape values for a given set of points in natural coordinates template ::value> * = nullptr> static inline void computeShapes(const Eigen::MatrixBase &Xs, const Eigen::MatrixBase &N_); /// compute the shape values for a given point in natural coordinates template ::value> * = nullptr> static inline void computeShapes(const Eigen::MatrixBase & /*Xs*/, Eigen::MatrixBase & /*N_*/) { AKANTU_TO_IMPLEMENT(); } /** * compute @f$ B_{ij} = \frac{\partial N_j}{\partial S_i} @f$ the variation of * shape functions along with variation of natural coordinates on a given set * of points in natural coordinates */ template static inline void computeDNDS(const Eigen::MatrixBase &Xs, Tensor3Base &dnds); /** * compute @f$ B_{ij} = \frac{\partial N_j}{\partial S_i} @f$ the variation of * shape functions along with * variation of natural coordinates on a given point in natural * coordinates */ template static inline void computeDNDS(const Eigen::MatrixBase & /*Xs*/, Eigen::MatrixBase & /*dNdS*/) { AKANTU_TO_IMPLEMENT(); } /** * compute @f$ @f$ **/ static inline void computeD2NDS2(const Matrix &natural_coord, Tensor3 &d2nds2); /** * compute @f$ B_{ij} = \frac{\partial N_j}{\partial S_i} @f$ the * second variation of * shape functions along with * variation of natural coordinates on a given point in natural * coordinates */ template static inline void computeD2NDS2(const vector_type & /*unused*/, matrix_type & /*unused*/) { AKANTU_TO_IMPLEMENT(); } /// compute jacobian (or integration variable change factor) for a given point /// in the case of spatial_dimension != natural_space_dimension template static inline Real computeSpecialJacobian(const Eigen::MatrixBase &) { AKANTU_TO_IMPLEMENT(); } /// interpolate a field given (arbitrary) natural coordinates template static inline decltype(auto) interpolateOnNaturalCoordinates( const Eigen::MatrixBase &natural_coords, const Eigen::MatrixBase &nodal_values) { using interpolation = InterpolationProperty; Eigen::Matrix shapes; computeShapes(natural_coords, shapes); Matrix res; res.noalias() = interpolate(nodal_values, shapes); return res; } /// interpolate a field given the shape functions on the interpolation point template static inline auto interpolate(const Eigen::MatrixBase &nodal_values, const Eigen::MatrixBase &shapes); /// interpolate a field given the shape functions on the interpolations points template static inline void interpolate(const Eigen::MatrixBase &nodal_values, const Eigen::MatrixBase &Ns, const Eigen::MatrixBase &interpolated); /// compute the gradient of a given field on the given natural coordinates template static inline void gradientOnNaturalCoordinates(const Eigen::MatrixBase &natural_coords, const Eigen::MatrixBase &f, const Eigen::MatrixBase &dfds); public: static constexpr auto getShapeSize() { return InterpolationProperty::nb_nodes_per_element; } static constexpr auto getShapeDerivativesSize() { return (InterpolationProperty::nb_nodes_per_element * InterpolationProperty::natural_space_dimension); } static constexpr auto getNaturalSpaceDimension() { return InterpolationProperty::natural_space_dimension; } static constexpr auto getNbNodesPerInterpolationElement() { return InterpolationProperty::nb_nodes_per_element; } }; /* -------------------------------------------------------------------------- */ /* Integration */ /* -------------------------------------------------------------------------- */ template struct GaussIntegrationTypeData { /// quadrature points in natural coordinates static Real quad_positions[]; /// weights for the Gauss integration static Real quad_weights[]; }; template ::polynomial_degree> class GaussIntegrationElement { static constexpr InterpolationType itp_type = ElementClassProperty::interpolation_type; using interpolation_property = InterpolationProperty; public: static constexpr Int getNbQuadraturePoints(); static constexpr auto getQuadraturePoints() -> Matrix; static constexpr auto getWeights() -> Vector; }; /* -------------------------------------------------------------------------- */ /* ElementClass */ /* -------------------------------------------------------------------------- */ template ::element_kind> class ElementClass : public GeometricalElement< ElementClassProperty::geometrical_type>, public InterpolationElement< ElementClassProperty::interpolation_type> { protected: using geometrical_element = GeometricalElement::geometrical_type>; using interpolation_element = InterpolationElement< ElementClassProperty::interpolation_type>; using element_property = ElementClassProperty; using interpolation_property = typename interpolation_element::interpolation_property; public: /** * compute @f$ J = \frac{\partial x_j}{\partial s_i} @f$ the variation of real * coordinates along with variation of natural coordinates on a given point in * natural coordinates */ template static inline decltype(auto) computeJMat(const Eigen::MatrixBase &dnds, const Eigen::MatrixBase &node_coords); /** * compute the Jacobian matrix by computing the variation of real coordinates * along with variation of natural coordinates on a given set of points in * natural coordinates */ template static inline void computeJMat(const Tensor3Base &dnds, const Eigen::MatrixBase &node_coords, Tensor3Base &J); /// compute the jacobians of a serie of natural coordinates template static inline void computeJacobian(const Eigen::MatrixBase &natural_coords, const Eigen::MatrixBase &node_coords, Eigen::MatrixBase &jacobians); /// compute jacobian (or integration variable change factor) for a set of /// points template static inline void computeJacobian(const Tensor3Base &J, Eigen::MatrixBase &jacobians); /// compute jacobian (or integration variable change factor) for a given point template static inline Real computeJacobian(const Eigen::MatrixBase &J); /// compute shape derivatives (input is dxds) for a set of points static inline void computeShapeDerivatives(const Tensor3Base &J, const Tensor3Base &dnds, Tensor3Base &shape_deriv); /// compute shape derivatives (input is dxds) for a given point template static inline void computeShapeDerivatives(const Eigen::MatrixBase &J, const Eigen::MatrixBase &dnds, Eigen::MatrixBase &shape_deriv); /// compute the normal of a surface defined by the function f template static inline void computeNormalsOnNaturalCoordinates(const Eigen::MatrixBase &coord, const Eigen::MatrixBase &f, Eigen::MatrixBase &normals); /// get natural coordinates from real coordinates template * = nullptr> static inline void inverseMap(const Eigen::MatrixBase &real_coords, const Eigen::MatrixBase &node_coords, const Eigen::MatrixBase &natural_coords, Int max_iterations = 100, Real tolerance = 1e-10); /// get natural coordinates from real coordinates template * = nullptr> static inline void inverseMap(const Eigen::MatrixBase &real_coords, const Eigen::MatrixBase &node_coords, const Eigen::MatrixBase &natural_coords_, Int max_iterations = 100, Real tolerance = 1e-10); public: static constexpr auto getKind() { return element_kind; } static constexpr auto getSpatialDimension() { return ElementClassProperty::spatial_dimension; } using element_class_extra_geom_property = ElementClassExtraGeometryProperties; static constexpr decltype(auto) getP1ElementType() { return element_class_extra_geom_property::p1_type; } static constexpr decltype(auto) getFacetType(UInt t = 0) { return element_class_extra_geom_property::facet_type[t]; } static constexpr decltype(auto) getFacetTypes(); }; /* -------------------------------------------------------------------------- */ } // namespace akantu /* -------------------------------------------------------------------------- */ #include "geometrical_element_property.hh" #include "interpolation_element_tmpl.hh" /* -------------------------------------------------------------------------- */ #include "element_class_tmpl.hh" /* -------------------------------------------------------------------------- */ namespace akantu { AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_not_defined, _gt_not_defined, _itp_not_defined, _ek_not_defined, 0, _git_not_defined, 0); } // namespace akantu #include "element_class_hexahedron_8_inline_impl.hh" #include "element_class_pentahedron_6_inline_impl.hh" /* keep order */ #include "element_class_hexahedron_20_inline_impl.hh" #include "element_class_pentahedron_15_inline_impl.hh" #include "element_class_point_1_inline_impl.hh" #include "element_class_quadrangle_4_inline_impl.hh" #include "element_class_quadrangle_8_inline_impl.hh" #include "element_class_segment_2_inline_impl.hh" #include "element_class_segment_3_inline_impl.hh" #include "element_class_tetrahedron_10_inline_impl.hh" #include "element_class_tetrahedron_4_inline_impl.hh" #include "element_class_triangle_3_inline_impl.hh" #include "element_class_triangle_6_inline_impl.hh" /* -------------------------------------------------------------------------- */ #if defined(AKANTU_STRUCTURAL_MECHANICS) #include "element_class_structural.hh" #endif #if defined(AKANTU_COHESIVE_ELEMENT) #include "cohesive_element.hh" #endif #if defined(AKANTU_IGFEM) #include "element_class_igfem.hh" #endif #endif /* AKANTU_ELEMENT_CLASS_HH_ */ diff --git a/src/fe_engine/element_class_tmpl.hh b/src/fe_engine/element_class_tmpl.hh index 81e885af0..fbaf32590 100644 --- a/src/fe_engine/element_class_tmpl.hh +++ b/src/fe_engine/element_class_tmpl.hh @@ -1,586 +1,590 @@ /** * @file element_class_tmpl.hh * * @author Aurelia Isabel Cuba Ramos * @author Thomas Menouillard * @author Mohit Pundir * @author Nicolas Richart * * @date creation: Thu Feb 21 2013 * @date last modification: Fri Dec 11 2020 * * @brief Implementation of the inline templated function of the element class * descriptions * * * @section LICENSE * * Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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_class.hh" #include "aka_iterators.hh" #include "gauss_integration_tmpl.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #ifndef AKANTU_ELEMENT_CLASS_TMPL_HH_ #define AKANTU_ELEMENT_CLASS_TMPL_HH_ namespace akantu { template inline constexpr decltype(auto) ElementClass::getFacetTypes() { return Eigen::Map>( element_class_extra_geom_property::facet_type.data()); } /* -------------------------------------------------------------------------- */ /* GeometricalElement */ /* -------------------------------------------------------------------------- */ template template *> inline constexpr decltype(auto) GeometricalElement::getFacetLocalConnectivityPerElement() { - AKANTU_ERROR("Not a valid facet id for this element type"); + throw std::range_error("Not a valid facet id for this element type"); } template template *> inline constexpr decltype(auto) GeometricalElement::getFacetLocalConnectivityPerElement() { Int pos = 0; for (Int i = 0; i < t; ++i) { pos += geometrical_property::nb_facets[i] * geometrical_property::nb_nodes_per_facet[i]; } return Eigen::Map< const Eigen::Matrix>( geometrical_property::facet_connectivity_vect.data() + pos); } /* -------------------------------------------------------------------------- */ template inline constexpr decltype(auto) GeometricalElement::getFacetLocalConnectivityPerElement(Idx t) { Int pos = 0; for (Int i = 0; i < t; ++i) { pos += geometrical_property::nb_facets[i] * geometrical_property::nb_nodes_per_facet[i]; } return Eigen::Map>( geometrical_property::facet_connectivity_vect.data() + pos, geometrical_property::nb_facets[t], geometrical_property::nb_nodes_per_facet[t]); } /* -------------------------------------------------------------------------- */ template inline constexpr Int GeometricalElement::getNbFacetsPerElement() { Int total_nb_facets = 0; for (Int n = 0; n < geometrical_property::nb_facet_types; ++n) { total_nb_facets += geometrical_property::nb_facets[n]; } return total_nb_facets; } /* -------------------------------------------------------------------------- */ template inline constexpr Int GeometricalElement::getNbFacetsPerElement(Idx t) { return geometrical_property::nb_facets[t]; } /* -------------------------------------------------------------------------- */ template template inline bool GeometricalElement::contains( - const Eigen::MatrixBase & coords) { + const Eigen::MatrixBase &coords) { return GeometricalShapeContains::contains(coords); } /* -------------------------------------------------------------------------- */ template <> template inline bool GeometricalShapeContains<_gst_point>::contains( - const Eigen::MatrixBase & coords) { + const Eigen::MatrixBase &coords) { return (coords(0) < std::numeric_limits::epsilon()); } /* -------------------------------------------------------------------------- */ template <> template inline bool GeometricalShapeContains<_gst_square>::contains( - const Eigen::MatrixBase & coords) { + const Eigen::MatrixBase &coords) { bool in = true; for (Int i = 0; i < coords.size() && in; ++i) { in &= ((coords(i) >= -(1. + std::numeric_limits::epsilon())) && (coords(i) <= (1. + std::numeric_limits::epsilon()))); } return in; } /* -------------------------------------------------------------------------- */ template <> template inline bool GeometricalShapeContains<_gst_triangle>::contains( - const Eigen::MatrixBase & coords) { + const Eigen::MatrixBase &coords) { bool in = true; Real sum = 0; for (Int i = 0; (i < coords.size()) && in; ++i) { in &= ((coords(i) >= -(Math::getTolerance())) && (coords(i) <= (1. + Math::getTolerance()))); sum += coords(i); } if (in) { return (in && (sum <= (1. + Math::getTolerance()))); } return in; } /* -------------------------------------------------------------------------- */ template <> template inline bool GeometricalShapeContains<_gst_prism>::contains( - const Eigen::MatrixBase & coords) { + const Eigen::MatrixBase &coords) { bool in = ((coords(0) >= -1.) && (coords(0) <= 1.)); // x in segment [-1, 1] // y and z in triangle in &= ((coords(1) >= 0) && (coords(1) <= 1.)); in &= ((coords(2) >= 0) && (coords(2) <= 1.)); Real sum = coords(1) + coords(2); return (in && (sum <= 1)); } /* -------------------------------------------------------------------------- */ /* InterpolationElement */ /* -------------------------------------------------------------------------- */ template template ::value> *> inline void InterpolationElement::computeShapes( - const Eigen::MatrixBase & Xs, const Eigen::MatrixBase & N_) { + const Eigen::MatrixBase &Xs, const Eigen::MatrixBase &N_) { - Eigen::MatrixBase & N = const_cast &>( + Eigen::MatrixBase &N = const_cast &>( N_); // as advised by the Eigen developers - for (auto && data : zip(Xs, N)) { + for (auto &&data : zip(Xs, N)) { computeShapes(std::get<0>(data), std::get<1>(data)); } } /* -------------------------------------------------------------------------- */ template template inline void InterpolationElement::computeDNDS( - const Eigen::MatrixBase & Xs, Tensor3Base & dNdS) { - for (auto && data : zip(Xs, dNdS)) { + const Eigen::MatrixBase &Xs, Tensor3Base &dNdS) { + for (auto &&data : zip(Xs, dNdS)) { computeDNDS(std::get<0>(data), std::get<1>(data)); } } /* -------------------------------------------------------------------------- */ /** * interpolate on a point a field for which values are given on the * node of the element using the shape functions at this interpolation point * * @param nodal_values values of the function per node @f$ f_{ij} = f_{n_i j} *@f$ so it should be a matrix of size nb_nodes_per_element @f$\times@f$ *nb_degree_of_freedom * @param shapes value of shape functions at the interpolation point * @param interpolated interpolated value of f @f$ f_j(\xi) = \sum_i f_{n_i j} *N_i @f$ */ template template inline auto InterpolationElement::interpolate( - const Eigen::MatrixBase & nodal_values, - const Eigen::MatrixBase & shapes) { + const Eigen::MatrixBase &nodal_values, + const Eigen::MatrixBase &shapes) { return nodal_values * shapes; } /* -------------------------------------------------------------------------- */ /** * interpolate on several points a field for which values are given on the * node of the element using the shape functions at the interpolation point * * @param nodal_values values of the function per node @f$ f_{ij} = f_{n_i j} *@f$ so it should be a matrix of size nb_nodes_per_element @f$\times@f$ *nb_degree_of_freedom * @param shapes value of shape functions at the interpolation point * @param interpolated interpolated values of f @f$ f_j(\xi) = \sum_i f_{n_i j} *N_i @f$ */ template template inline void InterpolationElement::interpolate( - const Eigen::MatrixBase & nodal_values, - const Eigen::MatrixBase & Ns, - const Eigen::MatrixBase & interpolated_) { + const Eigen::MatrixBase &nodal_values, + const Eigen::MatrixBase &Ns, + const Eigen::MatrixBase &interpolated_) { - auto && interpolated = const_cast &>( + auto &&interpolated = const_cast &>( interpolated_); // as advised by the Eigen developers auto nb_points = Ns.cols(); for (auto p = 0; p < nb_points; ++p) { interpolated.col(p).noalias() = interpolate(nodal_values, Ns.col(p)); } } /* -------------------------------------------------------------------------- */ /** * interpolate the field on a point given in natural coordinates the field which * values are given on the node of the element * * @param natural_coords natural coordinates of point where to interpolate \xi * @param nodal_values values of the function per node @f$ f_{ij} = f_{n_i j} *@f$ so it should be a matrix of size nb_nodes_per_element @f$\times@f$ *nb_degree_of_freedom * @param interpolated interpolated value of f @f$ f_j(\xi) = \sum_i f_{n_i j} *N_i @f$ */ // template // inline decltype(auto) // InterpolationElement::interpolateOnNaturalCoordinates( // const Ref & natural_coords, // const Ref & nodal_values, Ref interpolated) { // using interpolation = InterpolationProperty; // Eigen::Matrix shapes; // computeShapes(natural_coords, shapes); // return interpolate(nodal_values, shapes); // } /* -------------------------------------------------------------------------- */ /// @f$ gradient_{ij} = \frac{\partial f_j}{\partial s_i} = \sum_k /// \frac{\partial N_k}{\partial s_i}f_{j n_k} @f$ template template inline void InterpolationElement::gradientOnNaturalCoordinates( - const Eigen::MatrixBase & natural_coords, - const Eigen::MatrixBase & f, const Eigen::MatrixBase & dfds_) { + const Eigen::MatrixBase &natural_coords, const Eigen::MatrixBase &f, + const Eigen::MatrixBase &dfds_) { constexpr auto nsp = InterpolationProperty::natural_space_dimension; constexpr auto nnodes = InterpolationProperty::nb_nodes_per_element; Eigen::Matrix dnds( nsp, nnodes); - auto & dfds = const_cast &>(dfds_); + auto &dfds = const_cast &>(dfds_); computeDNDS(natural_coords, dnds); dfds.noalias() = f * dnds.transpose(); } /* -------------------------------------------------------------------------- */ /* ElementClass */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ template template inline decltype(auto) ElementClass::computeJMat( - const Eigen::MatrixBase & dnds, - const Eigen::MatrixBase & node_coords) { + const Eigen::MatrixBase &dnds, + const Eigen::MatrixBase &node_coords) { /// @f$ J = dxds = dnds * x @f$ return dnds * node_coords.transpose(); } /* -------------------------------------------------------------------------- */ template template inline void -ElementClass::computeJMat(const Tensor3Base & dnds, - const Eigen::MatrixBase & node_coords, - Tensor3Base & J) { - for (auto && data : zip(J, dnds)) { +ElementClass::computeJMat(const Tensor3Base &dnds, + const Eigen::MatrixBase &node_coords, + Tensor3Base &J) { + for (auto &&data : zip(J, dnds)) { std::get<0>(data) = computeJMat(std::get<1>(data), node_coords); } } /* -------------------------------------------------------------------------- */ template template inline void ElementClass::computeJacobian( - const Eigen::MatrixBase & natural_coords, - const Eigen::MatrixBase & node_coords, - Eigen::MatrixBase & jacobians) { + const Eigen::MatrixBase &natural_coords, + const Eigen::MatrixBase &node_coords, + Eigen::MatrixBase &jacobians) { auto nb_points = natural_coords.cols(); Matrix dnds; Matrix J(natural_coords.rows(), node_coords.rows()); for (Int p = 0; p < nb_points; ++p) { interpolation_element::computeDNDS(natural_coords.col(p), dnds); J = computeJMat(dnds, node_coords); jacobians(p) = computeJacobian(J); } } /* -------------------------------------------------------------------------- */ template template inline void -ElementClass::computeJacobian(const Tensor3Base & J, - Eigen::MatrixBase & jacobians) { +ElementClass::computeJacobian(const Tensor3Base &J, + Eigen::MatrixBase &jacobians) { auto nb_points = J.size(2); for (Int p = 0; p < nb_points; ++p) { computeJacobian(J(p), jacobians.col(p)); } } /* -------------------------------------------------------------------------- */ template template inline Real -ElementClass::computeJacobian(const Eigen::MatrixBase & J) { +ElementClass::computeJacobian(const Eigen::MatrixBase &J) { if (J.rows() == J.cols()) { return J.determinant(); } else { switch (interpolation_property::natural_space_dimension) { case 1: { return J.norm(); } case 2: { auto Jstatic = Eigen::Map>(J.derived().data()); return (Jstatic.row(0)).cross(Jstatic.row(1)).norm(); } + case 0: + case 3: { + AKANTU_EXCEPTION("This case is only to avoid compilation warnings"); + } } } return 0; // avoids a warning } /* -------------------------------------------------------------------------- */ template template inline void ElementClass::computeShapeDerivatives( - const Eigen::MatrixBase & J, const Eigen::MatrixBase & dnds, - Eigen::MatrixBase & shape_deriv) { + const Eigen::MatrixBase &J, const Eigen::MatrixBase &dnds, + Eigen::MatrixBase &shape_deriv) { shape_deriv = J.inverse() * dnds; } /* -------------------------------------------------------------------------- */ template inline void ElementClass::computeShapeDerivatives( - const Tensor3Base & J, const Tensor3Base & dnds, - Tensor3Base & shape_deriv) { + const Tensor3Base &J, const Tensor3Base &dnds, + Tensor3Base &shape_deriv) { auto nb_points = J.size(2); for (Int p = 0; p < nb_points; ++p) { - auto && J_ = J(p); - auto && dnds_ = dnds(p); - auto && dndx_ = shape_deriv(p); + auto &&J_ = J(p); + auto &&dnds_ = dnds(p); + auto &&dndx_ = shape_deriv(p); dndx_ = J_.inverse() * dnds_; // computeShapeDerivatives(J_, dnds_, dndx_); } } /* -------------------------------------------------------------------------- */ template template inline void ElementClass::computeNormalsOnNaturalCoordinates( - const Eigen::MatrixBase & coord, const Eigen::MatrixBase & f, - Eigen::MatrixBase & normals) { + const Eigen::MatrixBase &coord, const Eigen::MatrixBase &f, + Eigen::MatrixBase &normals) { auto dimension = normals.rows(); auto nb_points = coord.cols(); constexpr auto ndim = interpolation_property::natural_space_dimension; AKANTU_DEBUG_ASSERT((dimension - 1) == ndim, "cannot extract a normal because of dimension mismatch " << dimension - 1 << " " << ndim); Matrix J(dimension, ndim); for (Int p = 0; p < nb_points; ++p) { interpolation_element::gradientOnNaturalCoordinates(coord.col(p), f, J); if (dimension == 2) { normals.col(p) = Math::normal(J); } if (dimension == 3) { normals.col(p) = Math::normal(J.col(0), J.col(1)); } } } /* ------------------------------------------------------------------------- */ /** * In the non linear cases we need to iterate to find the natural coordinates *@f$\xi@f$ * provided real coordinates @f$x@f$. * * We want to solve: @f$ x- \phi(\xi) = 0@f$ with @f$\phi(\xi) = \sum_I N_I(\xi) *x_I@f$ * the mapping function which uses the nodal coordinates @f$x_I@f$. * * To that end we use the Newton method and the following series: * * @f$ \frac{\partial \phi(x_k)}{\partial \xi} \left( \xi_{k+1} - \xi_k \right) *= x - \phi(x_k)@f$ * * When we consider elements embedded in a dimension higher than them (2D *triangle in a 3D space for example) * @f$ J = \frac{\partial \phi(\xi_k)}{\partial \xi}@f$ is of dimension *@f$dim_{space} \times dim_{elem}@f$ which * is not invertible in most cases. Rather we can solve the problem: * * @f$ J^T J \left( \xi_{k+1} - \xi_k \right) = J^T \left( x - \phi(\xi_k) *\right) @f$ * * So that * * @f$ d\xi = \xi_{k+1} - \xi_k = (J^T J)^{-1} J^T \left( x - \phi(\xi_k) *\right) @f$ * * So that if the series converges we have: * * @f$ 0 = J^T \left( \phi(\xi_\infty) - x \right) @f$ * * And we see that this is ill-posed only if @f$ J^T x = 0@f$ which means that *the vector provided * is normal to any tangent which means it is outside of the element itself. * * @param real_coords: the real coordinates the natural coordinates are sought *for * @param node_coords: the coordinates of the nodes forming the element * @param natural_coords: output->the sought natural coordinates * @param spatial_dimension: spatial dimension of the problem * **/ template template *> inline void ElementClass::inverseMap( - const Eigen::MatrixBase & real_coords, - const Eigen::MatrixBase & node_coords, - const Eigen::MatrixBase & natural_coords_, Int max_iterations, + const Eigen::MatrixBase &real_coords, + const Eigen::MatrixBase &node_coords, + const Eigen::MatrixBase &natural_coords_, Int max_iterations, Real tolerance) { - auto & natural_coords = const_cast &>( + auto &natural_coords = const_cast &>( natural_coords_); // as advised by the Eigen developers auto spatial_dimension = real_coords.size(); constexpr auto dimension = getSpatialDimension(); // matrix copy of the real_coords // MatrixProxy mreal_coords(real_coords.data(), // spatial_dimension, // 1); // initial guess natural_coords.zero(); // real space coordinates provided by initial guess Vector physical_guess(spatial_dimension); // objective function f = real_coords - physical_guess Vector f(spatial_dimension); // G = J^t * J Matrix G(dimension, dimension); // F = G.inverse() * J^t Matrix F(spatial_dimension, dimension); // J^t Matrix Jt(spatial_dimension, dimension); // dxi = \xi_{k+1} - \xi in the iterative process Vector dxi(dimension); /* --------------------------- */ /* init before iteration loop */ /* --------------------------- */ // do interpolation auto update_f = [&f, &physical_guess, &natural_coords, &node_coords, - &real_coords, spatial_dimension]() { + &real_coords]() { physical_guess = interpolation_element::interpolateOnNaturalCoordinates( natural_coords, node_coords); // compute initial objective function value f = real_coords - // physical_guess f = real_coords - physical_guess; // compute initial error auto error = f.norm(); return error; }; auto inverse_map_error = update_f(); /* --------------------------- */ /* iteration loop */ /* --------------------------- */ Int iterations{0}; while (tolerance < inverse_map_error and iterations < max_iterations) { // compute J^t interpolation_element::gradientOnNaturalCoordinates(natural_coords, node_coords, Jt); // compute G G = Jt.transpose() * Jt; // compute F F = Jt * G.inverse(); // compute increment dxi = F.transpose() * f; // update our guess natural_coords += dxi; inverse_map_error = update_f(); iterations++; } if (iterations >= max_iterations) { AKANTU_EXCEPTION("The solver in inverse map did not converge"); } } /* -------------------------------------------------------------------------- */ template template *> inline void ElementClass::inverseMap( - const Eigen::MatrixBase & real_coords, - const Eigen::MatrixBase & node_coords, - const Eigen::MatrixBase & natural_coords_, Int max_iterations, + const Eigen::MatrixBase &real_coords, + const Eigen::MatrixBase &node_coords, + const Eigen::MatrixBase &natural_coords_, Int max_iterations, Real tolerance) { - auto & natural_coords = const_cast &>( + auto &natural_coords = const_cast &>( natural_coords_); // as advised by the Eigen developers auto nb_points = real_coords.cols(); for (Int p = 0; p < nb_points; ++p) { inverseMap(real_coords(p), node_coords, natural_coords(p), max_iterations, tolerance); } } } // namespace akantu #endif /* AKANTU_ELEMENT_CLASS_TMPL_HH_ */ diff --git a/src/fe_engine/element_classes/element_class_hexahedron_20_inline_impl.hh b/src/fe_engine/element_classes/element_class_hexahedron_20_inline_impl.hh index 397a237de..c5c9a558a 100644 --- a/src/fe_engine/element_classes/element_class_hexahedron_20_inline_impl.hh +++ b/src/fe_engine/element_classes/element_class_hexahedron_20_inline_impl.hh @@ -1,232 +1,232 @@ /** * @file element_class_hexahedron_20_inline_impl.hh * * @author Guillaume Anciaux * @author Mauro Corrado * @author Sacha Laffely * @author Nicolas Richart * @author Damien Scantamburlo * * @date creation: Tue Mar 31 2015 * @date last modification: Fri Feb 07 2020 * * @brief Specialization of the element_class class for the type _hexahedron_20 * * * @section LICENSE * * Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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 . * */ /** * @verbatim \y \z / | / 7-----|18--------6 /| | / /| / | | / / | 19 | | / 17 | / 15 | / / 14 / | | / / | 4-------16---/---5 | | | +----|------------\x | 3-------10-|-----2 | / | / 12 / 13 / | 11 | 9 | / | / |/ |/ 0--------8-------1 x y z * N0 -1 -1 -1 * N1 1 -1 -1 * N2 1 1 -1 * N3 -1 1 -1 * N4 -1 -1 1 * N5 1 -1 1 * N6 1 1 1 * N7 -1 1 1 * N8 0 -1 -1 * N9 1 0 -1 * N10 0 1 -1 * N11 -1 0 -1 * N12 -1 -1 0 * N13 1 -1 0 * N14 1 1 0 * N15 -1 1 0 * N16 0 -1 1 * N17 1 0 1 * N18 0 1 1 * N19 -1 0 1 * \endverbatim */ /* -------------------------------------------------------------------------- */ #include "element_class.hh" /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_hexahedron_20, _gt_hexahedron_20, _itp_serendip_hexahedron_20, _ek_regular, 3, _git_segment, 3); /* -------------------------------------------------------------------------- */ template <> template ::value> *> inline void InterpolationElement<_itp_serendip_hexahedron_20>::computeShapes( - const Eigen::MatrixBase & c, Eigen::MatrixBase & N) { + const Eigen::MatrixBase &c, Eigen::MatrixBase &N) { // Shape function , Natural coordinates N(0) = 0.125 * (1 - c(0)) * (1 - c(1)) * (1 - c(2)) * (-2 - c(0) - c(1) - c(2)); N(1) = 0.125 * (1 + c(0)) * (1 - c(1)) * (1 - c(2)) * (-2 + c(0) - c(1) - c(2)); N(2) = 0.125 * (1 + c(0)) * (1 + c(1)) * (1 - c(2)) * (-2 + c(0) + c(1) - c(2)); N(3) = 0.125 * (1 - c(0)) * (1 + c(1)) * (1 - c(2)) * (-2 - c(0) + c(1) - c(2)); N(4) = 0.125 * (1 - c(0)) * (1 - c(1)) * (1 + c(2)) * (-2 - c(0) - c(1) + c(2)); N(5) = 0.125 * (1 + c(0)) * (1 - c(1)) * (1 + c(2)) * (-2 + c(0) - c(1) + c(2)); N(6) = 0.125 * (1 + c(0)) * (1 + c(1)) * (1 + c(2)) * (-2 + c(0) + c(1) + c(2)); N(7) = 0.125 * (1 - c(0)) * (1 + c(1)) * (1 + c(2)) * (-2 - c(0) + c(1) + c(2)); N(8) = 0.25 * (1 - c(0) * c(0)) * (1 - c(1)) * (1 - c(2)); N(9) = 0.25 * (1 - c(1) * c(1)) * (1 + c(0)) * (1 - c(2)); N(10) = 0.25 * (1 - c(0) * c(0)) * (1 + c(1)) * (1 - c(2)); N(11) = 0.25 * (1 - c(1) * c(1)) * (1 - c(0)) * (1 - c(2)); N(12) = 0.25 * (1 - c(2) * c(2)) * (1 - c(0)) * (1 - c(1)); N(13) = 0.25 * (1 - c(2) * c(2)) * (1 + c(0)) * (1 - c(1)); N(14) = 0.25 * (1 - c(2) * c(2)) * (1 + c(0)) * (1 + c(1)); N(15) = 0.25 * (1 - c(2) * c(2)) * (1 - c(0)) * (1 + c(1)); N(16) = 0.25 * (1 - c(0) * c(0)) * (1 - c(1)) * (1 + c(2)); N(17) = 0.25 * (1 - c(1) * c(1)) * (1 + c(0)) * (1 + c(2)); N(18) = 0.25 * (1 - c(0) * c(0)) * (1 + c(1)) * (1 + c(2)); N(19) = 0.25 * (1 - c(1) * c(1)) * (1 - c(0)) * (1 + c(2)); } /* -------------------------------------------------------------------------- */ template <> template inline void InterpolationElement<_itp_serendip_hexahedron_20>::computeDNDS( - const Eigen::MatrixBase & c, Eigen::MatrixBase & dnds) { + const Eigen::MatrixBase &c, Eigen::MatrixBase &dnds) { // derivatives ddx dnds(0, 0) = 0.25 * (c(0) + 0.5 * (c(1) + c(2) + 1)) * (c(1) - 1) * (c(2) - 1); dnds(0, 1) = 0.25 * (c(0) - 0.5 * (c(1) + c(2) + 1)) * (c(1) - 1) * (c(2) - 1); dnds(0, 2) = -0.25 * (c(0) + 0.5 * (c(1) - c(2) - 1)) * (c(1) + 1) * (c(2) - 1); dnds(0, 3) = -0.25 * (c(0) - 0.5 * (c(1) - c(2) - 1)) * (c(1) + 1) * (c(2) - 1); dnds(0, 4) = -0.25 * (c(0) + 0.5 * (c(1) - c(2) + 1)) * (c(1) - 1) * (c(2) + 1); dnds(0, 5) = -0.25 * (c(0) - 0.5 * (c(1) - c(2) + 1)) * (c(1) - 1) * (c(2) + 1); dnds(0, 6) = 0.25 * (c(0) + 0.5 * (c(1) + c(2) - 1)) * (c(1) + 1) * (c(2) + 1); dnds(0, 7) = 0.25 * (c(0) - 0.5 * (c(1) + c(2) - 1)) * (c(1) + 1) * (c(2) + 1); dnds(0, 8) = -0.5 * c(0) * (c(1) - 1) * (c(2) - 1); dnds(0, 9) = 0.25 * (c(1) * c(1) - 1) * (c(2) - 1); dnds(0, 10) = 0.5 * c(0) * (c(1) + 1) * (c(2) - 1); dnds(0, 11) = -0.25 * (c(1) * c(1) - 1) * (c(2) - 1); dnds(0, 12) = -0.25 * (c(2) * c(2) - 1) * (c(1) - 1); dnds(0, 13) = 0.25 * (c(1) - 1) * (c(2) * c(2) - 1); dnds(0, 14) = -0.25 * (c(1) + 1) * (c(2) * c(2) - 1); dnds(0, 15) = 0.25 * (c(1) + 1) * (c(2) * c(2) - 1); dnds(0, 16) = 0.5 * c(0) * (c(1) - 1) * (c(2) + 1); dnds(0, 17) = -0.25 * (c(2) + 1) * (c(1) * c(1) - 1); dnds(0, 18) = -0.5 * c(0) * (c(1) + 1) * (c(2) + 1); dnds(0, 19) = 0.25 * (c(2) + 1) * (c(1) * c(1) - 1); // ddy dnds(1, 0) = 0.25 * (c(1) + 0.5 * (c(0) + c(2) + 1)) * (c(0) - 1) * (c(2) - 1); dnds(1, 1) = -0.25 * (c(1) - 0.5 * (c(0) - c(2) - 1)) * (c(0) + 1) * (c(2) - 1); dnds(1, 2) = -0.25 * (c(1) + 0.5 * (c(0) - c(2) - 1)) * (c(0) + 1) * (c(2) - 1); dnds(1, 3) = 0.25 * (c(1) - 0.5 * (c(0) + c(2) + 1)) * (c(0) - 1) * (c(2) - 1); dnds(1, 4) = -0.25 * (c(1) + 0.5 * (c(0) - c(2) + 1)) * (c(0) - 1) * (c(2) + 1); dnds(1, 5) = 0.25 * (c(1) - 0.5 * (c(0) + c(2) - 1)) * (c(0) + 1) * (c(2) + 1); dnds(1, 6) = 0.25 * (c(1) + 0.5 * (c(0) + c(2) - 1)) * (c(0) + 1) * (c(2) + 1); dnds(1, 7) = -0.25 * (c(1) - 0.5 * (c(0) - c(2) + 1)) * (c(0) - 1) * (c(2) + 1); dnds(1, 8) = -0.25 * (c(0) * c(0) - 1) * (c(2) - 1); dnds(1, 9) = 0.5 * c(1) * (c(0) + 1) * (c(2) - 1); dnds(1, 10) = 0.25 * (c(0) * c(0) - 1) * (c(2) - 1); dnds(1, 11) = -0.5 * c(1) * (c(0) - 1) * (c(2) - 1); dnds(1, 12) = -0.25 * (c(2) * c(2) - 1) * (c(0) - 1); dnds(1, 13) = 0.25 * (c(0) + 1) * (c(2) * c(2) - 1); dnds(1, 14) = -0.25 * (c(0) + 1) * (c(2) * c(2) - 1); dnds(1, 15) = 0.25 * (c(0) - 1) * (c(2) * c(2) - 1); dnds(1, 16) = 0.25 * (c(2) + 1) * (c(0) * c(0) - 1); dnds(1, 17) = -0.5 * c(1) * (c(0) + 1) * (c(2) + 1); dnds(1, 18) = -0.25 * (c(2) + 1) * (c(0) * c(0) - 1); dnds(1, 19) = 0.5 * c(1) * (c(0) - 1) * (c(2) + 1); // ddz dnds(2, 0) = 0.25 * (c(2) + 0.5 * (c(0) + c(1) + 1)) * (c(0) - 1) * (c(1) - 1); dnds(2, 1) = -0.25 * (c(2) - 0.5 * (c(0) - c(1) - 1)) * (c(0) + 1) * (c(1) - 1); dnds(2, 2) = 0.25 * (c(2) - 0.5 * (c(0) + c(1) - 1)) * (c(0) + 1) * (c(1) + 1); dnds(2, 3) = -0.25 * (c(2) + 0.5 * (c(0) - c(1) + 1)) * (c(0) - 1) * (c(1) + 1); dnds(2, 4) = 0.25 * (c(2) - 0.5 * (c(0) + c(1) + 1)) * (c(0) - 1) * (c(1) - 1); dnds(2, 5) = -0.25 * (c(2) + 0.5 * (c(0) - c(1) - 1)) * (c(0) + 1) * (c(1) - 1); dnds(2, 6) = 0.25 * (c(2) + 0.5 * (c(0) + c(1) - 1)) * (c(0) + 1) * (c(1) + 1); dnds(2, 7) = -0.25 * (c(2) - 0.5 * (c(0) - c(1) + 1)) * (c(0) - 1) * (c(1) + 1); dnds(2, 8) = -0.25 * (c(0) * c(0) - 1) * (c(1) - 1); dnds(2, 9) = 0.25 * (c(1) * c(1) - 1) * (c(0) + 1); dnds(2, 10) = 0.25 * (c(0) * c(0) - 1) * (c(1) + 1); dnds(2, 11) = -0.25 * (c(1) * c(1) - 1) * (c(0) - 1); dnds(2, 12) = -0.5 * c(2) * (c(1) - 1) * (c(0) - 1); dnds(2, 13) = 0.5 * c(2) * (c(0) + 1) * (c(1) - 1); dnds(2, 14) = -0.5 * c(2) * (c(0) + 1) * (c(1) + 1); dnds(2, 15) = 0.5 * c(2) * (c(0) - 1) * (c(1) + 1); dnds(2, 16) = 0.25 * (c(1) - 1) * (c(0) * c(0) - 1); dnds(2, 17) = -0.25 * (c(0) + 1) * (c(1) * c(1) - 1); dnds(2, 18) = -0.25 * (c(1) + 1) * (c(0) * c(0) - 1); dnds(2, 19) = 0.25 * (c(0) - 1) * (c(1) * c(1) - 1); } /* -------------------------------------------------------------------------- */ template <> template -constexpr inline Real GeometricalElement<_gt_hexahedron_20>::getInradius( - const Eigen::MatrixBase & coord) { +inline Real GeometricalElement<_gt_hexahedron_20>::getInradius( + const Eigen::MatrixBase &coord) { return GeometricalElement<_gt_hexahedron_8>::getInradius(coord) * 0.5; } } // namespace akantu diff --git a/src/fe_engine/element_classes/element_class_hexahedron_8_inline_impl.hh b/src/fe_engine/element_classes/element_class_hexahedron_8_inline_impl.hh index 464d3b88a..27cc5560c 100644 --- a/src/fe_engine/element_classes/element_class_hexahedron_8_inline_impl.hh +++ b/src/fe_engine/element_classes/element_class_hexahedron_8_inline_impl.hh @@ -1,226 +1,226 @@ /** * @file element_class_hexahedron_8_inline_impl.hh * * @author Guillaume Anciaux * @author Nicolas Richart * @author Peter Spijker * * @date creation: Mon Mar 14 2011 * @date last modification: Fri Feb 07 2020 * * @brief Specialization of the element_class class for the type _hexahedron_8 * * * @section LICENSE * * Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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 . * */ /** * @verbatim \zeta ^ (-1,1,1) | (1,1,1) 7---|------6 /| | /| / | | / | (-1,-1,1) 4----------5 | (1,-1,1) | | | | | | | | | | | | +---|-------> \xi | | / | | (-1,1,-1) | 3-/-----|--2 (1,1,-1) | / / | / |/ / |/ 0-/--------1 (-1,-1,-1) / (1,-1,-1) / \eta @endverbatim * * \f[ * \begin{array}{llll} * N1 = (1 - \xi) (1 - \eta) (1 - \zeta) / 8 * & \frac{\partial N1}{\partial \xi} = - (1 - \eta) (1 - \zeta) / 8 * & \frac{\partial N1}{\partial \eta} = - (1 - \xi) (1 - \zeta) / 8 * & \frac{\partial N1}{\partial \zeta} = - (1 - \xi) (1 - \eta) / 8 \\ * N2 = (1 + \xi) (1 - \eta) (1 - \zeta) / 8 * & \frac{\partial N2}{\partial \xi} = (1 - \eta) (1 - \zeta) / 8 * & \frac{\partial N2}{\partial \eta} = - (1 + \xi) (1 - \zeta) / 8 * & \frac{\partial N2}{\partial \zeta} = - (1 + \xi) (1 - \eta) / 8 \\ * N3 = (1 + \xi) (1 + \eta) (1 - \zeta) / 8 * & \frac{\partial N3}{\partial \xi} = (1 + \eta) (1 - \zeta) / 8 * & \frac{\partial N3}{\partial \eta} = (1 + \xi) (1 - \zeta) / 8 * & \frac{\partial N3}{\partial \zeta} = - (1 + \xi) (1 + \eta) / 8 \\ * N4 = (1 - \xi) (1 + \eta) (1 - \zeta) / 8 * & \frac{\partial N4}{\partial \xi} = - (1 + \eta) (1 - \zeta) / 8 * & \frac{\partial N4}{\partial \eta} = (1 - \xi) (1 - \zeta) / 8 * & \frac{\partial N4}{\partial \zeta} = - (1 - \xi) (1 + \eta) / 8 \\ * N5 = (1 - \xi) (1 - \eta) (1 + \zeta) / 8 * & \frac{\partial N5}{\partial \xi} = - (1 - \eta) (1 + \zeta) / 8 * & \frac{\partial N5}{\partial \eta} = - (1 - \xi) (1 + \zeta) / 8 * & \frac{\partial N5}{\partial \zeta} = (1 - \xi) (1 - \eta) / 8 \\ * N6 = (1 + \xi) (1 - \eta) (1 + \zeta) / 8 * & \frac{\partial N6}{\partial \xi} = (1 - \eta) (1 + \zeta) / 8 * & \frac{\partial N6}{\partial \eta} = - (1 + \xi) (1 + \zeta) / 8 * & \frac{\partial N6}{\partial \zeta} = (1 + \xi) (1 - \eta) / 8 \\ * N7 = (1 + \xi) (1 + \eta) (1 + \zeta) / 8 * & \frac{\partial N7}{\partial \xi} = (1 + \eta) (1 + \zeta) / 8 * & \frac{\partial N7}{\partial \eta} = (1 + \xi) (1 + \zeta) / 8 * & \frac{\partial N7}{\partial \zeta} = (1 + \xi) (1 + \eta) / 8 \\ * N8 = (1 - \xi) (1 + \eta) (1 + \zeta) / 8 * & \frac{\partial N8}{\partial \xi} = - (1 + \eta) (1 + \zeta) / 8 * & \frac{\partial N8}{\partial \eta} = (1 - \xi) (1 + \zeta) / 8 * & \frac{\partial N8}{\partial \zeta} = (1 - \xi) (1 + \eta) / 8 \\ * \end{array} * \f] * * @f{eqnarray*}{ * \xi_{q0} &=& -1/\sqrt{3} \qquad \eta_{q0} = -1/\sqrt{3} \qquad \zeta_{q0} = -1/\sqrt{3} \\ * \xi_{q1} &=& 1/\sqrt{3} \qquad \eta_{q1} = -1/\sqrt{3} \qquad \zeta_{q1} = -1/\sqrt{3} \\ * \xi_{q2} &=& 1/\sqrt{3} \qquad \eta_{q2} = 1/\sqrt{3} \qquad \zeta_{q2} = -1/\sqrt{3} \\ * \xi_{q3} &=& -1/\sqrt{3} \qquad \eta_{q3} = 1/\sqrt{3} \qquad \zeta_{q3} = -1/\sqrt{3} \\ * \xi_{q4} &=& -1/\sqrt{3} \qquad \eta_{q4} = -1/\sqrt{3} \qquad \zeta_{q4} = 1/\sqrt{3} \\ * \xi_{q5} &=& 1/\sqrt{3} \qquad \eta_{q5} = -1/\sqrt{3} \qquad \zeta_{q5} = 1/\sqrt{3} \\ * \xi_{q6} &=& 1/\sqrt{3} \qquad \eta_{q6} = 1/\sqrt{3} \qquad \zeta_{q6} = 1/\sqrt{3} \\ * \xi_{q7} &=& -1/\sqrt{3} \qquad \eta_{q7} = 1/\sqrt{3} \qquad \zeta_{q7} = 1/\sqrt{3} \\ * @f} */ /* -------------------------------------------------------------------------- */ #include "element_class.hh" /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_hexahedron_8, _gt_hexahedron_8, _itp_lagrange_hexahedron_8, _ek_regular, 3, _git_segment, 2); /* -------------------------------------------------------------------------- */ template <> template ::value> *> inline void InterpolationElement<_itp_lagrange_hexahedron_8>::computeShapes( - const Eigen::MatrixBase & c, Eigen::MatrixBase & N) { + const Eigen::MatrixBase &c, Eigen::MatrixBase &N) { /// Natural coordinates N(0) = .125 * (1 - c(0)) * (1 - c(1)) * (1 - c(2)); /// N1(q_0) N(1) = .125 * (1 + c(0)) * (1 - c(1)) * (1 - c(2)); /// N2(q_0) N(2) = .125 * (1 + c(0)) * (1 + c(1)) * (1 - c(2)); /// N3(q_0) N(3) = .125 * (1 - c(0)) * (1 + c(1)) * (1 - c(2)); /// N4(q_0) N(4) = .125 * (1 - c(0)) * (1 - c(1)) * (1 + c(2)); /// N5(q_0) N(5) = .125 * (1 + c(0)) * (1 - c(1)) * (1 + c(2)); /// N6(q_0) N(6) = .125 * (1 + c(0)) * (1 + c(1)) * (1 + c(2)); /// N7(q_0) N(7) = .125 * (1 - c(0)) * (1 + c(1)) * (1 + c(2)); /// N8(q_0) } /* -------------------------------------------------------------------------- */ template <> template inline void InterpolationElement<_itp_lagrange_hexahedron_8>::computeDNDS( - const Eigen::MatrixBase & c, Eigen::MatrixBase & dnds) { + const Eigen::MatrixBase &c, Eigen::MatrixBase &dnds) { /** * @f[ * dnds = \left( * \begin{array}{cccccccc} * \frac{\partial N1}{\partial \xi} & \frac{\partial N2}{\partial * \xi} * & \frac{\partial N3}{\partial \xi} & \frac{\partial * N4}{\partial \xi} * & \frac{\partial N5}{\partial \xi} & \frac{\partial * N6}{\partial \xi} * & \frac{\partial N7}{\partial \xi} & \frac{\partial * N8}{\partial \xi}\\ * \frac{\partial N1}{\partial \eta} & \frac{\partial N2}{\partial * \eta} * & \frac{\partial N3}{\partial \eta} & \frac{\partial * N4}{\partial \eta} * & \frac{\partial N5}{\partial \eta} & \frac{\partial * N6}{\partial \eta} * & \frac{\partial N7}{\partial \eta} & \frac{\partial * N8}{\partial \eta}\\ * \frac{\partial N1}{\partial \zeta} & \frac{\partial N2}{\partial * \zeta} * & \frac{\partial N3}{\partial \zeta} & \frac{\partial * N4}{\partial \zeta} * & \frac{\partial N5}{\partial \zeta} & \frac{\partial * N6}{\partial \zeta} * & \frac{\partial N7}{\partial \zeta} & \frac{\partial * N8}{\partial \zeta} * \end{array} * \right) * @f] */ dnds(0, 0) = -.125 * (1 - c(1)) * (1 - c(2)); dnds(0, 1) = .125 * (1 - c(1)) * (1 - c(2)); dnds(0, 2) = .125 * (1 + c(1)) * (1 - c(2)); dnds(0, 3) = -.125 * (1 + c(1)) * (1 - c(2)); dnds(0, 4) = -.125 * (1 - c(1)) * (1 + c(2)); dnds(0, 5) = .125 * (1 - c(1)) * (1 + c(2)); dnds(0, 6) = .125 * (1 + c(1)) * (1 + c(2)); dnds(0, 7) = -.125 * (1 + c(1)) * (1 + c(2)); dnds(1, 0) = -.125 * (1 - c(0)) * (1 - c(2)); dnds(1, 1) = -.125 * (1 + c(0)) * (1 - c(2)); dnds(1, 2) = .125 * (1 + c(0)) * (1 - c(2)); dnds(1, 3) = .125 * (1 - c(0)) * (1 - c(2)); dnds(1, 4) = -.125 * (1 - c(0)) * (1 + c(2)); dnds(1, 5) = -.125 * (1 + c(0)) * (1 + c(2)); dnds(1, 6) = .125 * (1 + c(0)) * (1 + c(2)); dnds(1, 7) = .125 * (1 - c(0)) * (1 + c(2)); dnds(2, 0) = -.125 * (1 - c(0)) * (1 - c(1)); dnds(2, 1) = -.125 * (1 + c(0)) * (1 - c(1)); dnds(2, 2) = -.125 * (1 + c(0)) * (1 + c(1)); dnds(2, 3) = -.125 * (1 - c(0)) * (1 + c(1)); dnds(2, 4) = .125 * (1 - c(0)) * (1 - c(1)); dnds(2, 5) = .125 * (1 + c(0)) * (1 - c(1)); dnds(2, 6) = .125 * (1 + c(0)) * (1 + c(1)); dnds(2, 7) = .125 * (1 - c(0)) * (1 + c(1)); } /* -------------------------------------------------------------------------- */ template <> template -constexpr inline Real GeometricalElement<_gt_hexahedron_8>::getInradius( - const Eigen::MatrixBase & X) { - auto && a = (X(0) - X(1)).norm(); - auto && b = (X(1) - X(2)).norm(); - auto && c = (X(2) - X(3)).norm(); - auto && d = (X(3) - X(0)).norm(); - auto && e = (X(0) - X(4)).norm(); - auto && f = (X(1) - X(5)).norm(); - auto && g = (X(2) - X(6)).norm(); - auto && h = (X(3) - X(7)).norm(); - auto && i = (X(4) - X(5)).norm(); - auto && j = (X(5) - X(6)).norm(); - auto && k = (X(6) - X(7)).norm(); - auto && l = (X(7) - X(4)).norm(); +inline Real GeometricalElement<_gt_hexahedron_8>::getInradius( + const Eigen::MatrixBase &X) { + auto &&a = (X(0) - X(1)).norm(); + auto &&b = (X(1) - X(2)).norm(); + auto &&c = (X(2) - X(3)).norm(); + auto &&d = (X(3) - X(0)).norm(); + auto &&e = (X(0) - X(4)).norm(); + auto &&f = (X(1) - X(5)).norm(); + auto &&g = (X(2) - X(6)).norm(); + auto &&h = (X(3) - X(7)).norm(); + auto &&i = (X(4) - X(5)).norm(); + auto &&j = (X(5) - X(6)).norm(); + auto &&k = (X(6) - X(7)).norm(); + auto &&l = (X(7) - X(4)).norm(); auto p = std::min({a, b, c, d, e, f, g, h, i, j, k, l}); return p; } } // namespace akantu diff --git a/src/fe_engine/element_classes/element_class_pentahedron_15_inline_impl.hh b/src/fe_engine/element_classes/element_class_pentahedron_15_inline_impl.hh index 47ea2452c..203c62629 100644 --- a/src/fe_engine/element_classes/element_class_pentahedron_15_inline_impl.hh +++ b/src/fe_engine/element_classes/element_class_pentahedron_15_inline_impl.hh @@ -1,186 +1,186 @@ /** * @file element_class_pentahedron_15_inline_impl.hh * * @author Guillaume Anciaux * @author Mauro Corrado * @author Sacha Laffely * @author Nicolas Richart * @author Damien Scantamburlo * * @date creation: Tue Mar 31 2015 * @date last modification: Fri Feb 07 2020 * * @brief Specialization of the element_class class for the type * _pentahedron_15 * * * @section LICENSE * * Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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 . * */ /** * \verbatim z ^ | | | 1 | /|\ |/ | \ 10 7 6 / | \ / | \ 4 2--8--0 | \ / / | \11 / 13 12 9---------->y | / \ / |/ \ / 5--14--3 / / / v x \endverbatim x y z * N0 -1 1 0 * N1 -1 0 1 * N2 -1 0 0 * N3 1 1 0 * N4 1 0 1 * N5 1 0 0 * N6 -1 0.5 0.5 * N7 -1 0 0.5 * N8 -1 0.5 0 * N9 0 1 0 * N10 0 0 1 * N11 0 0 0 * N12 1 0.5 0.5 * N13 1 0 0.5 * N14 1 0.5 0 */ /* -------------------------------------------------------------------------- */ #include "element_class.hh" /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_pentahedron_15, _gt_pentahedron_15, _itp_lagrange_pentahedron_15, _ek_regular, 3, _git_pentahedron, 2); /* -------------------------------------------------------------------------- */ template <> template ::value> *> inline void InterpolationElement<_itp_lagrange_pentahedron_15>::computeShapes( - const Eigen::MatrixBase & c, Eigen::MatrixBase & N) { - auto && x = c(0); - auto && y = c(1); - auto && z = c(2); + const Eigen::MatrixBase &c, Eigen::MatrixBase &N) { + auto &&x = c(0); + auto &&y = c(1); + auto &&z = c(2); // Shape Functions, Natural coordinates N(0) = 0.5 * y * (1 - x) * (2 * y - 2 - x); N(1) = 0.5 * z * (1 - x) * (2 * z - 2 - x); N(2) = 0.5 * (x - 1) * (1 - y - z) * (x + 2 * y + 2 * z); N(3) = 0.5 * y * (1 + x) * (2 * y - 2 + x); N(4) = 0.5 * z * (1 + x) * (2 * z - 2 + x); N(5) = 0.5 * (-x - 1) * (1 - y - z) * (-x + 2 * y + 2 * z); N(6) = 2.0 * y * z * (1 - x); N(7) = 2.0 * z * (1 - y - z) * (1 - x); N(8) = 2.0 * y * (1 - x) * (1 - y - z); N(9) = y * (1 - x * x); N(10) = z * (1 - x * x); N(11) = (1 - y - z) * (1 - x * x); N(12) = 2.0 * y * z * (1 + x); N(13) = 2.0 * z * (1 - y - z) * (1 + x); N(14) = 2.0 * y * (1 - y - z) * (1 + x); } /* -------------------------------------------------------------------------- */ template <> template inline void InterpolationElement<_itp_lagrange_pentahedron_15>::computeDNDS( - const Eigen::MatrixBase & c, Eigen::MatrixBase & dnds) { - auto && x = c(0); - auto && y = c(1); - auto && z = c(2); + const Eigen::MatrixBase &c, Eigen::MatrixBase &dnds) { + auto &&x = c(0); + auto &&y = c(1); + auto &&z = c(2); // ddx dnds(0, 0) = 0.5 * y * (2 * x - 2 * y + 1); dnds(0, 1) = 0.5 * z * (2 * x - 2 * z + 1); dnds(0, 2) = -0.5 * (2 * x + 2 * y + 2 * z - 1) * (y + z - 1); dnds(0, 3) = 0.5 * y * (2 * x + 2 * y - 1); dnds(0, 4) = 0.5 * z * (2 * x + 2 * z - 1); dnds(0, 5) = -0.5 * (y + z - 1) * (2 * x - 2 * y - 2 * z + 1); dnds(0, 6) = -2.0 * y * z; dnds(0, 7) = 2.0 * z * (y + z - 1); dnds(0, 8) = 2.0 * y * (y + z - 1); dnds(0, 9) = -2.0 * x * y; dnds(0, 10) = -2.0 * x * z; dnds(0, 11) = 2.0 * x * (y + z - 1); dnds(0, 12) = 2.0 * y * z; dnds(0, 13) = -2.0 * z * (y + z - 1); dnds(0, 14) = -2.0 * y * (y + z - 1); // ddy dnds(1, 0) = -0.5 * (x - 1) * (4 * y - x - 2); dnds(1, 1) = 0.0; dnds(1, 2) = -0.5 * (x - 1) * (4 * y + x + 2 * (2 * z - 1)); dnds(1, 3) = 0.5 * (x + 1) * (4 * y + x - 2); dnds(1, 4) = 0.0; dnds(1, 5) = 0.5 * (x + 1) * (4 * y - x + 2 * (2 * z - 1)); dnds(1, 6) = -2.0 * (x - 1) * z; dnds(1, 7) = 2.0 * z * (x - 1); dnds(1, 8) = 2.0 * (2 * y + z - 1) * (x - 1); dnds(1, 9) = -(x * x - 1); dnds(1, 10) = 0.0; dnds(1, 11) = (x * x - 1); dnds(1, 12) = 2.0 * z * (x + 1); dnds(1, 13) = -2.0 * z * (x + 1); dnds(1, 14) = -2.0 * (2 * y + z - 1) * (x + 1); // ddz dnds(2, 0) = 0.0; dnds(2, 1) = -0.5 * (x - 1) * (4 * z - x - 2); dnds(2, 2) = -0.5 * (x - 1) * (4 * z + x + 2 * (2 * y - 1)); dnds(2, 3) = 0.0; dnds(2, 4) = 0.5 * (x + 1) * (4 * z + x - 2); dnds(2, 5) = 0.5 * (x + 1) * (4 * z - x + 2 * (2 * y - 1)); dnds(2, 6) = -2.0 * (x - 1) * y; dnds(2, 7) = 2.0 * (x - 1) * (2 * z + y - 1); dnds(2, 8) = 2.0 * y * (x - 1); dnds(2, 9) = 0.0; dnds(2, 10) = -(x * x - 1); dnds(2, 11) = (x * x - 1); dnds(2, 12) = 2.0 * (x + 1) * y; dnds(2, 13) = -2.0 * (x + 1) * (2 * z + y - 1); dnds(2, 14) = -2.0 * (x + 1) * y; } /* -------------------------------------------------------------------------- */ template <> template -constexpr inline Real GeometricalElement<_gt_pentahedron_15>::getInradius( - const Eigen::MatrixBase & coord) { +inline Real GeometricalElement<_gt_pentahedron_15>::getInradius( + const Eigen::MatrixBase &coord) { return GeometricalElement<_gt_pentahedron_6>::getInradius(coord) * 0.5; } } // namespace akantu diff --git a/src/fe_engine/element_classes/element_class_pentahedron_6_inline_impl.hh b/src/fe_engine/element_classes/element_class_pentahedron_6_inline_impl.hh index 93cf4ef2e..04365f439 100644 --- a/src/fe_engine/element_classes/element_class_pentahedron_6_inline_impl.hh +++ b/src/fe_engine/element_classes/element_class_pentahedron_6_inline_impl.hh @@ -1,142 +1,142 @@ /** * @file element_class_pentahedron_6_inline_impl.hh * * @author Guillaume Anciaux * @author Marion Estelle Chambart * @author Mauro Corrado * @author Thomas Menouillard * @author Nicolas Richart * * @date creation: Mon Mar 14 2011 * @date last modification: Tue Sep 29 2020 * * @brief Specialization of the element_class class for the type _pentahedron_6 * * * @section LICENSE * * Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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 . * */ /** * @verbatim /z | | | 1 | /|\ |/ | \ / | \ / | \ / | \ 4 2-----0 | \ / / | \/ / | \ /----------/y | / \ / |/ \ / 5---.--3 / / / \x x y z * N0 -1 1 0 * N1 -1 0 1 * N2 -1 0 0 * N3 1 1 0 * N4 1 0 1 * N5 1 0 0 \endverbatim */ /* -------------------------------------------------------------------------- */ #include "element_class.hh" /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_pentahedron_6, _gt_pentahedron_6, _itp_lagrange_pentahedron_6, _ek_regular, 3, _git_pentahedron, 1); /* -------------------------------------------------------------------------- */ template <> template ::value> *> inline void InterpolationElement<_itp_lagrange_pentahedron_6>::computeShapes( - const Eigen::MatrixBase & c, Eigen::MatrixBase & N) { + const Eigen::MatrixBase &c, Eigen::MatrixBase &N) { /// Natural coordinates N(0) = 0.5 * c(1) * (1 - c(0)); // N1(q) N(1) = 0.5 * c(2) * (1 - c(0)); // N2(q) N(2) = 0.5 * (1 - c(1) - c(2)) * (1 - c(0)); // N3(q) N(3) = 0.5 * c(1) * (1 + c(0)); // N4(q) N(4) = 0.5 * c(2) * (1 + c(0)); // N5(q) N(5) = 0.5 * (1 - c(1) - c(2)) * (1 + c(0)); // N6(q) } /* -------------------------------------------------------------------------- */ template <> template inline void InterpolationElement<_itp_lagrange_pentahedron_6>::computeDNDS( - const Eigen::MatrixBase & c, Eigen::MatrixBase & dnds) { + const Eigen::MatrixBase &c, Eigen::MatrixBase &dnds) { dnds(0, 0) = -0.5 * c(1); dnds(0, 1) = -0.5 * c(2); dnds(0, 2) = -0.5 * (1 - c(1) - c(2)); dnds(0, 3) = 0.5 * c(1); dnds(0, 4) = 0.5 * c(2); dnds(0, 5) = 0.5 * (1 - c(1) - c(2)); dnds(1, 0) = 0.5 * (1 - c(0)); dnds(1, 1) = 0.0; dnds(1, 2) = -0.5 * (1 - c(0)); dnds(1, 3) = 0.5 * (1 + c(0)); dnds(1, 4) = 0.0; dnds(1, 5) = -0.5 * (1 + c(0)); dnds(2, 0) = 0.0; dnds(2, 1) = 0.5 * (1 - c(0)); dnds(2, 2) = -0.5 * (1 - c(0)); dnds(2, 3) = 0.0; dnds(2, 4) = 0.5 * (1 + c(0)); dnds(2, 5) = -0.5 * (1 + c(0)); } /* -------------------------------------------------------------------------- */ template <> template -constexpr inline Real GeometricalElement<_gt_pentahedron_6>::getInradius( - const Eigen::MatrixBase & coord) { - auto && u0 = coord.col(0); - auto && u1 = coord.col(1); - auto && u2 = coord.col(2); - auto && u3 = coord.col(3); - auto && u4 = coord.col(4); - auto && u5 = coord.col(5); +inline Real GeometricalElement<_gt_pentahedron_6>::getInradius( + const Eigen::MatrixBase &coord) { + auto &&u0 = coord.col(0); + auto &&u1 = coord.col(1); + auto &&u2 = coord.col(2); + auto &&u3 = coord.col(3); + auto &&u4 = coord.col(4); + auto &&u5 = coord.col(5); auto inradius_triangle_1 = Math::triangle_inradius(u0, u1, u2); auto inradius_triangle_2 = Math::triangle_inradius(u3, u4, u5); auto d1 = (u3 - u0).norm() * 0.5; auto d2 = (u5 - u2).norm() * 0.5; auto d3 = (u4 - u1).norm() * 0.5; auto p = 2. * std::min({inradius_triangle_1, inradius_triangle_2, d1, d2, d3}); return p; } } // namespace akantu diff --git a/src/fe_engine/element_classes/element_class_point_1_inline_impl.hh b/src/fe_engine/element_classes/element_class_point_1_inline_impl.hh index 998143563..ac4747202 100644 --- a/src/fe_engine/element_classes/element_class_point_1_inline_impl.hh +++ b/src/fe_engine/element_classes/element_class_point_1_inline_impl.hh @@ -1,96 +1,96 @@ /** * @file element_class_point_1_inline_impl.hh * * @author Dana Christen * @author Nicolas Richart * @author Marco Vocialta * * @date creation: Fri Jun 18 2010 * @date last modification: Fri Feb 28 2020 * * @brief Specialization of the element_class class for the type _point_1 * * * @section LICENSE * * Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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 . * */ /** * @verbatim x (0) @endverbatim * * @f{eqnarray*}{ * N1 &=& 1 * @f} * * @f{eqnarray*}{ * q_0 &=& 0 * @f} */ /* -------------------------------------------------------------------------- */ #include "element_class.hh" /* -------------------------------------------------------------------------- */ namespace akantu { AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_point_1, _gt_point, _itp_lagrange_point_1, _ek_regular, 0, _git_point, 1); template <> template inline void ElementClass<_point_1, _ek_regular>::computeNormalsOnNaturalCoordinates( const Eigen::MatrixBase & /*coord*/, const Eigen::MatrixBase & /*f*/, Eigen::MatrixBase & /*normals*/) {} /* --------------r------------------------------------------------------------ */ template <> template ::value> *> inline void InterpolationElement<_itp_lagrange_point_1>::computeShapes( const Eigen::MatrixBase & /*natural_coords*/, - Eigen::MatrixBase & N) { + Eigen::MatrixBase &N) { N(0) = 1; /// N1(q_0) } /* -------------------------------------------------------------------------- */ template <> template inline void InterpolationElement<_itp_lagrange_point_1>::computeDNDS( const Eigen::MatrixBase & /*natural_coords*/, Eigen::MatrixBase & /*dnds*/) {} /* -------------------------------------------------------------------------- */ template <> template inline Real InterpolationElement<_itp_lagrange_point_1>::computeSpecialJacobian( const Eigen::MatrixBase & /*J*/) { return 0.; } /* -------------------------------------------------------------------------- */ template <> template -constexpr inline Real GeometricalElement<_gt_point>::getInradius( +inline Real GeometricalElement<_gt_point>::getInradius( const Eigen::MatrixBase & /*coord*/) { return 0.; } } // namespace akantu diff --git a/src/fe_engine/element_classes/element_class_quadrangle_4_inline_impl.hh b/src/fe_engine/element_classes/element_class_quadrangle_4_inline_impl.hh index d8303fcc6..011cea5c8 100644 --- a/src/fe_engine/element_classes/element_class_quadrangle_4_inline_impl.hh +++ b/src/fe_engine/element_classes/element_class_quadrangle_4_inline_impl.hh @@ -1,170 +1,170 @@ /** * @file element_class_quadrangle_4_inline_impl.hh * * @author Mohit Pundir * @author Nicolas Richart * * @date creation: Mon Dec 13 2010 * @date last modification: Fri Dec 11 2020 * * @brief Specialization of the element_class class for the type _quadrangle_4 * * * @section LICENSE * * Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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 . * */ /** * @verbatim \eta ^ (-1,1) | (1,1) x---------x | | | | | | --|---------|-----> \xi | | | | | | x---------x (-1,-1) | (1,-1) @endverbatim * * @f[ * \begin{array}{lll} * N1 = (1 - \xi) (1 - \eta) / 4 * & \frac{\partial N1}{\partial \xi} = - (1 - \eta) / 4 * & \frac{\partial N1}{\partial \eta} = - (1 - \xi) / 4 \\ * N2 = (1 + \xi) (1 - \eta) / 4 \\ * & \frac{\partial N2}{\partial \xi} = (1 - \eta) / 4 * & \frac{\partial N2}{\partial \eta} = - (1 + \xi) / 4 \\ * N3 = (1 + \xi) (1 + \eta) / 4 \\ * & \frac{\partial N3}{\partial \xi} = (1 + \eta) / 4 * & \frac{\partial N3}{\partial \eta} = (1 + \xi) / 4 \\ * N4 = (1 - \xi) (1 + \eta) / 4 * & \frac{\partial N4}{\partial \xi} = - (1 + \eta) / 4 * & \frac{\partial N4}{\partial \eta} = (1 - \xi) / 4 \\ * \end{array} * @f] * * @f{eqnarray*}{ * \xi_{q0} &=& 0 \qquad \eta_{q0} = 0 * @f} */ /* -------------------------------------------------------------------------- */ #include "element_class.hh" /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_quadrangle_4, _gt_quadrangle_4, _itp_lagrange_quadrangle_4, _ek_regular, 2, _git_segment, 2); /* -------------------------------------------------------------------------- */ template <> template ::value> *> inline void InterpolationElement<_itp_lagrange_quadrangle_4>::computeShapes( - const Eigen::MatrixBase & c, Eigen::MatrixBase & N) { + const Eigen::MatrixBase &c, Eigen::MatrixBase &N) { N(0) = 1. / 4. * (1. - c(0)) * (1. - c(1)); /// N1(q_0) N(1) = 1. / 4. * (1. + c(0)) * (1. - c(1)); /// N2(q_0) N(2) = 1. / 4. * (1. + c(0)) * (1. + c(1)); /// N3(q_0) N(3) = 1. / 4. * (1. - c(0)) * (1. + c(1)); /// N4(q_0) } /* -------------------------------------------------------------------------- */ template <> template inline void InterpolationElement<_itp_lagrange_quadrangle_4>::computeDNDS( - const Eigen::MatrixBase & c, Eigen::MatrixBase & dnds) { + const Eigen::MatrixBase &c, Eigen::MatrixBase &dnds) { /** * @f[ * dnds = \left( * \begin{array}{cccc} * \frac{\partial N1}{\partial \xi} & \frac{\partial N2}{\partial * \xi} * & \frac{\partial N3}{\partial \xi} & \frac{\partial * N4}{\partial \xi}\\ * \frac{\partial N1}{\partial \eta} & \frac{\partial N2}{\partial * \eta} * & \frac{\partial N3}{\partial \eta} & \frac{\partial * N4}{\partial \eta} * \end{array} * \right) * @f] */ dnds(0, 0) = -1. / 4. * (1. - c(1)); dnds(0, 1) = 1. / 4. * (1. - c(1)); dnds(0, 2) = 1. / 4. * (1. + c(1)); dnds(0, 3) = -1. / 4. * (1. + c(1)); dnds(1, 0) = -1. / 4. * (1. - c(0)); dnds(1, 1) = -1. / 4. * (1. + c(0)); dnds(1, 2) = 1. / 4. * (1. + c(0)); dnds(1, 3) = 1. / 4. * (1. - c(0)); } /* -------------------------------------------------------------------------- */ template <> template inline void InterpolationElement<_itp_lagrange_quadrangle_4>::computeD2NDS2( - const vector_type & /*c*/, matrix_type & d2nds2) { + const vector_type & /*c*/, matrix_type &d2nds2) { d2nds2.zero(); d2nds2(1, 0) = 1. / 4.; d2nds2(1, 1) = -1. / 4.; d2nds2(1, 2) = 1. / 4.; d2nds2(1, 3) = -1. / 4.; d2nds2(2, 0) = 1. / 4.; d2nds2(2, 1) = -1. / 4.; d2nds2(2, 2) = 1. / 4.; d2nds2(2, 3) = -1. / 4.; } /* -------------------------------------------------------------------------- */ template <> template -constexpr inline Real GeometricalElement<_gt_quadrangle_4>::getInradius( - const Eigen::MatrixBase & coord) { - auto && u0 = coord.col(0); - auto && u1 = coord.col(1); - auto && u2 = coord.col(2); - auto && u3 = coord.col(3); +inline Real GeometricalElement<_gt_quadrangle_4>::getInradius( + const Eigen::MatrixBase &coord) { + auto &&u0 = coord.col(0); + auto &&u1 = coord.col(1); + auto &&u2 = coord.col(2); + auto &&u3 = coord.col(3); Real a = (u0 - u1).norm(); Real b = (u1 - u2).norm(); Real c = (u2 - u3).norm(); Real d = (u3 - u0).norm(); // Real septimetre = (a + b + c + d) / 2.; // Real p = Math::distance_2d(coord + 0, coord + 4); // Real q = Math::distance_2d(coord + 2, coord + 6); // Real area = sqrt(4*(p*p * q*q) - (a*a + b*b + c*c + d*d)*(a*a + c*c - b*b - // d*d)) / 4.; // Real h = sqrt(area); // to get a length // Real h = area / septimetre; // formula of inradius for circumscritable // quadrelateral Real h = std::min({a, b, c, d}); return h; } } // namespace akantu diff --git a/src/fe_engine/element_classes/element_class_quadrangle_8_inline_impl.hh b/src/fe_engine/element_classes/element_class_quadrangle_8_inline_impl.hh index 3636c31e5..52d16d869 100644 --- a/src/fe_engine/element_classes/element_class_quadrangle_8_inline_impl.hh +++ b/src/fe_engine/element_classes/element_class_quadrangle_8_inline_impl.hh @@ -1,181 +1,181 @@ /** * @file element_class_quadrangle_8_inline_impl.hh * * @author Nicolas Richart * * @date creation: Wed May 18 2011 * @date last modification: Tue Sep 29 2020 * * @brief Specialization of the ElementClass for the _quadrangle_8 * * * @section LICENSE * * Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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 . * */ /** * @verbatim \eta ^ | (-1,1) (0,1) (1,1) x-------x-------x | | | | | | | | | (-1,0)| | |(1,0) ----x---------------X-----> \xi | | | | | | | | | | | | x-------x-------x (-1,-1) (0,-1) (1,-1) | @endverbatim * * @f[ * \begin{array}{lll} * N1 = (1 - \xi) (1 - \eta)(- 1 - \xi - \eta) / 4 * & \frac{\partial N1}{\partial \xi} = (1 - \eta)(2 \xi + \eta) / 4 * & \frac{\partial N1}{\partial \eta} = (1 - \xi)(\xi + 2 \eta) / 4 \\ * N2 = (1 + \xi) (1 - \eta)(- 1 + \xi - \eta) / 4 \\ * & \frac{\partial N2}{\partial \xi} = (1 - \eta)(2 \xi - \eta) / 4 * & \frac{\partial N2}{\partial \eta} = - (1 + \xi)(\xi - 2 \eta) / 4 \\ * N3 = (1 + \xi) (1 + \eta)(- 1 + \xi + \eta) / 4 \\ * & \frac{\partial N3}{\partial \xi} = (1 + \eta)(2 \xi + \eta) / 4 * & \frac{\partial N3}{\partial \eta} = (1 + \xi)(\xi + 2 \eta) / 4 \\ * N4 = (1 - \xi) (1 + \eta)(- 1 - \xi + \eta) / 4 * & \frac{\partial N4}{\partial \xi} = (1 + \eta)(2 \xi - \eta) / 4 * & \frac{\partial N4}{\partial \eta} = - (1 - \xi)(\xi - 2 \eta) / 4 \\ * N5 = (1 - \xi^2) (1 - \eta) / 2 * & \frac{\partial N1}{\partial \xi} = - \xi (1 - \eta) * & \frac{\partial N1}{\partial \eta} = - (1 - \xi^2) / 2 \\ * N6 = (1 + \xi) (1 - \eta^2) / 2 \\ * & \frac{\partial N2}{\partial \xi} = (1 - \eta^2) / 2 * & \frac{\partial N2}{\partial \eta} = - \eta (1 + \xi) \\ * N7 = (1 - \xi^2) (1 + \eta) / 2 \\ * & \frac{\partial N3}{\partial \xi} = - \xi (1 + \eta) * & \frac{\partial N3}{\partial \eta} = (1 - \xi^2) / 2 \\ * N8 = (1 - \xi) (1 - \eta^2) / 2 * & \frac{\partial N4}{\partial \xi} = - (1 - \eta^2) / 2 * & \frac{\partial N4}{\partial \eta} = - \eta (1 - \xi) \\ * \end{array} * @f] * * @f{eqnarray*}{ * \xi_{q0} &=& 0 \qquad \eta_{q0} = 0 * @f} */ /* -------------------------------------------------------------------------- */ #include "element_class.hh" /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_quadrangle_8, _gt_quadrangle_8, _itp_serendip_quadrangle_8, _ek_regular, 2, _git_segment, 3); /* -------------------------------------------------------------------------- */ template <> template ::value> *> inline void InterpolationElement<_itp_serendip_quadrangle_8>::computeShapes( const Eigen::MatrixBase &c, Eigen::MatrixBase &N) { /// Natural coordinates const Real xi = c(0); const Real eta = c(1); N(0) = .25 * (1 - xi) * (1 - eta) * (-1 - xi - eta); N(1) = .25 * (1 + xi) * (1 - eta) * (-1 + xi - eta); N(2) = .25 * (1 + xi) * (1 + eta) * (-1 + xi + eta); N(3) = .25 * (1 - xi) * (1 + eta) * (-1 - xi + eta); N(4) = .5 * (1 - xi * xi) * (1 - eta); N(5) = .5 * (1 + xi) * (1 - eta * eta); N(6) = .5 * (1 - xi * xi) * (1 + eta); N(7) = .5 * (1 - xi) * (1 - eta * eta); } /* -------------------------------------------------------------------------- */ template <> template inline void InterpolationElement<_itp_serendip_quadrangle_8>::computeDNDS( const Eigen::MatrixBase &c, Eigen::MatrixBase &dnds) { const Real xi = c(0); const Real eta = c(1); /// dN/dxi dnds(0, 0) = .25 * (1 - eta) * (2 * xi + eta); dnds(0, 1) = .25 * (1 - eta) * (2 * xi - eta); dnds(0, 2) = .25 * (1 + eta) * (2 * xi + eta); dnds(0, 3) = .25 * (1 + eta) * (2 * xi - eta); dnds(0, 4) = -xi * (1 - eta); dnds(0, 5) = .5 * (1 - eta * eta); dnds(0, 6) = -xi * (1 + eta); dnds(0, 7) = -.5 * (1 - eta * eta); /// dN/deta dnds(1, 0) = .25 * (1 - xi) * (2 * eta + xi); dnds(1, 1) = .25 * (1 + xi) * (2 * eta - xi); dnds(1, 2) = .25 * (1 + xi) * (2 * eta + xi); dnds(1, 3) = .25 * (1 - xi) * (2 * eta - xi); dnds(1, 4) = -.5 * (1 - xi * xi); dnds(1, 5) = -eta * (1 + xi); dnds(1, 6) = .5 * (1 - xi * xi); dnds(1, 7) = -eta * (1 - xi); } /* -------------------------------------------------------------------------- */ template <> template -constexpr inline Real GeometricalElement<_gt_quadrangle_8>::getInradius( +inline Real GeometricalElement<_gt_quadrangle_8>::getInradius( const Eigen::MatrixBase &coord) { auto &&u0 = coord.col(0); auto &&u1 = coord.col(1); auto &&u2 = coord.col(2); auto &&u3 = coord.col(3); auto &&u4 = coord.col(4); auto &&u5 = coord.col(5); auto &&u6 = coord.col(6); auto &&u7 = coord.col(7); Real a = (u0 - u4).norm(); Real b = (u4 - u1).norm(); Real h = std::min(a, b); a = (u1 - u5).norm(); b = (u5 - u2).norm(); h = std::min(h, std::min(a, b)); a = (u2 - u6).norm(); b = (u6 - u3).norm(); h = std::min(h, std::min(a, b)); a = (u3 - u7).norm(); b = (u7 - u0).norm(); h = std::min(h, std::min(a, b)); return h; } } // namespace akantu diff --git a/src/fe_engine/element_classes/element_class_segment_2_inline_impl.hh b/src/fe_engine/element_classes/element_class_segment_2_inline_impl.hh index f122b03a7..a1e40bb13 100644 --- a/src/fe_engine/element_classes/element_class_segment_2_inline_impl.hh +++ b/src/fe_engine/element_classes/element_class_segment_2_inline_impl.hh @@ -1,115 +1,115 @@ /** * @file element_class_segment_2_inline_impl.hh * * @author Emil Gallyamov * @author Mohit Pundir * @author Nicolas Richart * * @date creation: Fri Jul 16 2010 * @date last modification: Fri Dec 11 2020 * * @brief Specialization of the element_class class for the type _segment_2 * * * @section LICENSE * * Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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 . * */ /** * @verbatim q --x--------|--------x---> x -1 0 1 @endverbatim * * @f{eqnarray*}{ * w_1(x) &=& 1/2(1 - x) \\ * w_2(x) &=& 1/2(1 + x) * @f} * * @f{eqnarray*}{ * x_{q} &=& 0 * @f} */ /* -------------------------------------------------------------------------- */ #include "element_class.hh" /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_segment_2, _gt_segment_2, _itp_lagrange_segment_2, _ek_regular, 1, _git_segment, 1); /* -------------------------------------------------------------------------- */ template <> template ::value> *> inline void InterpolationElement<_itp_lagrange_segment_2>::computeShapes( - const Eigen::MatrixBase & natural_coords, Eigen::MatrixBase & N) { + const Eigen::MatrixBase &natural_coords, Eigen::MatrixBase &N) { /// natural coordinate Real c = natural_coords(0); /// shape functions N(0) = 0.5 * (1 - c); N(1) = 0.5 * (1 + c); } /* -------------------------------------------------------------------------- */ template <> template inline void InterpolationElement<_itp_lagrange_segment_2>::computeDNDS( const Eigen::MatrixBase & /*natural_coords*/, - Eigen::MatrixBase & dnds) { + Eigen::MatrixBase &dnds) { /// dN1/de dnds(0, 0) = -.5; /// dN2/de dnds(0, 1) = .5; } /* -------------------------------------------------------------------------- */ template <> template inline void InterpolationElement<_itp_lagrange_segment_2>::computeD2NDS2( - const vector_type & /*natural_coords*/, matrix_type & d2nds2) { + const vector_type & /*natural_coords*/, matrix_type &d2nds2) { d2nds2.zero(); } /* -------------------------------------------------------------------------- */ template <> template -constexpr inline Real GeometricalElement<_gt_segment_2>::getInradius( - const Eigen::MatrixBase & coord) { +inline Real GeometricalElement<_gt_segment_2>::getInradius( + const Eigen::MatrixBase &coord) { return (coord.col(1) - coord.col(0)).norm(); } /* -------------------------------------------------------------------------- */ template <> template -inline void GeometricalElement<_gt_segment_2>::getNormal( - const Eigen::MatrixBase & coord, Eigen::MatrixBase & normal) { - AKANTU_DEBUG_ASSERT(normal.size() == 2, - "The normal is only uniquely defined in 2D"); +inline void +GeometricalElement<_gt_segment_2>::getNormal(const Eigen::MatrixBase &coord, + Eigen::MatrixBase &normal) { + assert(normal.size() == 2 && "The normal is only uniquely defined in 2D"); Math::normal(coord.col(0) - coord.col(1), normal); } /* -------------------------------------------------------------------------- */ } // namespace akantu diff --git a/src/fe_engine/element_classes/element_class_segment_3_inline_impl.hh b/src/fe_engine/element_classes/element_class_segment_3_inline_impl.hh index b0b672d00..433acb36f 100644 --- a/src/fe_engine/element_classes/element_class_segment_3_inline_impl.hh +++ b/src/fe_engine/element_classes/element_class_segment_3_inline_impl.hh @@ -1,117 +1,116 @@ /** * @file element_class_segment_3_inline_impl.hh * * @author Emil Gallyamov * @author Nicolas Richart * * @date creation: Fri Jul 16 2010 * @date last modification: Wed Dec 09 2020 * * @brief Specialization of the element_class class for the type _segment_3 * * * @section LICENSE * * Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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 . * */ /** * @verbatim -1 0 1 -----x---------x---------x-----> x 1 3 2 @endverbatim * * * @f[ * \begin{array}{lll} * x_{1} = -1 & x_{2} = 1 & x_{3} = 0 * \end{array} * @f] * * @f[ * \begin{array}{ll} * w_1(x) = \frac{x}{2}(x - 1) & w'_1(x) = x - \frac{1}{2}\\ * w_2(x) = \frac{x}{2}(x + 1) & w'_2(x) = x + \frac{1}{2}\\ * w_3(x) = 1-x^2 & w'_3(x) = -2x * \end{array} * @f] * * @f[ * \begin{array}{ll} * x_{q1} = -1/\sqrt{3} & x_{q2} = 1/\sqrt{3} * \end{array} * @f] */ /* -------------------------------------------------------------------------- */ #include "element_class.hh" /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_segment_3, _gt_segment_3, _itp_lagrange_segment_3, _ek_regular, 1, _git_segment, 2); /* -------------------------------------------------------------------------- */ template <> template ::value> *> inline void InterpolationElement<_itp_lagrange_segment_3>::computeShapes( - const Eigen::MatrixBase & natural_coords, Eigen::MatrixBase & N) { + const Eigen::MatrixBase &natural_coords, Eigen::MatrixBase &N) { Real c = natural_coords(0); N(0) = (c - 1) * c / 2; N(1) = (c + 1) * c / 2; N(2) = 1 - c * c; } /* -------------------------------------------------------------------------- */ template <> template inline void InterpolationElement<_itp_lagrange_segment_3>::computeDNDS( - const Eigen::MatrixBase & natural_coords, - Eigen::MatrixBase & dnds) { + const Eigen::MatrixBase &natural_coords, Eigen::MatrixBase &dnds) { Real c = natural_coords(0); dnds(0, 0) = c - .5; dnds(0, 1) = c + .5; dnds(0, 2) = -2 * c; } /* -------------------------------------------------------------------------- */ template <> template -constexpr inline Real GeometricalElement<_gt_segment_3>::getInradius( - const Eigen::MatrixBase & coord) { +inline Real GeometricalElement<_gt_segment_3>::getInradius( + const Eigen::MatrixBase &coord) { auto dist1 = (coord(1) - coord(0)).norm(); auto dist2 = (coord(2) - coord(1)).norm(); return std::min(dist1, dist2); } /* -------------------------------------------------------------------------- */ template <> template -inline void GeometricalElement<_gt_segment_3>::getNormal( - const Eigen::MatrixBase & coord, Eigen::MatrixBase & normal) { - Eigen::Matrix natural_coords; - natural_coords << .5; +inline void +GeometricalElement<_gt_segment_3>::getNormal(const Eigen::MatrixBase &coord, + Eigen::MatrixBase &normal) { + Eigen::Matrix natural_coords{{.5}}; ElementClass<_segment_3>::computeNormalsOnNaturalCoordinates(natural_coords, coord, normal); } } // namespace akantu diff --git a/src/fe_engine/element_classes/element_class_tetrahedron_10_inline_impl.hh b/src/fe_engine/element_classes/element_class_tetrahedron_10_inline_impl.hh index 0ba54945c..f6541b66f 100644 --- a/src/fe_engine/element_classes/element_class_tetrahedron_10_inline_impl.hh +++ b/src/fe_engine/element_classes/element_class_tetrahedron_10_inline_impl.hh @@ -1,288 +1,287 @@ /** * @file element_class_tetrahedron_10_inline_impl.hh * * @author Guillaume Anciaux * @author Nicolas Richart * @author Peter Spijker * * @date creation: Fri Jul 16 2010 * @date last modification: Fri Feb 07 2020 * * @brief Specialization of the element_class class for the type * _tetrahedron_10 * * * @section LICENSE * * Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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 . * */ /** * @verbatim \zeta ^ | (0,0,1) x |` . | ` . | ` . | ` . (0,0.5,0.5) | ` x. | q4 o ` . \eta | ` . -, (0,0,0.5) x ` x (0.5,0,0.5) - | ` x-(0,1,0) | q3 o` - ' | (0,0.5,0) - ` ' | x- ` x (0.5,0.5,0) | q1 o - o q2` ' | - ` ' | - ` ' x---------------x--------------` x-----> \xi (0,0,0) (0.5,0,0) (1,0,0) @endverbatim * * * @f[ * \begin{array}{lll} * \xi_{0} = 0 & \eta_{0} = 0 & \zeta_{0} = 0 \\ * \xi_{1} = 1 & \eta_{1} = 0 & \zeta_{1} = 0 \\ * \xi_{2} = 0 & \eta_{2} = 1 & \zeta_{2} = 0 \\ * \xi_{3} = 0 & \eta_{3} = 0 & \zeta_{3} = 1 \\ * \xi_{4} = 1/2 & \eta_{4} = 0 & \zeta_{4} = 0 \\ * \xi_{5} = 1/2 & \eta_{5} = 1/2 & \zeta_{5} = 0 \\ * \xi_{6} = 0 & \eta_{6} = 1/2 & \zeta_{6} = 0 \\ * \xi_{7} = 0 & \eta_{7} = 0 & \zeta_{7} = 1/2 \\ * \xi_{8} = 1/2 & \eta_{8} = 0 & \zeta_{8} = 1/2 \\ * \xi_{9} = 0 & \eta_{9} = 1/2 & \zeta_{9} = 1/2 * \end{array} * @f] * * @f[ * \begin{array}{llll} * N1 = (1 - \xi - \eta - \zeta) (1 - 2 \xi - 2 \eta - 2 \zeta) * & \frac{\partial N1}{\partial \xi} = 4 \xi + 4 \eta + 4 \zeta - 3 * & \frac{\partial N1}{\partial \eta} = 4 \xi + 4 \eta + 4 \zeta - 3 * & \frac{\partial N1}{\partial \zeta} = 4 \xi + 4 \eta + 4 \zeta - 3 \\ * N2 = \xi (2 \xi - 1) * & \frac{\partial N2}{\partial \xi} = 4 \xi - 1 * & \frac{\partial N2}{\partial \eta} = 0 * & \frac{\partial N2}{\partial \zeta} = 0 \\ * N3 = \eta (2 \eta - 1) * & \frac{\partial N3}{\partial \xi} = 0 * & \frac{\partial N3}{\partial \eta} = 4 \eta - 1 * & \frac{\partial N3}{\partial \zeta} = 0 \\ * N4 = \zeta (2 \zeta - 1) * & \frac{\partial N4}{\partial \xi} = 0 * & \frac{\partial N4}{\partial \eta} = 0 * & \frac{\partial N4}{\partial \zeta} = 4 \zeta - 1 \\ * N5 = 4 \xi (1 - \xi - \eta - \zeta) * & \frac{\partial N5}{\partial \xi} = 4 - 8 \xi - 4 \eta - 4 \zeta * & \frac{\partial N5}{\partial \eta} = -4 \xi * & \frac{\partial N5}{\partial \zeta} = -4 \xi \\ * N6 = 4 \xi \eta * & \frac{\partial N6}{\partial \xi} = 4 \eta * & \frac{\partial N6}{\partial \eta} = 4 \xi * & \frac{\partial N6}{\partial \zeta} = 0 \\ * N7 = 4 \eta (1 - \xi - \eta - \zeta) * & \frac{\partial N7}{\partial \xi} = -4 \eta * & \frac{\partial N7}{\partial \eta} = 4 - 4 \xi - 8 \eta - 4 \zeta * & \frac{\partial N7}{\partial \zeta} = -4 \eta \\ * N8 = 4 \zeta (1 - \xi - \eta - \zeta) * & \frac{\partial N8}{\partial \xi} = -4 \zeta * & \frac{\partial N8}{\partial \eta} = -4 \zeta * & \frac{\partial N8}{\partial \zeta} = 4 - 4 \xi - 4 \eta - 8 \zeta \\ * N9 = 4 \zeta \xi * & \frac{\partial N9}{\partial \xi} = 4 \zeta * & \frac{\partial N9}{\partial \eta} = 0 * & \frac{\partial N9}{\partial \zeta} = 4 \xi \\ * N10 = 4 \eta \zeta * & \frac{\partial N10}{\partial \xi} = 0 * & \frac{\partial N10}{\partial \eta} = 4 \zeta * & \frac{\partial N10}{\partial \zeta} = 4 \eta \\ * \end{array} * @f] * * @f[ * a = \frac{5 - \sqrt{5}}{20}\\ * b = \frac{5 + 3 \sqrt{5}}{20} * \begin{array}{lll} * \xi_{q_0} = a & \eta_{q_0} = a & \zeta_{q_0} = a \\ * \xi_{q_1} = b & \eta_{q_1} = a & \zeta_{q_1} = a \\ * \xi_{q_2} = a & \eta_{q_2} = b & \zeta_{q_2} = a \\ * \xi_{q_3} = a & \eta_{q_3} = a & \zeta_{q_3} = b * \end{array} * @f] */ /* -------------------------------------------------------------------------- */ #include "element_class.hh" /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_tetrahedron_10, _gt_tetrahedron_10, _itp_lagrange_tetrahedron_10, _ek_regular, 3, _git_tetrahedron, 2); /* -------------------------------------------------------------------------- */ template <> template ::value> *> inline void InterpolationElement<_itp_lagrange_tetrahedron_10>::computeShapes( - const Eigen::MatrixBase & natural_coords, Eigen::MatrixBase & N) { + const Eigen::MatrixBase &natural_coords, Eigen::MatrixBase &N) { /// Natural coordinates Real xi = natural_coords(0); Real eta = natural_coords(1); Real zeta = natural_coords(2); Real sum = xi + eta + zeta; Real c0 = 1 - sum; Real c1 = 1 - 2 * sum; Real c2 = 2 * xi - 1; Real c3 = 2 * eta - 1; Real c4 = 2 * zeta - 1; /// Shape functions N(0) = c0 * c1; N(1) = xi * c2; N(2) = eta * c3; N(3) = zeta * c4; N(4) = 4 * xi * c0; N(5) = 4 * xi * eta; N(6) = 4 * eta * c0; N(7) = 4 * zeta * c0; N(8) = 4 * xi * zeta; N(9) = 4 * eta * zeta; } /* -------------------------------------------------------------------------- */ template <> template inline void InterpolationElement<_itp_lagrange_tetrahedron_10>::computeDNDS( - const Eigen::MatrixBase & natural_coords, - Eigen::MatrixBase & dnds) { + const Eigen::MatrixBase &natural_coords, Eigen::MatrixBase &dnds) { /** * \f[ * dnds = \left( * \begin{array}{cccccccccc} * \frac{\partial N1}{\partial \xi} & \frac{\partial N2}{\partial * \xi} * & \frac{\partial N3}{\partial \xi} & \frac{\partial N4}{\partial * \xi} * & \frac{\partial N5}{\partial \xi} & \frac{\partial N6}{\partial * \xi} * & \frac{\partial N7}{\partial \xi} & \frac{\partial N8}{\partial * \xi} * & \frac{\partial N9}{\partial \xi} & \frac{\partial * N10}{\partial \xi} \\ * \frac{\partial N1}{\partial \eta} & \frac{\partial N2}{\partial * \eta} * & \frac{\partial N3}{\partial \eta} & \frac{\partial N4}{\partial * \eta} * & \frac{\partial N5}{\partial \eta} & \frac{\partial N6}{\partial * \eta} * & \frac{\partial N7}{\partial \eta} & \frac{\partial N8}{\partial * \eta} * & \frac{\partial N9}{\partial \eta} & \frac{\partial * N10}{\partial \eta} \\ * \frac{\partial N1}{\partial \zeta} & \frac{\partial N2}{\partial * \zeta} * & \frac{\partial N3}{\partial \zeta} & \frac{\partial N4}{\partial * \zeta} * & \frac{\partial N5}{\partial \zeta} & \frac{\partial N6}{\partial * \zeta} * & \frac{\partial N7}{\partial \zeta} & \frac{\partial N8}{\partial * \zeta} * & \frac{\partial N9}{\partial \zeta} & \frac{\partial * N10}{\partial \zeta} * \end{array} * \right) * \f] */ /// Natural coordinates Real xi = natural_coords(0); Real eta = natural_coords(1); Real zeta = natural_coords(2); Real sum = xi + eta + zeta; /// \frac{\partial N_i}{\partial \xi} dnds(0, 0) = 4 * sum - 3; dnds(0, 1) = 4 * xi - 1; dnds(0, 2) = 0; dnds(0, 3) = 0; dnds(0, 4) = 4 * (1 - sum - xi); dnds(0, 5) = 4 * eta; dnds(0, 6) = -4 * eta; dnds(0, 7) = -4 * zeta; dnds(0, 8) = 4 * zeta; dnds(0, 9) = 0; /// \frac{\partial N_i}{\partial \eta} dnds(1, 0) = 4 * sum - 3; dnds(1, 1) = 0; dnds(1, 2) = 4 * eta - 1; dnds(1, 3) = 0; dnds(1, 4) = -4 * xi; dnds(1, 5) = 4 * xi; dnds(1, 6) = 4 * (1 - sum - eta); dnds(1, 7) = -4 * zeta; dnds(1, 8) = 0; dnds(1, 9) = 4 * zeta; /// \frac{\partial N_i}{\partial \zeta} dnds(2, 0) = 4 * sum - 3; dnds(2, 1) = 0; dnds(2, 2) = 0; dnds(2, 3) = 4 * zeta - 1; dnds(2, 4) = -4 * xi; dnds(2, 5) = 0; dnds(2, 6) = -4 * eta; dnds(2, 7) = 4 * (1 - sum - zeta); dnds(2, 8) = 4 * xi; dnds(2, 9) = 4 * eta; } /* -------------------------------------------------------------------------- */ template <> template -constexpr inline Real GeometricalElement<_gt_tetrahedron_10>::getInradius( - const Eigen::MatrixBase & coord) { +inline Real GeometricalElement<_gt_tetrahedron_10>::getInradius( + const Eigen::MatrixBase &coord) { // Only take the four corner tetrahedra Matrix tetrahedra{ {0, 4, 6, 7}, {4, 1, 5, 8}, {6, 5, 2, 9}, {7, 8, 9, 3}}; auto inradius = std::numeric_limits::max(); for (Int t = 0; t < 4; t++) { auto ir = Math::tetrahedron_inradius( coord.col(tetrahedra(t, 0)), coord.col(tetrahedra(t, 1)), coord.col(tetrahedra(t, 2)), coord.col(tetrahedra(t, 3))); inradius = std::min(ir, inradius); } return 2. * inradius; } } // namespace akantu diff --git a/src/fe_engine/element_classes/element_class_tetrahedron_4_inline_impl.hh b/src/fe_engine/element_classes/element_class_tetrahedron_4_inline_impl.hh index e2e6fa88f..d14b9cd2c 100644 --- a/src/fe_engine/element_classes/element_class_tetrahedron_4_inline_impl.hh +++ b/src/fe_engine/element_classes/element_class_tetrahedron_4_inline_impl.hh @@ -1,144 +1,144 @@ /** * @file element_class_tetrahedron_4_inline_impl.hh * * @author Guillaume Anciaux * @author Nicolas Richart * * @date creation: Fri Jul 16 2010 * @date last modification: Wed Jun 17 2020 * * @brief Specialization of the element_class class for the type _tetrahedron_4 * * * @section LICENSE * * Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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 . * */ /** * @verbatim \eta ^ | x (0,0,1,0) |` | ` ° \zeta | ` ° - | ` x (0,0,0,1) | q.` - ' | -` ' | - ` ' | - ` ' x------------------x-----> \xi (1,0,0,0) (0,1,0,0) @endverbatim * * @f{eqnarray*}{ * N1 &=& 1 - \xi - \eta - \zeta \\ * N2 &=& \xi \\ * N3 &=& \eta \\ * N4 &=& \zeta * @f} * * @f[ * \xi_{q0} = 1/4 \qquad \eta_{q0} = 1/4 \qquad \zeta_{q0} = 1/4 * @f] */ /* -------------------------------------------------------------------------- */ #include "element_class.hh" /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_tetrahedron_4, _gt_tetrahedron_4, _itp_lagrange_tetrahedron_4, _ek_regular, 3, _git_tetrahedron, 1); /* -------------------------------------------------------------------------- */ template <> template ::value> *> inline void InterpolationElement<_itp_lagrange_tetrahedron_4>::computeShapes( - const Eigen::MatrixBase & natural_coords, Eigen::MatrixBase & N) { + const Eigen::MatrixBase &natural_coords, Eigen::MatrixBase &N) { Real c0 = 1 - natural_coords(0) - natural_coords(1) - natural_coords(2); /// @f$ c0 = 1 - \xi - \eta - \zeta @f$ Real c1 = natural_coords(1); /// @f$ c1 = \xi @f$ Real c2 = natural_coords(2); /// @f$ c2 = \eta @f$ Real c3 = natural_coords(0); /// @f$ c3 = \zeta @f$ N(0) = c0; N(1) = c1; N(2) = c2; N(3) = c3; } /* -------------------------------------------------------------------------- */ template <> template inline void InterpolationElement<_itp_lagrange_tetrahedron_4>::computeDNDS( const Eigen::MatrixBase & /*natural_coords*/, - Eigen::MatrixBase & dnds) { + Eigen::MatrixBase &dnds) { /** * @f[ * dnds = \left( * \begin{array}{cccccc} * \frac{\partial N1}{\partial \xi} & \frac{\partial N2}{\partial * \xi} * & \frac{\partial N3}{\partial \xi} & \frac{\partial N4}{\partial * \xi} \\ * \frac{\partial N1}{\partial \eta} & \frac{\partial N2}{\partial * \eta} * & \frac{\partial N3}{\partial \eta} & \frac{\partial N4}{\partial * \eta} \\ * \frac{\partial N1}{\partial \zeta} & \frac{\partial N2}{\partial * \zeta} * & \frac{\partial N3}{\partial \zeta} & \frac{\partial N4}{\partial * \zeta} * \end{array} * \right) * @f] */ dnds(0, 0) = -1.; dnds(1, 0) = -1.; dnds(2, 0) = -1.; dnds(0, 1) = 0.; dnds(1, 1) = 1.; dnds(2, 1) = 0.; dnds(0, 2) = 0.; dnds(1, 2) = 0.; dnds(2, 2) = 1.; dnds(0, 3) = 1.; dnds(1, 3) = 0.; dnds(2, 3) = 0.; } /* -------------------------------------------------------------------------- */ template <> template -constexpr inline Real GeometricalElement<_gt_tetrahedron_4>::getInradius( - const Eigen::MatrixBase & coord) { +inline Real GeometricalElement<_gt_tetrahedron_4>::getInradius( + const Eigen::MatrixBase &coord) { return 2. * Math::tetrahedron_inradius(coord.col(0), coord.col(1), coord.col(2), coord.col(3)); } } // namespace akantu diff --git a/src/fe_engine/element_classes/element_class_triangle_3_inline_impl.hh b/src/fe_engine/element_classes/element_class_triangle_3_inline_impl.hh index aa04a3957..b104fd548 100644 --- a/src/fe_engine/element_classes/element_class_triangle_3_inline_impl.hh +++ b/src/fe_engine/element_classes/element_class_triangle_3_inline_impl.hh @@ -1,126 +1,126 @@ /** * @file element_class_triangle_3_inline_impl.hh * * @author Guillaume Anciaux * @author Mohit Pundir * @author Nicolas Richart * * @date creation: Fri Jul 16 2010 * @date last modification: Fri Dec 11 2020 * * @brief Specialization of the element_class class for the type _triangle_3 * * * @section LICENSE * * Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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 . * */ /** * @verbatim \eta ^ | x (0,0,1) |` | ` | q ` | ° ` x--------x-----> \xi (1,0,0) (0,1,0) @endverbatim * * @f{eqnarray*}{ * N1 &=& 1 - \xi - \eta \\ * N2 &=& \xi \\ * N3 &=& \eta * @f} * * @f{eqnarray*}{ * \xi_{q0} &=& 1/3 \qquad \eta_{q0} = 1/3 * @f} */ /* -------------------------------------------------------------------------- */ #include "element_class.hh" /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_triangle_3, _gt_triangle_3, _itp_lagrange_triangle_3, _ek_regular, 2, _git_triangle, 1); /* -------------------------------------------------------------------------- */ template <> template ::value> *> inline void InterpolationElement<_itp_lagrange_triangle_3>::computeShapes( const Eigen::MatrixBase &X, Eigen::MatrixBase &N) { N(0) = 1 - X(0) - X(1); /// @f$ c0 = 1 - \xi - \eta @f$ N(1) = X(0); /// @f$ c1 = \xi @f$ N(2) = X(1); /// @f$ c2 = \eta @f$ } /* -------------------------------------------------------------------------- */ template <> template inline void InterpolationElement<_itp_lagrange_triangle_3>::computeDNDS( const Eigen::MatrixBase & /*natural_coords*/, Eigen::MatrixBase &dnds) { /** * @f[ * dnds = \left( * \begin{array}{cccccc} * \frac{\partial N1}{\partial \xi} & \frac{\partial N2}{\partial * \xi} & \frac{\partial N3}{\partial \xi} \\ * \frac{\partial N1}{\partial \eta} & \frac{\partial N2}{\partial * \eta} & \frac{\partial N3}{\partial \eta} * \end{array} * \right) * @f] */ dnds(0, 0) = -1.; dnds(0, 1) = 1.; dnds(0, 2) = 0.; dnds(1, 0) = -1.; dnds(1, 1) = 0.; dnds(1, 2) = 1.; } /* -------------------------------------------------------------------------- */ template <> template inline void InterpolationElement<_itp_lagrange_triangle_3>::computeD2NDS2( const vector_type & /*natural_coords*/, matrix_type &d2nds2) { d2nds2.zero(); } /* -------------------------------------------------------------------------- */ template <> template -constexpr inline Real GeometricalElement<_gt_triangle_3>::getInradius( +inline Real GeometricalElement<_gt_triangle_3>::getInradius( const Eigen::MatrixBase &coord) { auto &&coord1 = coord.col(0); auto &&coord2 = coord.col(1); auto &&coord3 = coord.col(2); return 2. * Math::triangle_inradius(coord1, coord2, coord3); } /* -------------------------------------------------------------------------- */ } // namespace akantu diff --git a/src/fe_engine/element_classes/element_class_triangle_6_inline_impl.hh b/src/fe_engine/element_classes/element_class_triangle_6_inline_impl.hh index 31c9bac1d..091b4545e 100644 --- a/src/fe_engine/element_classes/element_class_triangle_6_inline_impl.hh +++ b/src/fe_engine/element_classes/element_class_triangle_6_inline_impl.hh @@ -1,192 +1,191 @@ /** * @file element_class_triangle_6_inline_impl.hh * * @author Guillaume Anciaux * @author Mohit Pundir * @author Nicolas Richart * * @date creation: Fri Jul 16 2010 * @date last modification: Fri Feb 28 2020 * * @brief Specialization of the element_class class for the type _triangle_6 * * * @section LICENSE * * Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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 . * */ /** * @verbatim \eta ^ | x 2 | ` | ` | . ` | q2 ` 5 x x 4 | ` | ` | .q0 q1. ` | ` x---------x---------x-----> \xi 0 3 1 @endverbatim * * * @f[ * \begin{array}{ll} * \xi_{0} = 0 & \eta_{0} = 0 \\ * \xi_{1} = 1 & \eta_{1} = 0 \\ * \xi_{2} = 0 & \eta_{2} = 1 \\ * \xi_{3} = 1/2 & \eta_{3} = 0 \\ * \xi_{4} = 1/2 & \eta_{4} = 1/2 \\ * \xi_{5} = 0 & \eta_{5} = 1/2 * \end{array} * @f] * * @f[ * \begin{array}{lll} * N1 = -(1 - \xi - \eta) (1 - 2 (1 - \xi - \eta)) * & \frac{\partial N1}{\partial \xi} = 1 - 4(1 - \xi - \eta) * & \frac{\partial N1}{\partial \eta} = 1 - 4(1 - \xi - \eta) \\ * N2 = - \xi (1 - 2 \xi) * & \frac{\partial N2}{\partial \xi} = - 1 + 4 \xi * & \frac{\partial N2}{\partial \eta} = 0 \\ * N3 = - \eta (1 - 2 \eta) * & \frac{\partial N3}{\partial \xi} = 0 * & \frac{\partial N3}{\partial \eta} = - 1 + 4 \eta \\ * N4 = 4 \xi (1 - \xi - \eta) * & \frac{\partial N4}{\partial \xi} = 4 (1 - 2 \xi - \eta) * & \frac{\partial N4}{\partial \eta} = - 4 \xi \\ * N5 = 4 \xi \eta * & \frac{\partial N5}{\partial \xi} = 4 \eta * & \frac{\partial N5}{\partial \eta} = 4 \xi \\ * N6 = 4 \eta (1 - \xi - \eta) * & \frac{\partial N6}{\partial \xi} = - 4 \eta * & \frac{\partial N6}{\partial \eta} = 4 (1 - \xi - 2 \eta) * \end{array} * @f] * * @f{eqnarray*}{ * \xi_{q0} &=& 1/6 \qquad \eta_{q0} = 1/6 \\ * \xi_{q1} &=& 2/3 \qquad \eta_{q1} = 1/6 \\ * \xi_{q2} &=& 1/6 \qquad \eta_{q2} = 2/3 * @f} */ /* -------------------------------------------------------------------------- */ #include "element_class.hh" /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_triangle_6, _gt_triangle_6, _itp_lagrange_triangle_6, _ek_regular, 2, _git_triangle, 2); /* -------------------------------------------------------------------------- */ template <> template ::value> *> inline void InterpolationElement<_itp_lagrange_triangle_6>::computeShapes( - const Eigen::MatrixBase & natural_coords, Eigen::MatrixBase & N) { + const Eigen::MatrixBase &natural_coords, Eigen::MatrixBase &N) { /// Natural coordinates Real c0 = 1 - natural_coords(0) - natural_coords(1); /// @f$ c0 = 1 - \xi - \eta @f$ Real c1 = natural_coords(0); /// @f$ c1 = \xi @f$ Real c2 = natural_coords(1); /// @f$ c2 = \eta @f$ N(0) = c0 * (2 * c0 - 1.); N(1) = c1 * (2 * c1 - 1.); N(2) = c2 * (2 * c2 - 1.); N(3) = 4 * c0 * c1; N(4) = 4 * c1 * c2; N(5) = 4 * c2 * c0; } /* -------------------------------------------------------------------------- */ template <> template inline void InterpolationElement<_itp_lagrange_triangle_6>::computeDNDS( - const Eigen::MatrixBase & natural_coords, - Eigen::MatrixBase & dnds) { + const Eigen::MatrixBase &natural_coords, Eigen::MatrixBase &dnds) { /** * @f[ * dnds = \left( * \begin{array}{cccccc} * \frac{\partial N1}{\partial \xi} * & \frac{\partial N2}{\partial \xi} * & \frac{\partial N3}{\partial \xi} * & \frac{\partial N4}{\partial \xi} * & \frac{\partial N5}{\partial \xi} * & \frac{\partial N6}{\partial \xi} \\ * * \frac{\partial N1}{\partial \eta} * & \frac{\partial N2}{\partial \eta} * & \frac{\partial N3}{\partial \eta} * & \frac{\partial N4}{\partial \eta} * & \frac{\partial N5}{\partial \eta} * & \frac{\partial N6}{\partial \eta} * \end{array} * \right) * @f] */ /// Natural coordinates Real c0 = 1 - natural_coords(0) - natural_coords(1); /// @f$ c0 = 1 - \xi - \eta @f$ Real c1 = natural_coords(0); /// @f$ c1 = \xi @f$ Real c2 = natural_coords(1); /// @f$ c2 = \eta @f$ dnds(0, 0) = 1 - 4 * c0; dnds(0, 1) = 4 * c1 - 1.; dnds(0, 2) = 0.; dnds(0, 3) = 4 * (c0 - c1); dnds(0, 4) = 4 * c2; dnds(0, 5) = -4 * c2; dnds(1, 0) = 1 - 4 * c0; dnds(1, 1) = 0.; dnds(1, 2) = 4 * c2 - 1.; dnds(1, 3) = -4 * c1; dnds(1, 4) = 4 * c1; dnds(1, 5) = 4 * (c0 - c2); } /* -------------------------------------------------------------------------- */ template <> template -constexpr inline Real GeometricalElement<_gt_triangle_6>::getInradius( - const Eigen::MatrixBase & coord) { - UInt triangles[4][3] = {{0, 3, 5}, {3, 1, 4}, {3, 4, 5}, {5, 4, 2}}; +inline Real GeometricalElement<_gt_triangle_6>::getInradius( + const Eigen::MatrixBase &coord) { + Int triangles[4][3] = {{0, 3, 5}, {3, 1, 4}, {3, 4, 5}, {5, 4, 2}}; Real inradius = std::numeric_limits::max(); for (Int t = 0; t < 4; t++) { auto ir = Math::triangle_inradius( coord(triangles[t][0]), coord(triangles[t][1]), coord(triangles[t][2])); inradius = std::min(ir, inradius); } return 2. * inradius; } } // namespace akantu diff --git a/src/io/dumper/dumper_homogenizing_field.hh b/src/io/dumper/dumper_homogenizing_field.hh index 5f365c6b5..789c5a2c2 100644 --- a/src/io/dumper/dumper_homogenizing_field.hh +++ b/src/io/dumper/dumper_homogenizing_field.hh @@ -1,198 +1,195 @@ /** * @file dumper_homogenizing_field.hh * * @author Guillaume Anciaux * @author Nicolas Richart * * @date creation: Tue Sep 02 2014 * @date last modification: Fri Jul 24 2020 * * @brief description of field homogenizing field * * * @section LICENSE * * Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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_DUMPER_HOMOGENIZING_FIELD_HH_ #define AKANTU_DUMPER_HOMOGENIZING_FIELD_HH_ /* -------------------------------------------------------------------------- */ #include "dumper_compute.hh" /* -------------------------------------------------------------------------- */ namespace akantu { namespace dumpers { - /* ------------------------------------------------------------------------ */ - template - inline type typeConverter(const type & input, - Vector & /*res*/, - Int /*nb_data*/) { - throw; - } - - /* ------------------------------------------------------------------------ */ - template - inline Matrix typeConverter(const Matrix & input, - Vector & res, Int nb_data) { - MatrixProxy tmp(res.data(), input.rows(), nb_data / input.rows()); - return tmp; - } - - /* ------------------------------------------------------------------------ */ - template - inline Vector typeConverter(const Vector & /*unused*/, - Vector & res, Int /*unused*/) { - return res; - } - - /* ------------------------------------------------------------------------ */ - template - class AvgHomogenizingFunctor : public ComputeFunctor { - /* ---------------------------------------------------------------------- */ - /* Typedefs */ - /* ---------------------------------------------------------------------- */ - private: - using value_type = typename type::value_type; - - /* ---------------------------------------------------------------------- */ - /* Constructors/Destructors */ - /* ---------------------------------------------------------------------- */ - public: - AvgHomogenizingFunctor(ElementTypeMap & nb_datas) { - auto types = nb_datas.elementTypes(); - auto tit = types.begin(); - auto end = types.end(); - - nb_data = nb_datas(*tit); - - for (; tit != end; ++tit) { - if (nb_data != nb_datas(*tit)) { - throw; - } - } - } - - /* ---------------------------------------------------------------------- */ - /* Methods */ - /* ---------------------------------------------------------------------- */ - public: - type func(const type & d, Element /*global_index*/) - override { - Vector res(this->nb_data); - res.zero(); - if (d.size() % this->nb_data) { +/* ------------------------------------------------------------------------ */ +template +inline type typeConverter(const type & /*input*/, + Vector & /*res*/, + Int /*nb_data*/) { + throw; +} + +/* ------------------------------------------------------------------------ */ +template +inline Matrix typeConverter(const Matrix &input, Vector &res, + Int nb_data) { + MatrixProxy tmp(res.data(), input.rows(), nb_data / input.rows()); + return tmp; +} + +/* ------------------------------------------------------------------------ */ +template +inline Vector typeConverter(const Vector & /*unused*/, + Vector &res, Int /*unused*/) { + return res; +} + +/* ------------------------------------------------------------------------ */ +template +class AvgHomogenizingFunctor : public ComputeFunctor { + /* ---------------------------------------------------------------------- */ + /* Typedefs */ + /* ---------------------------------------------------------------------- */ +private: + using value_type = typename type::value_type; + + /* ---------------------------------------------------------------------- */ + /* Constructors/Destructors */ + /* ---------------------------------------------------------------------- */ +public: + AvgHomogenizingFunctor(ElementTypeMap &nb_datas) { + auto types = nb_datas.elementTypes(); + auto tit = types.begin(); + auto end = types.end(); + + nb_data = nb_datas(*tit); + + for (; tit != end; ++tit) { + if (nb_data != nb_datas(*tit)) { throw; } - auto nb_to_average = d.size() / this->nb_data; - - auto && ptr = d.data(); - for (Int i = 0; i < nb_to_average; ++i) { - VectorProxy tmp(ptr, this->nb_data); - res += tmp; - ptr += this->nb_data; - } - res /= nb_to_average; - return typeConverter(d, res, this->nb_data); - }; - - Int getDim() override { return nb_data; }; - Int getNbComponent(Int /*old_nb_comp*/) - override { throw; }; - - /* ---------------------------------------------------------------------- */ - /* Class Members */ - /* ---------------------------------------------------------------------- */ + } + } - /// The size of data: i.e. the size of the vector to be returned - Int nb_data; - }; - /* ------------------------------------------------------------------------ */ - - /* ------------------------------------------------------------------------ */ - class HomogenizerProxy { - /* ---------------------------------------------------------------------- */ - /* Constructors/Destructors */ - /* ---------------------------------------------------------------------- */ - public: - HomogenizerProxy() = default; - - public: - inline static std::unique_ptr - createHomogenizer(Field & field); - - template - inline std::unique_ptr connectToField(T * field) { - ElementTypeMap nb_components = field->getNbComponents(); - - using ret_type = typename T::types::return_type; - return this->instantiateHomogenizer(nb_components); + /* ---------------------------------------------------------------------- */ + /* Methods */ + /* ---------------------------------------------------------------------- */ +public: + type func(const type &d, Element /*global_index*/) override { + Vector res(this->nb_data); + res.zero(); + if (d.size() % this->nb_data) { + throw; } + auto nb_to_average = d.size() / this->nb_data; - template - inline std::unique_ptr - instantiateHomogenizer(ElementTypeMap & nb_components); + auto &&ptr = d.data(); + for (Int i = 0; i < nb_to_average; ++i) { + VectorProxy tmp(ptr, this->nb_data); + res += tmp; + ptr += this->nb_data; + } + res /= nb_to_average; + return typeConverter(d, res, this->nb_data); }; - /* ------------------------------------------------------------------------ */ + Int getDim() override { return nb_data; }; + Int getNbComponent(Int /*old_nb_comp*/) override { throw; }; - template - inline std::unique_ptr - HomogenizerProxy::instantiateHomogenizer( - ElementTypeMap & nb_components) { - using Homogenizer = dumpers::AvgHomogenizingFunctor; - return std::make_unique(nb_components); - } + /* ---------------------------------------------------------------------- */ + /* Class Members */ + /* ---------------------------------------------------------------------- */ - template <> - inline std::unique_ptr - HomogenizerProxy::instantiateHomogenizer>( - ElementTypeMap & /*nb_components*/) { - throw; - return nullptr; - } + /// The size of data: i.e. the size of the vector to be returned + Int nb_data; +}; +/* ------------------------------------------------------------------------ */ - /* ------------------------------------------------------------------------ */ - /// for connection to a FieldCompute - template - inline std::unique_ptr - FieldCompute::connect( - HomogenizerProxy & proxy) { - return proxy.connectToField(this); - } +/* ------------------------------------------------------------------------ */ +class HomogenizerProxy { + /* ---------------------------------------------------------------------- */ + /* Constructors/Destructors */ + /* ---------------------------------------------------------------------- */ +public: + HomogenizerProxy() = default; - template - inline std::unique_ptr - FieldCompute::connect( - HomogenizerProxy & proxy) { - return proxy.connectToField(this); +public: + inline static std::unique_ptr + createHomogenizer(Field &field); + + template + inline std::unique_ptr connectToField(T *field) { + ElementTypeMap nb_components = field->getNbComponents(); + + using ret_type = typename T::types::return_type; + return this->instantiateHomogenizer(nb_components); } - /* ------------------------------------------------------------------------ */ + template inline std::unique_ptr - HomogenizerProxy::createHomogenizer(Field & field) { - HomogenizerProxy homogenizer_proxy; - return field.connect(homogenizer_proxy); - } + instantiateHomogenizer(ElementTypeMap &nb_components); +}; + +/* ------------------------------------------------------------------------ */ + +template +inline std::unique_ptr +HomogenizerProxy::instantiateHomogenizer(ElementTypeMap &nb_components) { + using Homogenizer = dumpers::AvgHomogenizingFunctor; + return std::make_unique(nb_components); +} + +template <> +inline std::unique_ptr +HomogenizerProxy::instantiateHomogenizer>( + ElementTypeMap & /*nb_components*/) { + throw; + return nullptr; +} + +/* ------------------------------------------------------------------------ */ +/// for connection to a FieldCompute +template +inline std::unique_ptr +FieldCompute::connect( + HomogenizerProxy &proxy) { + return proxy.connectToField(this); +} + +template +inline std::unique_ptr +FieldCompute::connect( + HomogenizerProxy &proxy) { + return proxy.connectToField(this); +} + +/* ------------------------------------------------------------------------ */ +inline std::unique_ptr +HomogenizerProxy::createHomogenizer(Field &field) { + HomogenizerProxy homogenizer_proxy; + return field.connect(homogenizer_proxy); +} } // namespace dumpers } // namespace akantu #endif /* AKANTU_DUMPER_HOMOGENIZING_FIELD_HH_ */ diff --git a/src/model/solid_mechanics/material.hh b/src/model/solid_mechanics/material.hh index e6758c3a8..51184d471 100644 --- a/src/model/solid_mechanics/material.hh +++ b/src/model/solid_mechanics/material.hh @@ -1,797 +1,806 @@ /** * @file material.hh * * @author Fabian Barras * @author Aurelia Isabel Cuba Ramos * @author Lucas Frerot * @author Enrico Milanese * @author Daniel Pino Muñoz * @author Nicolas Richart * @author Marco Vocialta * * @date creation: Fri Jun 18 2010 * @date last modification: Fri Apr 09 2021 * * @brief Mother class for all materials * * * @section LICENSE * * Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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_factory.hh" #include "aka_voigthelper.hh" #include "data_accessor.hh" #include "integration_point.hh" #include "parsable.hh" #include "parser.hh" /* -------------------------------------------------------------------------- */ #include "internal_field.hh" #include "random_internal_field.hh" /* -------------------------------------------------------------------------- */ #include "mesh_events.hh" #include "solid_mechanics_model_event_handler.hh" /* -------------------------------------------------------------------------- */ #ifndef AKANTU_MATERIAL_HH_ #define AKANTU_MATERIAL_HH_ /* -------------------------------------------------------------------------- */ namespace akantu { class Model; class SolidMechanicsModel; class Material; } // namespace akantu namespace akantu { using MaterialFactory = Factory; /** * Interface of all materials * Prerequisites for a new material * - inherit from this class * - implement the following methods: * \code * virtual Real getStableTimeStep(Real h, const Element & element = * ElementNull); * * virtual void computeStress(ElementType el_type, * GhostType ghost_type = _not_ghost); * * virtual void computeTangentStiffness(ElementType el_type, * Array & tangent_matrix, * GhostType ghost_type = _not_ghost); * \endcode * */ class Material : public DataAccessor, public Parsable, public MeshEventHandler, protected SolidMechanicsModelEventHandler { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: Material(const Material &mat) = delete; Material &operator=(const Material &mat) = delete; /// Initialize material with defaults Material(SolidMechanicsModel &model, const ID &id = ""); /// Initialize material with custom mesh & fe_engine Material(SolidMechanicsModel &model, Int dim, const Mesh &mesh, FEEngine &fe_engine, const ID &id = ""); /// Destructor ~Material() override; protected: void initialize(); /* ------------------------------------------------------------------------ */ /* Function that materials can/should reimplement */ /* ------------------------------------------------------------------------ */ protected: /// constitutive law virtual void computeStress(ElementType /* el_type */, GhostType /* ghost_type */ = _not_ghost) { AKANTU_TO_IMPLEMENT(); } /// compute the tangent stiffness matrix virtual void computeTangentModuli(ElementType /*el_type*/, Array & /*tangent_matrix*/, GhostType /*ghost_type*/ = _not_ghost) { AKANTU_TO_IMPLEMENT(); } /// compute the potential energy virtual void computePotentialEnergy(ElementType el_type); /// compute the potential energy for an element [[gnu::deprecated("Use the interface with an Element")]] virtual void computePotentialEnergyByElement(ElementType /*type*/, Int /*index*/, Vector & /*epot_on_quad_points*/) { AKANTU_TO_IMPLEMENT(); } virtual void computePotentialEnergyByElement(const Element & /*element*/, Vector & /*epot_on_quad_points*/) { AKANTU_TO_IMPLEMENT(); } virtual void updateEnergies(ElementType /*el_type*/) {} virtual void updateEnergiesAfterDamage(ElementType /*el_type*/) {} /// set the material to steady state (to be implemented for materials that /// need it) virtual void setToSteadyState(ElementType /*el_type*/, GhostType /*ghost_type*/ = _not_ghost) {} /// function called to update the internal parameters when the modifiable /// parameters are modified virtual void updateInternalParameters() {} public: /// extrapolate internal values virtual void extrapolateInternal(const ID &id, const Element &element, const Matrix &points, Matrix &extrapolated); /// compute the p-wave speed in the material virtual Real getPushWaveSpeed(const Element & /*element*/) const { AKANTU_TO_IMPLEMENT(); } /// compute the s-wave speed in the material virtual Real getShearWaveSpeed(const Element & /*element*/) const { AKANTU_TO_IMPLEMENT(); } /// get a material celerity to compute the stable time step (default: is the /// push wave speed) virtual Real getCelerity(const Element &element) const { return getPushWaveSpeed(element); } /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: template void registerInternal(InternalField & /*vect*/) { AKANTU_TO_IMPLEMENT(); } template void unregisterInternal(InternalField & /*vect*/) { AKANTU_TO_IMPLEMENT(); } /// initialize the material computed parameter virtual void initMaterial(); /// compute the residual for this material // virtual void updateResidual(GhostType ghost_type = _not_ghost); /// assemble the residual for this material virtual void assembleInternalForces(GhostType ghost_type); /// save the internals in the previous_stress if needed virtual void savePreviousState(); /// restore the internals from previous_stress if needed virtual void restorePreviousState(); /// compute the stresses for this material virtual void computeAllStresses(GhostType ghost_type = _not_ghost); // virtual void // computeAllStressesFromTangentModuli(GhostType ghost_type = _not_ghost); virtual void computeAllCauchyStresses(GhostType ghost_type = _not_ghost); /// set material to steady state void setToSteadyState(GhostType ghost_type = _not_ghost); /// compute the stiffness matrix virtual void assembleStiffnessMatrix(GhostType ghost_type); /// add an element to the local mesh filter inline auto addElement(ElementType type, Int element, GhostType ghost_type); inline auto addElement(const Element &element); /// add many elements at once void addElements(const Array &elements_to_add); /// remove many element at once void removeElements(const Array &elements_to_remove); /// function to print the contain of the class void printself(std::ostream &stream, int indent = 0) const override; /** * interpolate stress on given positions for each element by means * of a geometrical interpolation on quadrature points */ void interpolateStress(ElementTypeMapArray &result, GhostType ghost_type = _not_ghost); /** * interpolate stress on given positions for each element by means * of a geometrical interpolation on quadrature points and store the * results per facet */ void interpolateStressOnFacets(ElementTypeMapArray &result, ElementTypeMapArray &by_elem_result, GhostType ghost_type = _not_ghost); /** * function to initialize the elemental field interpolation * function by inverting the quadrature points' coordinates */ void initElementalFieldInterpolation( const ElementTypeMapArray &interpolation_points_coordinates); /* ------------------------------------------------------------------------ */ /* Common part */ /* ------------------------------------------------------------------------ */ protected: /* ------------------------------------------------------------------------ */ constexpr static inline Int getTangentStiffnessVoigtSize(Int dim) { return (dim * (dim - 1) / 2 + dim); } template constexpr static inline Int getTangentStiffnessVoigtSize() { return getTangentStiffnessVoigtSize(dim); } /// compute the potential energy by element void computePotentialEnergyByElements(); /// resize the intenals arrays virtual void resizeInternals(); template decltype(auto) getArguments(ElementType el_type, GhostType ghost_type) { auto &&args = zip(tuple::get<"grad_u"_h>() = make_view(this->gradu(el_type, ghost_type)), tuple::get<"previous_sigma"_h>() = make_view(this->stress.previous(el_type, ghost_type)), tuple::get<"previous_grad_u"_h>() = make_view(this->gradu.previous(el_type, ghost_type))); if (not finite_deformation) { return zip_append(args, tuple::get<"sigma"_h>() = make_view( this->stress(el_type, ghost_type))); } return zip_append(args, tuple::get<"sigma"_h>() = make_view( this->piola_kirchhoff_2(el_type, ghost_type))); } template decltype(auto) getArgumentsTangent(Array &tangent_matrix, ElementType el_type, GhostType ghost_type) { constexpr auto tangent_size = Material::getTangentStiffnessVoigtSize(dim); return zip(tuple::get<"tangent_moduli"_h>() = make_view(tangent_matrix), tuple::get<"grad_u"_h>() = make_view(this->gradu(el_type, ghost_type))); } /* ------------------------------------------------------------------------ */ /* Finite deformation functions */ /* This functions area implementing what is described in the paper of Bathe */ /* et al, in IJNME, Finite Element Formulations For Large Deformation */ /* Dynamic Analysis, Vol 9, 353-386, 1975 */ /* ------------------------------------------------------------------------ */ protected: /// assemble the residual template void assembleInternalForces(GhostType ghost_type); template void computeAllStressesFromTangentModuli(ElementType type, GhostType ghost_type); template void assembleStiffnessMatrix(ElementType type, GhostType ghost_type); /// assembling in finite deformation template void assembleStiffnessMatrixNL(ElementType type, GhostType ghost_type); template void assembleStiffnessMatrixL2(ElementType type, GhostType ghost_type); /* ------------------------------------------------------------------------ */ /* Conversion functions */ /* ------------------------------------------------------------------------ */ public: /// Size of the Stress matrix for the case of finite deformation see: Bathe et /// al, IJNME, Vol 9, 353-386, 1975 static constexpr inline Int getCauchyStressMatrixSize(Int dim); /// Sets the stress matrix according to Bathe et al, IJNME, Vol 9, 353-386, /// 1975 template static constexpr inline void setCauchyStressMatrix(const Eigen::MatrixBase &S_t, Eigen::MatrixBase &sigma); /// write the stress tensor in the Voigt notation. template static constexpr inline decltype(auto) stressToVoigt(const Eigen::MatrixBase &stress) { return VoigtHelper::matrixToVoigt(stress); } /// write the strain tensor in the Voigt notation. template static constexpr inline decltype(auto) strainToVoigt(const Eigen::MatrixBase &strain) { return VoigtHelper::matrixToVoigtWithFactors(strain); } /// write a voigt vector to stress template static constexpr inline void voigtToStress(const Eigen::MatrixBase &voigt, Eigen::MatrixBase &stress) { VoigtHelper::voigtToMatrix(voigt, stress); } /// Computation of Cauchy stress tensor in the case of finite deformation from /// the 2nd Piola-Kirchhoff for a given element type template void StoCauchy(ElementType el_type, GhostType ghost_type = _not_ghost); /// Computation the Cauchy stress the 2nd Piola-Kirchhoff and the deformation /// gradient template static constexpr inline void StoCauchy(const Eigen::MatrixBase &F, const Eigen::MatrixBase &S, Eigen::MatrixBase &sigma, const Real &C33 = 1.0); template static constexpr inline decltype(auto) StoCauchy(const Eigen::MatrixBase &F, const Eigen::MatrixBase &S, const Real &C33 = 1.0); template static constexpr inline void gradUToF(const Eigen::MatrixBase &grad_u, Eigen::MatrixBase &F); template static constexpr inline decltype(auto) gradUToF(const Eigen::MatrixBase &grad_u); template static constexpr inline void rightCauchy(const Eigen::MatrixBase &F, Eigen::MatrixBase &C); template static constexpr inline decltype(auto) rightCauchy(const Eigen::MatrixBase &F); template static constexpr inline void leftCauchy(const Eigen::MatrixBase &F, Eigen::MatrixBase &B); template static constexpr inline decltype(auto) leftCauchy(const Eigen::MatrixBase &F); template static constexpr inline void gradUToEpsilon(const Eigen::MatrixBase &grad_u, Eigen::MatrixBase &epsilon); template static constexpr inline decltype(auto) gradUToEpsilon(const Eigen::MatrixBase &grad_u); template static constexpr inline void gradUToE(const Eigen::MatrixBase &grad_u, Eigen::MatrixBase &epsilon); template static constexpr inline decltype(auto) gradUToE(const Eigen::MatrixBase &grad_u); template static constexpr inline void computeDeviatoric(const Eigen::MatrixBase &sigma, Eigen::MatrixBase &sigma_dev) { sigma_dev = sigma - Matrix::Identity() * sigma.trace() / dim; } template static constexpr inline decltype(auto) computeDeviatoric(const Eigen::MatrixBase &sigma) { Matrix sigma_dev; Material::computeDeviatoric(sigma, sigma_dev); return sigma_dev; } template static inline Real stressToVonMises(const Eigen::MatrixBase &stress); protected: /// converts global element to local element inline Element convertToLocalElement(const Element &global_element) const; /// converts local element to global element inline Element convertToGlobalElement(const Element &local_element) const; /// converts global quadrature point to local quadrature point inline IntegrationPoint convertToLocalPoint(const IntegrationPoint &global_point) const; /// converts local quadrature point to global quadrature point inline IntegrationPoint convertToGlobalPoint(const IntegrationPoint &local_point) const; /* ------------------------------------------------------------------------ */ /* DataAccessor inherited members */ /* ------------------------------------------------------------------------ */ public: inline Int 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; template inline void packElementDataHelper(const ElementTypeMapArray &data_to_pack, CommunicationBuffer &buffer, const Array &elements, const ID &fem_id = ID()) const; template inline void unpackElementDataHelper(ElementTypeMapArray &data_to_unpack, CommunicationBuffer &buffer, const Array &elements, const ID &fem_id = ID()); /* ------------------------------------------------------------------------ */ /* MeshEventHandler inherited members */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ void onNodesAdded(const Array &, const NewNodesEvent &) override{}; void onNodesRemoved(const Array &, const Array &, const RemovedNodesEvent &) override{}; void onElementsAdded(const Array &element_list, const NewElementsEvent &event) override; void onElementsRemoved(const Array &element_list, const ElementTypeMapArray &new_numbering, const RemovedElementsEvent &event) override; void onElementsChanged(const Array &, const Array &, const ElementTypeMapArray &, const ChangedElementsEvent &) override{}; /* ------------------------------------------------------------------------ */ /* SolidMechanicsModelEventHandler inherited members */ /* ------------------------------------------------------------------------ */ public: virtual void beforeSolveStep(); virtual void afterSolveStep(bool converged = true); void onDamageIteration() override; void onDamageUpdate() override; void onDump() override; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(Name, name, const std::string &); AKANTU_GET_MACRO(Model, model, const SolidMechanicsModel &) AKANTU_GET_MACRO(ID, id, const ID &); AKANTU_GET_MACRO(Rho, rho, Real); AKANTU_SET_MACRO(Rho, rho, Real); AKANTU_GET_MACRO(SpatialDimension, spatial_dimension, Int); /// return the potential energy for the subset of elements contained by the /// material Real getPotentialEnergy(); /// return the potential energy for the provided element Real getPotentialEnergy(const Element &element); [[gnu::deprecated("Use the interface with an Element")]] Real getPotentialEnergy(ElementType type, Int index); /// return the energy (identified by id) for the subset of elements contained /// by the material virtual Real getEnergy(const std::string &type); /// return the energy (identified by id) for the provided element virtual Real getEnergy(const std::string &energy_id, const Element &element); [[gnu::deprecated("Use the interface with an Element")]] virtual Real getEnergy(const std::string &energy_id, ElementType type, Idx index) final { return getEnergy(energy_id, {type, index, _not_ghost}); } AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ElementFilter, element_filter, Idx); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(GradU, gradu, Real); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Stress, stress, Real); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(PotentialEnergy, potential_energy, Real); AKANTU_GET_MACRO(GradU, gradu, const ElementTypeMapArray &); AKANTU_GET_MACRO(Stress, stress, const ElementTypeMapArray &); AKANTU_GET_MACRO(ElementFilter, element_filter, const ElementTypeMapArray &); AKANTU_GET_MACRO(FEEngine, fem, FEEngine &); bool isNonLocal() const { return is_non_local; } template const Array &getArray(const ID &id, ElementType type, GhostType ghost_type = _not_ghost) const; template Array &getArray(const ID &id, ElementType type, GhostType ghost_type = _not_ghost); template const InternalField &getInternal(const ID &id) const; template InternalField &getInternal(const ID &id); template inline bool isInternal(const ID &id, ElementKind element_kind) const; template ElementTypeMap getInternalDataPerElem(const ID &id, ElementKind element_kind) const; bool isFiniteDeformation() const { return finite_deformation; } bool isInelasticDeformation() const { return inelastic_deformation; } template inline void setParam(const ID ¶m, T value); inline const Parameter &getParam(const ID ¶m) const; template void flattenInternal(const std::string &field_id, ElementTypeMapArray &internal_flat, GhostType ghost_type = _not_ghost, ElementKind element_kind = _ek_not_defined) const; /// apply a constant eigengrad_u everywhere in the material virtual void applyEigenGradU(const Matrix &prescribed_eigen_grad_u, GhostType /*ghost_type*/ = _not_ghost); bool hasMatrixChanged(const ID &id) { if (id == "K") { return hasStiffnessMatrixChanged() or finite_deformation; } return true; } MatrixType getMatrixType(const ID &id) { if (id == "K") { return getTangentType(); } if (id == "M") { return _symmetric; } return _mt_not_defined; } /// specify if the matrix need to be recomputed for this material virtual bool hasStiffnessMatrixChanged() { return true; } /// specify the type of matrix, if not overloaded the material is not valid /// for static or implicit computations virtual MatrixType getTangentType() { return _mt_not_defined; } /// static method to reteive the material factory static MaterialFactory &getFactory(); protected: bool isInit() const { return is_init; } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// boolean to know if the material has been initialized bool is_init{false}; std::map *> internal_vectors_real; std::map *> internal_vectors_int; std::map *> internal_vectors_bool; protected: ID id; /// Link to the fem object in the model FEEngine &fem; /// Finite deformation bool finite_deformation{false}; /// Finite deformation bool inelastic_deformation{false}; /// material name std::string name; /// The model to witch the material belong SolidMechanicsModel &model; /// density : rho Real rho{0.}; /// spatial dimension Int spatial_dimension; /// list of element handled by the material ElementTypeMapArray element_filter; /// stresses arrays ordered by element types InternalField stress; /// eigengrad_u arrays ordered by element types InternalField eigengradu; /// grad_u arrays ordered by element types InternalField gradu; /// Green Lagrange strain (Finite deformation) InternalField green_strain; /// Second Piola-Kirchhoff stress tensor arrays ordered by element types /// (Finite deformation) InternalField piola_kirchhoff_2; /// potential energy by element InternalField potential_energy; /// tell if using in non local mode or not bool is_non_local{false}; /// tell if the material need the previous stress state bool use_previous_stress{false}; /// tell if the material need the previous strain state bool use_previous_gradu{false}; /// elemental field interpolation coordinates InternalField interpolation_inverse_coordinates; /// elemental field interpolation points InternalField interpolation_points_matrices; /// vector that contains the names of all the internals that need to /// be transferred when material interfaces move std::vector internals_to_transfer; private: /// eigen_grad_u for the parser Matrix eigen_grad_u; }; /// standard output stream operator inline std::ostream &operator<<(std::ostream &stream, const Material &_this) { _this.printself(stream); return stream; } } // namespace akantu #include "material_inline_impl.hh" #include "internal_field_tmpl.hh" #include "random_internal_field_tmpl.hh" /* -------------------------------------------------------------------------- */ /* Auto loop */ /* -------------------------------------------------------------------------- */ /// This can be used to automatically write the loop on quadrature points in /// functions such as computeStress. This macro in addition to write the loop /// provides two tensors (matrices) sigma and grad_u #define MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type) \ - auto &&grad_u_view = make_view(this->gradu(el_type, ghost_type)); \ + auto &&grad_u_view = \ + make_view(this->gradu(el_type, ghost_type), this->spatial_dimension, \ + this->spatial_dimension); \ \ - auto stress_view = make_view(this->stress(el_type, ghost_type)); \ + auto stress_view = \ + make_view(this->stress(el_type, ghost_type), this->spatial_dimension, \ + this->spatial_dimension); \ \ if (this->isFiniteDeformation()) { \ - stress_view = \ - make_view(this->piola_kirchhoff_2(el_type, ghost_type)); \ + stress_view = make_view(this->piola_kirchhoff_2(el_type, ghost_type), \ + this->spatial_dimension, this->spatial_dimension); \ } \ \ for (auto &&data : zip(grad_u_view, stress_view)) { \ [[gnu::unused]] auto &&grad_u = std::get<0>(data); \ [[gnu::unused]] auto &&sigma = std::get<1>(data) #define MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END } /// This can be used to automatically write the loop on quadrature points in /// functions such as computeTangentModuli. This macro in addition to write the /// loop provides two tensors (matrices) sigma_tensor, grad_u, and a matrix /// where the elemental tangent moduli should be stored in Voigt Notation #define MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_mat) \ - auto &&grad_u_view = make_view(this->gradu(el_type, ghost_type)); \ + auto &&grad_u_view = \ + make_view(this->gradu(el_type, ghost_type), this->spatial_dimension, \ + this->spatial_dimension); \ \ - auto &&stress_view = make_view(this->stress(el_type, ghost_type)); \ + auto &&stress_view = \ + make_view(this->stress(el_type, ghost_type), this->spatial_dimension, \ + this->spatial_dimension); \ \ - constexpr auto tangent_size = this->getTangentStiffnessVoigtSize(dim); \ + auto tangent_size = \ + Material::getTangentStiffnessVoigtSize(this->spatial_dimension); \ \ - auto &&tangent_view = make_view(tangent_mat); \ + auto &&tangent_view = make_view(tangent_mat, tangent_size, tangent_size); \ \ for (auto &&data : zip(grad_u_view, stress_view, tangent_view)) { \ [[gnu::unused]] auto &&grad_u = std::get<0>(data); \ [[gnu::unused]] auto &&sigma = std::get<1>(data); \ auto &&tangent = std::get<2>(data); #define MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END } /* -------------------------------------------------------------------------- */ #define INSTANTIATE_MATERIAL_ONLY(mat_name) \ template class mat_name<1>; /* NOLINT */ \ template class mat_name<2>; /* NOLINT */ \ template class mat_name<3> /* NOLINT */ #define MATERIAL_DEFAULT_PER_DIM_ALLOCATOR(id, mat_name) \ [](Int dim, const ID &, SolidMechanicsModel &model, \ const ID &id) /* NOLINT */ \ -> std::unique_ptr< \ Material> { /* NOLINT */ \ switch (dim) { \ case 1: \ return std::make_unique>(/* NOLINT */ \ model, id); \ case 2: \ return std::make_unique>(/* NOLINT */ \ model, id); \ case 3: \ return std::make_unique>(/* NOLINT */ \ model, id); \ default: \ AKANTU_EXCEPTION( \ "The dimension " \ << dim \ << "is not a valid dimension for the material " \ << #id); \ } \ } #define INSTANTIATE_MATERIAL(id, mat_name) \ INSTANTIATE_MATERIAL_ONLY(mat_name); \ static bool material_is_alocated_##id = \ MaterialFactory::getInstance().registerAllocator( \ #id, MATERIAL_DEFAULT_PER_DIM_ALLOCATOR(id, mat_name)) #define INSTANTIATE_MATERIAL_NO_INSTATIATION(id, mat_name) \ static bool material_is_alocated_##id [[gnu::unused]] = \ MaterialFactory::getInstance().registerAllocator( \ #id, MATERIAL_DEFAULT_PER_DIM_ALLOCATOR(id, mat_name)) #endif /* AKANTU_MATERIAL_HH_ */ diff --git a/src/model/solid_mechanics/material_inline_impl.hh b/src/model/solid_mechanics/material_inline_impl.hh index 3f649d097..7a666ba4d 100644 --- a/src/model/solid_mechanics/material_inline_impl.hh +++ b/src/model/solid_mechanics/material_inline_impl.hh @@ -1,564 +1,557 @@ /** * @file material_inline_impl.hh * * @author Fabian Barras * @author Aurelia Isabel Cuba Ramos * @author Lucas Frerot * @author Enrico Milanese * @author Daniel Pino Muñoz * @author Nicolas Richart * @author Marco Vocialta * * @date creation: Tue Jul 27 2010 * @date last modification: Fri Apr 09 2021 * * @brief Implementation of the inline functions of the class material * * * @section LICENSE * * Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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 "integration_point.hh" #include "material.hh" #include "solid_mechanics_model.hh" /* -------------------------------------------------------------------------- */ // #ifndef __AKANTU_MATERIAL_INLINE_IMPL_CC__ // #define __AKANTU_MATERIAL_INLINE_IMPL_CC__ namespace akantu { /* -------------------------------------------------------------------------- */ inline auto Material::addElement(ElementType type, Int element, GhostType ghost_type) { - auto & el_filter = this->element_filter(type, ghost_type); + auto &el_filter = this->element_filter(type, ghost_type); el_filter.push_back(element); return el_filter.size() - 1; } /* -------------------------------------------------------------------------- */ -inline auto Material::addElement(const Element & element) { +inline auto Material::addElement(const Element &element) { return this->addElement(element.type, element.element, element.ghost_type); } /* -------------------------------------------------------------------------- */ constexpr inline Int Material::getCauchyStressMatrixSize(Int dim) { return (dim * dim); } /* -------------------------------------------------------------------------- */ template -constexpr inline void Material::gradUToF(const Eigen::MatrixBase & grad_u, - Eigen::MatrixBase & F) { - AKANTU_DEBUG_ASSERT(F.size() >= grad_u.size() && grad_u.size() == dim * dim, - "The dimension of the tensor F should be greater or " - "equal to the dimension of the tensor grad_u."); +constexpr inline void Material::gradUToF(const Eigen::MatrixBase &grad_u, + Eigen::MatrixBase &F) { + assert(F.size() >= grad_u.size() && grad_u.size() == dim * dim && + "The dimension of the tensor F should be greater or " + "equal to the dimension of the tensor grad_u."); F.Identity(); F.template block(0, 0) += grad_u; } /* -------------------------------------------------------------------------- */ template constexpr inline decltype(auto) -Material::gradUToF(const Eigen::MatrixBase & grad_u) { +Material::gradUToF(const Eigen::MatrixBase &grad_u) { Matrix F; gradUToF(grad_u, F); return F; } /* -------------------------------------------------------------------------- */ template -constexpr inline void Material::StoCauchy(const Eigen::MatrixBase & F, - const Eigen::MatrixBase & S, - Eigen::MatrixBase & sigma, - const Real & C33) { +constexpr inline void Material::StoCauchy(const Eigen::MatrixBase &F, + const Eigen::MatrixBase &S, + Eigen::MatrixBase &sigma, + const Real &C33) { Real J = F.determinant() * sqrt(C33); Matrix F_S; F_S = F * S; Real constant = J ? 1. / J : 0; sigma = constant * F_S * F.transpose(); } /* -------------------------------------------------------------------------- */ template constexpr inline decltype(auto) -Material::StoCauchy(const Eigen::MatrixBase & F, - const Eigen::MatrixBase & S, const Real & C33) { +Material::StoCauchy(const Eigen::MatrixBase &F, + const Eigen::MatrixBase &S, const Real &C33) { Matrix sigma; Material::StoCauchy(F, S, sigma, C33); return sigma; } /* -------------------------------------------------------------------------- */ template -constexpr inline void Material::rightCauchy(const Eigen::MatrixBase & F, - Eigen::MatrixBase & C) { +constexpr inline void Material::rightCauchy(const Eigen::MatrixBase &F, + Eigen::MatrixBase &C) { C = F.transpose() * F; } /* -------------------------------------------------------------------------- */ template constexpr inline decltype(auto) -Material::rightCauchy(const Eigen::MatrixBase & F) { +Material::rightCauchy(const Eigen::MatrixBase &F) { Matrix C; rightCauchy(F, C); return C; } /* -------------------------------------------------------------------------- */ template -constexpr inline void Material::leftCauchy(const Eigen::MatrixBase & F, - Eigen::MatrixBase & B) { +constexpr inline void Material::leftCauchy(const Eigen::MatrixBase &F, + Eigen::MatrixBase &B) { B = F * F.transpose(); } /* -------------------------------------------------------------------------- */ template constexpr inline decltype(auto) -Material::leftCauchy(const Eigen::MatrixBase & F) { +Material::leftCauchy(const Eigen::MatrixBase &F) { Matrix B; rightCauchy(F, B); return B; } /* -------------------------------------------------------------------------- */ template constexpr inline void -Material::gradUToEpsilon(const Eigen::MatrixBase & grad_u, - Eigen::MatrixBase & epsilon) { +Material::gradUToEpsilon(const Eigen::MatrixBase &grad_u, + Eigen::MatrixBase &epsilon) { epsilon = .5 * (grad_u.transpose() + grad_u); } /* -------------------------------------------------------------------------- */ template inline decltype(auto) constexpr Material::gradUToEpsilon( - const Eigen::MatrixBase & grad_u) { + const Eigen::MatrixBase &grad_u) { Matrix epsilon; Material::gradUToEpsilon(grad_u, epsilon); return epsilon; } /* -------------------------------------------------------------------------- */ template -constexpr inline void Material::gradUToE(const Eigen::MatrixBase & grad_u, - Eigen::MatrixBase & E) { +constexpr inline void Material::gradUToE(const Eigen::MatrixBase &grad_u, + Eigen::MatrixBase &E) { E = (grad_u.transpose() * grad_u + grad_u.transpose() + grad_u) / 2.; } /* -------------------------------------------------------------------------- */ template constexpr inline decltype(auto) -Material::gradUToE(const Eigen::MatrixBase & grad_u) { +Material::gradUToE(const Eigen::MatrixBase &grad_u) { Matrix E; gradUToE(grad_u, E); return E; } /* -------------------------------------------------------------------------- */ template -inline Real Material::stressToVonMises(const Eigen::MatrixBase & stress) { +inline Real Material::stressToVonMises(const Eigen::MatrixBase &stress) { // compute deviatoric stress auto dim = stress.cols(); - auto && deviatoric_stress = + auto &&deviatoric_stress = stress - Matrix::Identity(dim, dim) * stress.trace() / 3.; // return Von Mises stress return std::sqrt(3. * deviatoric_stress.doubleDot(deviatoric_stress) / 2.); } /* -------------------------------------------------------------------------- */ template constexpr inline void -Material::setCauchyStressMatrix(const Eigen::MatrixBase & S_t, - Eigen::MatrixBase & sigma) { - AKANTU_DEBUG_IN(); - +Material::setCauchyStressMatrix(const Eigen::MatrixBase &S_t, + Eigen::MatrixBase &sigma) { sigma.zero(); /// see Finite ekement formulations for large deformation dynamic analysis, /// Bathe et al. IJNME vol 9, 1975, page 364 ^t \f$\tau\f$ for (Int i = 0; i < dim; ++i) { for (Int m = 0; m < dim; ++m) { for (Int n = 0; n < dim; ++n) { sigma(i * dim + m, i * dim + n) = S_t(m, n); } } } - - AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ inline Element -Material::convertToLocalElement(const Element & global_element) const { +Material::convertToLocalElement(const Element &global_element) const { auto ge = global_element.element; #ifndef AKANTU_NDEBUG auto model_mat_index = this->model.getMaterialByElement( global_element.type, global_element.ghost_type)(ge); auto mat_index = this->model.getMaterialIndex(this->name); AKANTU_DEBUG_ASSERT(model_mat_index == mat_index, "Conversion of a global element in a local element for " "the wrong material " << this->name << std::endl); #endif auto le = this->model.getMaterialLocalNumbering( global_element.type, global_element.ghost_type)(ge); Element tmp_quad{global_element.type, le, global_element.ghost_type}; return tmp_quad; } /* -------------------------------------------------------------------------- */ inline Element -Material::convertToGlobalElement(const Element & local_element) const { +Material::convertToGlobalElement(const Element &local_element) const { auto le = local_element.element; auto ge = this->element_filter(local_element.type, local_element.ghost_type)(le); Element tmp_quad{local_element.type, ge, local_element.ghost_type}; return tmp_quad; } /* -------------------------------------------------------------------------- */ inline IntegrationPoint -Material::convertToLocalPoint(const IntegrationPoint & global_point) const { - const FEEngine & fem = this->model.getFEEngine(); - auto && nb_quad = fem.getNbIntegrationPoints(global_point.type); - auto && el = +Material::convertToLocalPoint(const IntegrationPoint &global_point) const { + const FEEngine &fem = this->model.getFEEngine(); + auto &&nb_quad = fem.getNbIntegrationPoints(global_point.type); + auto &&el = this->convertToLocalElement(static_cast(global_point)); return IntegrationPoint(el, global_point.num_point, nb_quad); } /* -------------------------------------------------------------------------- */ inline IntegrationPoint -Material::convertToGlobalPoint(const IntegrationPoint & local_point) const { - const FEEngine & fem = this->model.getFEEngine(); +Material::convertToGlobalPoint(const IntegrationPoint &local_point) const { + const FEEngine &fem = this->model.getFEEngine(); auto nb_quad = fem.getNbIntegrationPoints(local_point.type); Element el = this->convertToGlobalElement(static_cast(local_point)); IntegrationPoint tmp_quad(el, local_point.num_point, nb_quad); return tmp_quad; } /* -------------------------------------------------------------------------- */ -inline Int Material::getNbData(const Array & elements, - const SynchronizationTag & tag) const { +inline Int Material::getNbData(const Array &elements, + const SynchronizationTag &tag) const { if (tag == SynchronizationTag::_smm_stress) { return (this->isFiniteDeformation() ? 3 : 1) * spatial_dimension * spatial_dimension * sizeof(Real) * this->getModel().getNbIntegrationPoints(elements); } return 0; } /* -------------------------------------------------------------------------- */ -inline void Material::packData(CommunicationBuffer & buffer, - const Array & elements, - const SynchronizationTag & tag) const { +inline void Material::packData(CommunicationBuffer &buffer, + const Array &elements, + const SynchronizationTag &tag) const { if (tag == SynchronizationTag::_smm_stress) { if (this->isFiniteDeformation()) { packElementDataHelper(piola_kirchhoff_2, buffer, elements); packElementDataHelper(gradu, buffer, elements); } packElementDataHelper(stress, buffer, elements); } } /* -------------------------------------------------------------------------- */ -inline void Material::unpackData(CommunicationBuffer & buffer, - const Array & elements, - const SynchronizationTag & tag) { +inline void Material::unpackData(CommunicationBuffer &buffer, + const Array &elements, + const SynchronizationTag &tag) { if (tag == SynchronizationTag::_smm_stress) { if (this->isFiniteDeformation()) { unpackElementDataHelper(piola_kirchhoff_2, buffer, elements); unpackElementDataHelper(gradu, buffer, elements); } unpackElementDataHelper(stress, buffer, elements); } } /* -------------------------------------------------------------------------- */ -inline const Parameter & Material::getParam(const ID & param) const { +inline const Parameter &Material::getParam(const ID ¶m) const { try { return get(param); } catch (...) { AKANTU_EXCEPTION("No parameter " << param << " in the material " << getID()); } } /* -------------------------------------------------------------------------- */ -template -inline void Material::setParam(const ID & param, T value) { +template inline void Material::setParam(const ID ¶m, T value) { try { set(param, value); } catch (...) { AKANTU_EXCEPTION("No parameter " << param << " in the material " << getID()); } updateInternalParameters(); } /* -------------------------------------------------------------------------- */ template inline void Material::packElementDataHelper( - const ElementTypeMapArray & data_to_pack, CommunicationBuffer & buffer, - const Array & elements, const ID & fem_id) const { + const ElementTypeMapArray &data_to_pack, CommunicationBuffer &buffer, + const Array &elements, const ID &fem_id) const { DataAccessor::packElementalDataHelper(data_to_pack, buffer, elements, true, model.getFEEngine(fem_id)); } /* -------------------------------------------------------------------------- */ template inline void Material::unpackElementDataHelper( - ElementTypeMapArray & data_to_unpack, CommunicationBuffer & buffer, - const Array & elements, const ID & fem_id) { + ElementTypeMapArray &data_to_unpack, CommunicationBuffer &buffer, + const Array &elements, const ID &fem_id) { DataAccessor::unpackElementalDataHelper(data_to_unpack, buffer, elements, true, model.getFEEngine(fem_id)); } /* -------------------------------------------------------------------------- */ template <> -inline void Material::registerInternal(InternalField & vect) { +inline void Material::registerInternal(InternalField &vect) { internal_vectors_real[vect.getID()] = &vect; } template <> -inline void Material::registerInternal(InternalField & vect) { +inline void Material::registerInternal(InternalField &vect) { internal_vectors_int[vect.getID()] = &vect; } template <> -inline void Material::registerInternal(InternalField & vect) { +inline void Material::registerInternal(InternalField &vect) { internal_vectors_bool[vect.getID()] = &vect; } /* -------------------------------------------------------------------------- */ template <> -inline void Material::unregisterInternal(InternalField & vect) { +inline void Material::unregisterInternal(InternalField &vect) { internal_vectors_real.erase(vect.getID()); } template <> -inline void Material::unregisterInternal(InternalField & vect) { +inline void Material::unregisterInternal(InternalField &vect) { internal_vectors_int.erase(vect.getID()); } template <> -inline void Material::unregisterInternal(InternalField & vect) { +inline void Material::unregisterInternal(InternalField &vect) { internal_vectors_bool.erase(vect.getID()); } /* -------------------------------------------------------------------------- */ template inline bool Material::isInternal(const ID & /*id*/, ElementKind /*element_kind*/) const { AKANTU_TO_IMPLEMENT(); } template <> -inline bool Material::isInternal(const ID & id, +inline bool Material::isInternal(const ID &id, ElementKind element_kind) const { auto internal_array = internal_vectors_real.find(this->getID() + ":" + id); return not(internal_array == internal_vectors_real.end() || internal_array->second->getElementKind() != element_kind); } /* -------------------------------------------------------------------------- */ template inline ElementTypeMap -Material::getInternalDataPerElem(const ID & field_id, +Material::getInternalDataPerElem(const ID &field_id, ElementKind element_kind) const { if (!this->template isInternal(field_id, element_kind)) { AKANTU_EXCEPTION("Cannot find internal field " << id << " in material " << this->name); } - const InternalField & internal_field = + const InternalField &internal_field = this->template getInternal(field_id); - const auto & fe_engine = internal_field.getFEEngine(); + const auto &fe_engine = internal_field.getFEEngine(); auto nb_data_per_quad = internal_field.getNbComponent(); ElementTypeMap res; for (auto ghost_type : ghost_types) { - for (auto && type : internal_field.elementTypes(ghost_type)) { + for (auto &&type : internal_field.elementTypes(ghost_type)) { auto nb_quadrature_points = fe_engine.getNbIntegrationPoints(type, ghost_type); res(type, ghost_type) = nb_data_per_quad * nb_quadrature_points; } } return res; } /* -------------------------------------------------------------------------- */ template -void Material::flattenInternal(const std::string & field_id, - ElementTypeMapArray & internal_flat, +void Material::flattenInternal(const std::string &field_id, + ElementTypeMapArray &internal_flat, const GhostType ghost_type, ElementKind element_kind) const { if (!this->template isInternal(field_id, element_kind)) { AKANTU_EXCEPTION("Cannot find internal field " << id << " in material " << this->name); } - const auto & internal_field = this->template getInternal(field_id); + const auto &internal_field = this->template getInternal(field_id); - const auto & fe_engine = internal_field.getFEEngine(); - const auto & mesh = fe_engine.getMesh(); + const auto &fe_engine = internal_field.getFEEngine(); + const auto &mesh = fe_engine.getMesh(); - for (auto && type : internal_field.filterTypes(ghost_type)) { - const auto & src_vect = internal_field(type, ghost_type); - const auto & filter = internal_field.getFilter(type, ghost_type); + for (auto &&type : internal_field.filterTypes(ghost_type)) { + const auto &src_vect = internal_field(type, ghost_type); + const auto &filter = internal_field.getFilter(type, ghost_type); // total number of elements in the corresponding mesh auto nb_element_dst = mesh.getNbElement(type, ghost_type); // number of element in the internal field auto nb_element_src = filter.size(); // number of quadrature points per elem auto nb_quad_per_elem = fe_engine.getNbIntegrationPoints(type); // number of data per quadrature point auto nb_data_per_quad = internal_field.getNbComponent(); if (not internal_flat.exists(type, ghost_type)) { internal_flat.alloc(nb_element_dst * nb_quad_per_elem, nb_data_per_quad, type, ghost_type); } if (nb_element_src == 0) { continue; } // number of data per element auto nb_data = nb_quad_per_elem * nb_data_per_quad; - auto & dst_vect = internal_flat(type, ghost_type); + auto &dst_vect = internal_flat(type, ghost_type); dst_vect.resize(nb_element_dst * nb_quad_per_elem); auto it_dst = make_view(dst_vect, nb_data).begin(); - for (auto && data : zip(filter, make_view(src_vect, nb_data))) { + for (auto &&data : zip(filter, make_view(src_vect, nb_data))) { it_dst[std::get<0>(data)] = std::get<1>(data); } } } /* -------------------------------------------------------------------------- */ template inline const InternalField & Material::getInternal(const ID & /*int_id*/) const { AKANTU_TO_IMPLEMENT(); } /* -------------------------------------------------------------------------- */ template -inline InternalField & Material::getInternal(const ID & /*int_id*/) { +inline InternalField &Material::getInternal(const ID & /*int_id*/) { AKANTU_TO_IMPLEMENT(); } /* -------------------------------------------------------------------------- */ template <> inline const InternalField & -Material::getInternal(const ID & int_id) const { +Material::getInternal(const ID &int_id) const { auto it = internal_vectors_real.find(getID() + ":" + int_id); if (it == internal_vectors_real.end()) { AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID() << ") does not contain an internal " << int_id << " (" << (getID() + ":" + int_id) << ")"); } return *it->second; } /* -------------------------------------------------------------------------- */ template <> -inline InternalField & Material::getInternal(const ID & int_id) { +inline InternalField &Material::getInternal(const ID &int_id) { auto it = internal_vectors_real.find(getID() + ":" + int_id); if (it == internal_vectors_real.end()) { AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID() << ") does not contain an internal " << int_id << " (" << (getID() + ":" + int_id) << ")"); } return *it->second; } /* -------------------------------------------------------------------------- */ template <> -inline const InternalField & -Material::getInternal(const ID & int_id) const { +inline const InternalField &Material::getInternal(const ID &int_id) const { auto it = internal_vectors_int.find(getID() + ":" + int_id); if (it == internal_vectors_int.end()) { AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID() << ") does not contain an internal " << int_id << " (" << (getID() + ":" + int_id) << ")"); } return *it->second; } /* -------------------------------------------------------------------------- */ -template <> -inline InternalField & Material::getInternal(const ID & int_id) { +template <> inline InternalField &Material::getInternal(const ID &int_id) { auto it = internal_vectors_int.find(getID() + ":" + int_id); if (it == internal_vectors_int.end()) { AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID() << ") does not contain an internal " << int_id << " (" << (getID() + ":" + int_id) << ")"); } return *it->second; } /* -------------------------------------------------------------------------- */ template -inline const Array & Material::getArray(const ID & vect_id, ElementType type, - GhostType ghost_type) const { +inline const Array &Material::getArray(const ID &vect_id, ElementType type, + GhostType ghost_type) const { try { return this->template getInternal(vect_id)(type, ghost_type); - } catch (debug::Exception & e) { + } catch (debug::Exception &e) { AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID() << ") does not contain a vector " << vect_id << " [" << e << "]"); } } /* -------------------------------------------------------------------------- */ template -inline Array & Material::getArray(const ID & vect_id, ElementType type, - GhostType ghost_type) { +inline Array &Material::getArray(const ID &vect_id, ElementType type, + GhostType ghost_type) { try { return this->template getInternal(vect_id)(type, ghost_type); - } catch (debug::Exception & e) { + } catch (debug::Exception &e) { AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID() << ") does not contain a vector " << vect_id << " [" << e << "]"); } } } // namespace akantu //#endif /* __AKANTU_MATERIAL_INLINE_IMPL_CC__ */ diff --git a/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean.cc b/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean.cc index b662040b6..3bae54102 100644 --- a/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean.cc +++ b/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean.cc @@ -1,244 +1,243 @@ /** * @file material_neohookean.cc * * @author Daniel Pino Muñoz * @author Nicolas Richart * * @date creation: Mon Apr 08 2013 * @date last modification: Thu Feb 20 2020 * * @brief Specialization of the material class for finite deformation * neo-hookean material * * * @section LICENSE * * Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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_neohookean.hh" #include "solid_mechanics_model.hh" namespace akantu { /* -------------------------------------------------------------------------- */ template MaterialNeohookean::MaterialNeohookean( - SolidMechanicsModel & model, const ID & id) + SolidMechanicsModel &model, const ID &id) : Parent(model, id) { AKANTU_DEBUG_IN(); this->registerParam("E", E, Real(0.), _pat_parsable | _pat_modifiable, "Young's modulus"); this->registerParam("nu", nu, Real(0.5), _pat_parsable | _pat_modifiable, "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->finite_deformation = true; this->initialize_third_axis_deformation = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialNeohookean::initMaterial() { PlaneStressToolbox::initMaterial(); if (spatial_dimension == 1) { nu = 0.; } this->updateInternalParameters(); } /* -------------------------------------------------------------------------- */ template <> void MaterialNeohookean<2>::initMaterial() { PlaneStressToolbox<2>::initMaterial(); this->updateInternalParameters(); if (this->plane_stress) { this->third_axis_deformation.setDefaultValue(1.); } } /* -------------------------------------------------------------------------- */ template void MaterialNeohookean::updateInternalParameters() { lambda = nu * E / ((1 + nu) * (1 - 2 * nu)); mu = E / (2 * (1 + nu)); kpa = lambda + 2. / 3. * mu; } /* -------------------------------------------------------------------------- */ template void MaterialNeohookean::computeCauchyStressPlaneStress( ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); PlaneStressToolbox::computeCauchyStressPlaneStress(el_type, ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <> void MaterialNeohookean<2>::computeCauchyStressPlaneStress( ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); auto gradu_it = this->gradu(el_type, ghost_type).begin(2, 2); auto gradu_end = this->gradu(el_type, ghost_type).end(2, 2); auto piola_it = this->piola_kirchhoff_2(el_type, ghost_type).begin(2, 2); auto stress_it = this->stress(el_type, ghost_type).begin(2, 2); auto c33_it = this->third_axis_deformation(el_type, ghost_type).begin(); for (; gradu_it != gradu_end; ++gradu_it, ++piola_it, ++stress_it, ++c33_it) { - auto && grad_u = *gradu_it; - auto && piola = *piola_it; - auto && sigma = *stress_it; + auto &&grad_u = *gradu_it; + auto &&piola = *piola_it; + auto &&sigma = *stress_it; StoCauchy<2>(gradUToF<2>(grad_u), piola, sigma, *c33_it); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialNeohookean::computeStress(ElementType el_type, GhostType ghost_type) { - for (auto && args : this->getArguments(el_type, ghost_type)) { + for (auto &&args : this->getArguments(el_type, ghost_type)) { computeStressOnQuad(args); } } /* -------------------------------------------------------------------------- */ template <> void MaterialNeohookean<2>::computeStress(ElementType el_type, GhostType ghost_type) { - auto && arguments = getArguments(el_type, ghost_type); + auto &&arguments = getArguments(el_type, ghost_type); if (this->plane_stress) { PlaneStressToolbox<2>::computeStress(el_type, ghost_type); - for (auto && args : zip_replace<"C33"_h>( + for (auto &&args : zip_replace<"C33"_h>( arguments, this->third_axis_deformation(el_type, ghost_type))) { computeStressOnQuad(args); } } else { - for (auto && args : arguments) { + for (auto &&args : arguments) { computeStressOnQuad(args); } } } /* -------------------------------------------------------------------------- */ template void MaterialNeohookean::computeThirdAxisDeformation( ElementType /*el_type*/, GhostType /*ghost_type*/) {} /* -------------------------------------------------------------------------- */ template <> void MaterialNeohookean<2>::computeThirdAxisDeformation(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_ASSERT(this->plane_stress, "The third component of the strain " "can only be computed for 2D " "problems in Plane Stress!!"); - auto && arguments = getArguments(el_type, ghost_type); - for (auto && args : zip_replace<"C33"_h>( + auto &&arguments = getArguments(el_type, ghost_type); + for (auto &&args : zip_replace<"C33"_h>( arguments, this->third_axis_deformation(el_type, ghost_type))) { computeThirdAxisDeformationOnQuad(args); } } /* -------------------------------------------------------------------------- */ template void MaterialNeohookean::computePotentialEnergy( ElementType el_type) { AKANTU_DEBUG_IN(); - constexpr Int dim = 2; Material::computePotentialEnergy(el_type); Array::scalar_iterator epot = this->potential_energy(el_type).begin(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, _not_ghost); computePotentialEnergyOnQuad(grad_u, *epot); ++epot; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialNeohookean::computeTangentModuli( - ElementType el_type, Array & tangent_matrix, GhostType ghost_type) { - auto && arguments = getArgumentsTangent(tangent_matrix, el_type, ghost_type); + ElementType el_type, Array &tangent_matrix, GhostType ghost_type) { + auto &&arguments = getArgumentsTangent(tangent_matrix, el_type, ghost_type); - for (auto && args : arguments) { + for (auto &&args : arguments) { computeTangentModuliOnQuad(args); } } /* -------------------------------------------------------------------------- */ template <> void MaterialNeohookean<2>::computeTangentModuli(ElementType el_type, - Array & tangent_matrix, + Array &tangent_matrix, GhostType ghost_type) { - auto && arguments = getArgumentsTangent(tangent_matrix, el_type, ghost_type); + auto &&arguments = getArgumentsTangent(tangent_matrix, el_type, ghost_type); if (this->plane_stress) { PlaneStressToolbox<2>::computeStress(el_type, ghost_type); - for (auto && args : zip_replace<"C33"_h>( + for (auto &&args : zip_replace<"C33"_h>( arguments, this->third_axis_deformation(el_type, ghost_type))) { computeTangentModuliOnQuad(args); } } else { - for (auto && args : arguments) { + for (auto &&args : arguments) { computeTangentModuliOnQuad(args); } } } /* -------------------------------------------------------------------------- */ template Real MaterialNeohookean::getPushWaveSpeed( const Element & /*element*/) const { return sqrt((this->lambda + 2 * this->mu) / this->rho); } /* -------------------------------------------------------------------------- */ template Real MaterialNeohookean::getShearWaveSpeed( const Element & /*element*/) const { return sqrt(this->mu / this->rho); } /* -------------------------------------------------------------------------- */ INSTANTIATE_MATERIAL(neohookean, MaterialNeohookean); } // namespace akantu diff --git a/test/test_fe_engine/test_facet_element_mapping.cc b/test/test_fe_engine/test_facet_element_mapping.cc index 927bb9137..b0d3e916d 100644 --- a/test/test_fe_engine/test_facet_element_mapping.cc +++ b/test/test_fe_engine/test_facet_element_mapping.cc @@ -1,129 +1,129 @@ /** * @file test_facet_element_mapping.cc * * @author Dana Christen * * @date creation: Sun Oct 19 2014 * @date last modification: Fri Nov 02 2018 * * @brief Test of the MeshData class * * * @section LICENSE * * Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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_error.hh" #include "mesh.hh" #include "mesh_utils.hh" /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ using namespace akantu; using namespace std; -int main(int argc, char * argv[]) { +int main(int argc, char *argv[]) { // Testing the subelement-to-element mappings Int spatial_dimension(3); akantu::initialize(argc, argv); Mesh mesh(spatial_dimension, "my_mesh"); mesh.read("./cube_physical_names.msh"); typedef Array> ElemToSubelemMapping; typedef Array SubelemToElemMapping; std::cout << "ELEMENT-SUBELEMENT MAPPING:" << std::endl; for (auto ghost_type : ghost_types) { std::cout << " " << "Ghost type: " << ghost_type << std::endl; - for (const auto & type : mesh.elementTypes(spatial_dimension, ghost_type)) { + for (const auto &type : mesh.elementTypes(spatial_dimension, ghost_type)) { - const SubelemToElemMapping & subelement_to_element = + const SubelemToElemMapping &subelement_to_element = mesh.getSubelementToElement(type, ghost_type); std::cout << " " << " " << "Element type: " << type << std::endl; std::cout << " " << " " << " " << "subelement_to_element:" << std::endl; subelement_to_element.printself(std::cout, 8); for (Int i(0); i < subelement_to_element.size(); ++i) { std::cout << " "; for (Int j(0); j < mesh.getNbFacetsPerElement(type); ++j) { if (subelement_to_element(i, j) != ElementNull) { std::cout << subelement_to_element(i, j); std::cout << ", "; } else { std::cout << "ElementNull" << ", "; } } std::cout << "for element " << i << std::endl; } } - for (const auto & type : + for (const auto &type : mesh.elementTypes(spatial_dimension - 1, ghost_type)) { - const auto & element_to_subelement = + const auto &element_to_subelement = mesh.getElementToSubelement(type, ghost_type); std::cout << " " << " " << "Element type: " << type << std::endl; std::cout << " " << " " << " " << "element_to_subelement:" << std::endl; element_to_subelement.printself(std::cout, 8); for (Int i(0); i < element_to_subelement.size(); ++i) { - const auto & vec = element_to_subelement(i); + const auto &vec = element_to_subelement(i); std::cout << " "; std::cout << "item " << i << ": [ "; if (vec.size() > 0) { - for (Int j(0); j < vec.size(); ++j) { + for (Int j(0); j < Int(vec.size()); ++j) { if (vec[j] != ElementNull) { std::cout << vec[j] << ", "; } else { std::cout << "ElementNull" << ", "; } } } else { std::cout << "empty, "; } std::cout << "]" << ", " << std::endl; } std::cout << std::endl; } } return 0; } diff --git a/test/test_fe_engine/test_gradient.cc b/test/test_fe_engine/test_gradient.cc index 9c30845b1..3f6fb9275 100644 --- a/test/test_fe_engine/test_gradient.cc +++ b/test/test_fe_engine/test_gradient.cc @@ -1,104 +1,104 @@ /** * @file test_gradient.cc * * @author Nicolas Richart * @author Peter Spijker * * @date creation: Sun Oct 19 2014 * @date last modification: Mon Feb 19 2018 * * @brief test of the fem class * * * @section LICENSE * * Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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 . * * @section DESCRIPTION * * This code is computing the gradient of a linear field and check that it gives * a constant result. It also compute the gradient the coordinates of the mesh * and check that it gives the identity * */ /* -------------------------------------------------------------------------- */ #include "test_fe_engine_fixture.hh" /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ using namespace akantu; TYPED_TEST(TestFEMFixture, GradientPoly) { this->fem->initShapeFunctions(); Real alpha[2][3] = {{13, 23, 31}, {11, 7, 5}}; const auto dim = this->dim; const auto type = this->type; - const auto & position = this->fem->getMesh().getNodes(); + const auto &position = this->fem->getMesh().getNodes(); Array const_val(this->fem->getMesh().getNbNodes(), 2, "const_val"); - for (auto && pair : zip(make_view(position, dim), make_view(const_val, 2))) { - auto & pos = std::get<0>(pair); - auto & const_ = std::get<1>(pair); + for (auto &&pair : zip(make_view(position, dim), make_view(const_val, 2))) { + auto &pos = std::get<0>(pair); + auto &const_ = std::get<1>(pair); const_.set(0.); for (Int d = 0; d < dim; ++d) { const_(0) += alpha[0][d] * pos(d); const_(1) += alpha[1][d] * pos(d); } } /// compute the gradient Array grad_on_quad(this->nb_quadrature_points_total, 2 * dim, "grad_on_quad"); this->fem->gradientOnIntegrationPoints(const_val, grad_on_quad, 2, type); /// check the results - for (auto && grad : make_view(grad_on_quad, 2, dim)) { + for (auto &&grad : make_view(grad_on_quad, 2, dim)) { for (Int d = 0; d < dim; ++d) { EXPECT_NEAR(grad(0, d), alpha[0][d], 5e-13); EXPECT_NEAR(grad(1, d), alpha[1][d], 5e-13); } } } TYPED_TEST(TestFEMFixture, GradientPositions) { this->fem->initShapeFunctions(); - const auto dim = this->dim; - const auto type = this->type; + const auto dim = TestFixture::dim; + const auto type = TestFixture::type; UInt nb_quadrature_points = this->fem->getNbIntegrationPoints(type) * this->nb_element; Array grad_coord_on_quad(nb_quadrature_points, dim * dim, "grad_coord_on_quad"); - const auto & position = this->mesh->getNodes(); + const auto &position = this->mesh->getNodes(); this->fem->gradientOnIntegrationPoints(position, grad_coord_on_quad, dim, type); auto I = Matrix::Identity(); - for (auto && grad : make_view(grad_coord_on_quad, dim, dim)) { + for (auto &&grad : make_view(grad_coord_on_quad, dim, dim)) { auto diff = (I - grad).template lpNorm(); EXPECT_NEAR(0., diff, 2e-14); } } diff --git a/test/test_mesh_utils/test_mesh_partitionate/test_mesh_partitionate_mesh_data.cc b/test/test_mesh_utils/test_mesh_partitionate/test_mesh_partitionate_mesh_data.cc index 4edaeba44..fec0ab090 100644 --- a/test/test_mesh_utils/test_mesh_partitionate/test_mesh_partitionate_mesh_data.cc +++ b/test/test_mesh_utils/test_mesh_partitionate/test_mesh_partitionate_mesh_data.cc @@ -1,114 +1,114 @@ /** * @file test_mesh_partitionate_mesh_data.cc * * @author Dana Christen * * @date creation: Sun Oct 19 2014 * @date last modification: Fri Nov 02 2018 * * @brief test of manual partitioner * * * @section LICENSE * * Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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 "mesh.hh" #include "mesh_partition_mesh_data.hh" /* -------------------------------------------------------------------------- */ #include "dumper_elemental_field.hh" #include "dumper_paraview.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; /* -------------------------------------------------------------------------- */ /* Main */ /* -------------------------------------------------------------------------- */ -int main(int argc, char * argv[]) { +int main(int argc, char *argv[]) { initialize(argc, argv); Int dim = 2; UInt nb_partitions = 8; akantu::Mesh mesh(dim); mesh.read("quad.msh"); ElementTypeMapArray partition; UInt nb_component = 1; GhostType gt = _not_ghost; - for (const auto & type : mesh.elementTypes(dim, gt)) { + for (const auto &type : mesh.elementTypes(dim, gt)) { Int nb_element = mesh.getNbElement(type, gt); partition.alloc(nb_element, nb_component, type, gt); - auto & type_partition_reference = partition(type, gt); + auto &type_partition_reference = partition(type, gt); for (Int i(0); i < nb_element; ++i) { Vector barycenter(dim); Element element{type, i, gt}; mesh.getBarycenter(element, barycenter); Real real_proc = barycenter[0] * nb_partitions; if (std::abs(real_proc - round(real_proc)) < 10 * std::numeric_limits::epsilon()) { type_partition_reference(i) = round(real_proc); } else { std::cout << "*"; type_partition_reference(i) = floor(real_proc); } std::cout << "Assigned proc " << type_partition_reference(i) << " to elem " << i << " (type " << type << ", barycenter x-coordinate " << barycenter[0] << ")" << std::endl; } } - auto * partitioner = new akantu::MeshPartitionMeshData(mesh, dim); + auto *partitioner = new akantu::MeshPartitionMeshData(mesh, dim); partitioner->setPartitionMapping(partition); partitioner->partitionate(nb_partitions); - for (const auto & type : mesh.elementTypes(dim, gt)) { - UInt nb_element = mesh.getNbElement(type, gt); - const auto & type_partition_reference = partition(type, gt); - const auto & type_partition = partitioner->getPartitions()(type, gt); + for (const auto &type : mesh.elementTypes(dim, gt)) { + auto nb_element = mesh.getNbElement(type, gt); + const auto &type_partition_reference = partition(type, gt); + const auto &type_partition = partitioner->getPartitions()(type, gt); for (Int i(0); i < nb_element; ++i) { if (not(type_partition(i) == type_partition_reference(i))) { std::cout << "Incorrect partitioning" << std::endl; return 1; } } } #ifdef DEBUG_TEST DumperParaview dumper("test-mesh-data-partition"); - dumpers::Field * field1 = + dumpers::Field *field1 = new dumpers::ElementalField(partitioner->getPartitions(), dim); - dumpers::Field * field2 = new dumpers::ElementalField(partition, dim); + dumpers::Field *field2 = new dumpers::ElementalField(partition, dim); dumper.registerMesh(mesh, dim); dumper.registerField("partitions", field1); dumper.registerField("partitions_ref", field2); dumper.dump(); #endif delete partitioner; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/patch_tests/patch_test_linear_fixture.hh b/test/test_model/patch_tests/patch_test_linear_fixture.hh index eb72ed18e..60d1f4edb 100644 --- a/test/test_model/patch_tests/patch_test_linear_fixture.hh +++ b/test/test_model/patch_tests/patch_test_linear_fixture.hh @@ -1,184 +1,183 @@ /** * @file patch_test_linear_fixture.hh * * @author Guillaume Anciaux * @author Nicolas Richart * * @date creation: Tue Jan 30 2018 * @date last modification: Sun Jun 02 2019 * * @brief Fixture for linear patch tests * * * @section LICENSE * * Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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_utils.hh" #include "model.hh" #include "test_gtest_utils.hh" /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ #ifndef AKANTU_PATCH_TEST_LINEAR_FIXTURE_HH_ #define AKANTU_PATCH_TEST_LINEAR_FIXTURE_HH_ //#define DEBUG_TEST using namespace akantu; template class TestPatchTestLinear : public ::testing::Test { public: static constexpr ElementType type = type_::value; - static constexpr size_t dim = ElementClass::getSpatialDimension(); + static constexpr Int dim = ElementClass::getSpatialDimension(); virtual void SetUp() { mesh = std::make_unique(dim); mesh->read(std::to_string(type) + ".msh"); MeshUtils::buildFacets(*mesh); mesh->createBoundaryGroupFromGeometry(); model = std::make_unique(*mesh); } virtual void TearDown() { model.reset(nullptr); mesh.reset(nullptr); } - virtual void initModel(const AnalysisMethod & method, - const std::string & material_file) { + virtual void initModel(const AnalysisMethod &method, + const std::string &material_file) { debug::setDebugLevel(dblError); getStaticParser().parse(material_file); this->model->initFull(_analysis_method = method); this->applyBC(); if (method != _static) this->model->setTimeStep(0.8 * this->model->getStableTimeStep()); } virtual void applyBC() { - auto & boundary = this->model->getBlockedDOFs(); + auto &boundary = this->model->getBlockedDOFs(); - for (auto & eg : mesh->iterateElementGroups()) { - for (const auto & node : eg.getNodeGroup()) { + for (auto &eg : mesh->iterateElementGroups()) { + for (const auto &node : eg.getNodeGroup()) { for (Int s = 0; s < boundary.getNbComponent(); ++s) { boundary(node, s) = true; } } } } - virtual void applyBConDOFs(const Array & dofs) { - const auto & coordinates = this->mesh->getNodes(); - for (auto & eg : this->mesh->iterateElementGroups()) { - for (const auto & node : eg.getNodeGroup()) { + virtual void applyBConDOFs(const Array &dofs) { + const auto &coordinates = this->mesh->getNodes(); + for (auto &eg : this->mesh->iterateElementGroups()) { + for (const auto &node : eg.getNodeGroup()) { this->setLinearDOF(dofs.begin(dofs.getNbComponent())[node], coordinates.begin(this->dim)[node]); } } } - template Matrix prescribed_gradient(const V & dof) { + template Matrix prescribed_gradient(const V &dof) { Matrix gradient(dof.getNbComponent(), dim); for (Int i = 0; i < gradient.rows(); ++i) { for (Int j = 0; j < gradient.cols(); ++j) { gradient(i, j) = alpha(i, j + 1); } } return gradient; } template - void checkGradient(const Gradient & gradient, const DOFs & dofs) { + void checkGradient(const Gradient &gradient, const DOFs &dofs) { auto pgrad = prescribed_gradient(dofs); - for (auto & grad : + for (auto &grad : make_view(gradient, gradient.getNbComponent() / dim, dim)) { auto diff = grad - pgrad; auto gradient_error = diff.template lpNorm() / grad.template lpNorm(); EXPECT_NEAR(0, gradient_error, gradient_tolerance); } } template - void checkResults(presult_func_t && presult_func, const Result & results, - const DOFs & dofs) { + void checkResults(presult_func_t &&presult_func, const Result &results, + const DOFs &dofs) { Matrix presult = presult_func(prescribed_gradient(dofs)); - for (auto & result : make_view(results, presult.rows(), presult.cols())) { + for (auto &result : make_view(results, presult.rows(), presult.cols())) { auto diff = result - presult; auto result_error = diff.template lpNorm() / presult.template lpNorm(); EXPECT_NEAR(0, result_error, result_tolerance); } } - template - void setLinearDOF(V1 && dof, V2 && coord) { + template void setLinearDOF(V1 &&dof, V2 &&coord) { for (Int i = 0; i < dof.size(); ++i) { dof(i) = this->alpha(i, 0); for (Int j = 0; j < coord.size(); ++j) { dof(i) += this->alpha(i, j + 1) * coord(j); } } } - template void checkDOFs(V && dofs) { - const auto & coordinates = mesh->getNodes(); + template void checkDOFs(V &&dofs) { + const auto &coordinates = mesh->getNodes(); Vector ref_dof(dofs.getNbComponent()); - for (auto && tuple : zip(make_view(coordinates, dim), - make_view(dofs, dofs.getNbComponent()))) { + for (auto &&tuple : zip(make_view(coordinates, dim), + make_view(dofs, dofs.getNbComponent()))) { setLinearDOF(ref_dof, std::get<0>(tuple)); auto diff = std::get<1>(tuple) - ref_dof; auto dofs_error = diff.template lpNorm(); EXPECT_NEAR(0, dofs_error, dofs_tolerance); } } protected: std::unique_ptr mesh; std::unique_ptr model; Matrix alpha{{0.01, 0.02, 0.03, 0.04}, {0.05, 0.06, 0.07, 0.08}, {0.09, 0.10, 0.11, 0.12}}; Real gradient_tolerance{1e-13}; Real result_tolerance{1e-13}; Real dofs_tolerance{1e-15}; }; template constexpr ElementType TestPatchTestLinear::type; template -constexpr size_t TestPatchTestLinear::dim; +constexpr Int TestPatchTestLinear::dim; #endif /* AKANTU_PATCH_TEST_LINEAR_FIXTURE_HH_ */ diff --git a/test/test_model/patch_tests/patch_test_linear_solid_mechanics_fixture.hh b/test/test_model/patch_tests/patch_test_linear_solid_mechanics_fixture.hh index 0977d3d66..e98c03993 100644 --- a/test/test_model/patch_tests/patch_test_linear_solid_mechanics_fixture.hh +++ b/test/test_model/patch_tests/patch_test_linear_solid_mechanics_fixture.hh @@ -1,160 +1,160 @@ /** * @file patch_test_linear_solid_mechanics_fixture.hh * * @author Nicolas Richart * * @date creation: Tue Jan 30 2018 * @date last modification: Wed Nov 18 2020 * * @brief SolidMechanics patch tests fixture * * * @section LICENSE * * Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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 "patch_test_linear_fixture.hh" #include "solid_mechanics_model.hh" /* -------------------------------------------------------------------------- */ #ifndef AKANTU_PATCH_TEST_LINEAR_SOLID_MECHANICS_FIXTURE_HH_ #define AKANTU_PATCH_TEST_LINEAR_SOLID_MECHANICS_FIXTURE_HH_ /* -------------------------------------------------------------------------- */ template class TestPatchTestSMMLinear : public TestPatchTestLinear, SolidMechanicsModel> { using parent = TestPatchTestLinear, SolidMechanicsModel>; public: static constexpr bool plane_strain = std::tuple_element_t<1, tuple_>::value; void applyBC() override { parent::applyBC(); - auto & displacement = this->model->getDisplacement(); + auto &displacement = this->model->getDisplacement(); this->applyBConDOFs(displacement); } void checkForces() { - auto & mat = this->model->getMaterial(0); - auto & internal_forces = this->model->getInternalForce(); - auto & external_forces = this->model->getExternalForce(); + auto &mat = this->model->getMaterial(0); + auto &internal_forces = this->model->getInternalForce(); + auto &external_forces = this->model->getExternalForce(); auto dim = this->dim; Matrix sigma = make_view(mat.getStress(this->type), dim, dim).begin()[0]; external_forces.zero(); if (dim > 1) { - for (auto & eg : this->mesh->iterateElementGroups()) { + for (auto &eg : this->mesh->iterateElementGroups()) { this->model->applyBC(BC::Neumann::FromHigherDim(sigma), eg.getName()); } } else { external_forces(0) = -sigma(0, 0); external_forces(1) = sigma(0, 0); } Real force_norm_inf = -std::numeric_limits::max(); Vector total_force(dim); total_force.zero(); - for (auto && f : make_view(internal_forces, dim)) { + for (auto &&f : make_view(internal_forces, dim)) { total_force += f; force_norm_inf = std::max(force_norm_inf, f.template lpNorm()); } EXPECT_NEAR(0, total_force.template lpNorm() / force_norm_inf, 1e-9); - for (auto && tuple : zip(make_view(internal_forces, dim), - make_view(external_forces, dim))) { - auto && f_int = std::get<0>(tuple); - auto && f_ext = std::get<1>(tuple); + for (auto &&tuple : zip(make_view(internal_forces, dim), + make_view(external_forces, dim))) { + auto &&f_int = std::get<0>(tuple); + auto &&f_ext = std::get<1>(tuple); auto f = f_int + f_ext; EXPECT_NEAR(0, f.template lpNorm() / force_norm_inf, 1e-9); } } void checkAll() { - auto & displacement = this->model->getDisplacement(); - auto & mat = this->model->getMaterial(0); + auto &displacement = this->model->getDisplacement(); + auto &mat = this->model->getMaterial(0); this->checkDOFs(displacement); this->checkGradient(mat.getGradU(this->type), displacement); this->checkResults( - [&](const Matrix & pstrain) { + [&](const Matrix &pstrain) { Real nu = this->model->getMaterial(0).get("nu"); Real E = this->model->getMaterial(0).get("E"); - Matrixdim, this->dim> strain = + Matrix strain = (pstrain + pstrain.transpose()) / 2.; auto trace = strain.trace(); auto lambda = nu * E / ((1 + nu) * (1 - 2 * nu)); auto mu = E / (2 * (1 + nu)); if (not this->plane_strain) { lambda = nu * E / (1 - nu * nu); } - Matrixdim, this->dim> stress; + Matrix stress; - if (this->dim == 1) { + if (parent::dim == 1) { stress = E * strain; } else { - stress = Matrixdim, this->dim>::Identity() * lambda * - trace + + stress = Matrix::Identity() * + lambda * trace + 2 * mu * strain; } return stress; }, mat.getStress(this->type), displacement); this->checkForces(); } }; template constexpr bool TestPatchTestSMMLinear::plane_strain; template struct invalid_plan_stress : std::true_type {}; template struct invalid_plan_stress> : aka::bool_constant::getSpatialDimension() != 2 and not bool_c::value> {}; using true_false = std::tuple, aka::bool_constant>; template using valid_types = aka::negation>; using model_types = gtest_list_t< tuple_filter_t>>; TYPED_TEST_SUITE(TestPatchTestSMMLinear, model_types, ); #endif /* AKANTU_PATCH_TEST_LINEAR_SOLID_MECHANICS_FIXTURE_HH_ */ diff --git a/test/test_model/test_common/test_model_solver/test_dof_manager_default.cc b/test/test_model/test_common/test_model_solver/test_dof_manager_default.cc index a6d813a69..f45e3f419 100644 --- a/test/test_model/test_common/test_model_solver/test_dof_manager_default.cc +++ b/test/test_model/test_common/test_model_solver/test_dof_manager_default.cc @@ -1,133 +1,133 @@ /** * @file test_dof_manager_default.cc * * @author Nicolas Richart * * @date creation: Fri Feb 26 2016 * @date last modification: Wed Jan 30 2019 * * @brief Test default dof manager * * * @section LICENSE * * Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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 "dof_manager_default.hh" #include "solver_callback.hh" #include "sparse_matrix_aij.hh" #include "time_step_solver.hh" using namespace akantu; /** * =\o-----o-----o-> F * | | * |---- L ----| */ class MySolverCallback : public SolverCallback { public: - MySolverCallback(Real F, DOFManagerDefault & dof_manager, UInt nb_dofs = 3) + MySolverCallback(Real F, DOFManagerDefault &dof_manager, Int nb_dofs = 3) : dof_manager(dof_manager), dispacement(nb_dofs, 1, "disp"), blocked(nb_dofs, 1), forces(nb_dofs, 1), nb_dofs(nb_dofs) { dof_manager.registerDOFs("disp", dispacement, _dst_generic); dof_manager.registerBlockedDOFs("disp", blocked); dispacement.set(0.); forces.set(0.); blocked.set(false); forces(nb_dofs - 1, _x) = F; blocked(0, _x) = true; } - void assembleMatrix(const ID & matrix_id) override { + void assembleMatrix(const ID &matrix_id) override { if (matrix_id != "K") return; - auto & K = dynamic_cast(dof_manager.getMatrix("K")); + auto &K = dynamic_cast(dof_manager.getMatrix("K")); K.zero(); for (Int i = 1; i < nb_dofs - 1; ++i) K.add(i, i, 2.); for (Int i = 0; i < nb_dofs - 1; ++i) K.add(i, i + 1, -1.); K.add(0, 0, 1); K.add(nb_dofs - 1, nb_dofs - 1, 1); // K *= 1 / L_{el} K *= nb_dofs - 1; } - MatrixType getMatrixType(const ID & matrix_id) const override { + MatrixType getMatrixType(const ID &matrix_id) const override { if (matrix_id == "K") return _symmetric; return _mt_not_defined; } void assembleLumpedMatrix(const ID &) override {} void assembleResidual() override { dof_manager.assembleToResidual("disp", forces); } void predictor() override {} void corrector() override {} - DOFManagerDefault & dof_manager; + DOFManagerDefault &dof_manager; Array dispacement; Array blocked; Array forces; - UInt nb_dofs; + Int nb_dofs; }; -int main(int argc, char * argv[]) { +int main(int argc, char *argv[]) { initialize(argc, argv); DOFManagerDefault dof_manager("test_dof_manager"); MySolverCallback callback(10., dof_manager, 11); - NonLinearSolver & nls = + NonLinearSolver &nls = dof_manager.getNewNonLinearSolver("my_nls", NonLinearSolverType::_linear); - TimeStepSolver & tss = dof_manager.getNewTimeStepSolver( + TimeStepSolver &tss = dof_manager.getNewTimeStepSolver( "my_tss", TimeStepSolverType::_static, nls, callback); tss.setIntegrationScheme("disp", IntegrationSchemeType::_pseudo_time); tss.solveStep(callback); dof_manager.getMatrix("K").saveMatrix("K_dof_manager_default.mtx"); Array::const_scalar_iterator disp_it = callback.dispacement.begin(); Array::const_scalar_iterator force_it = callback.forces.begin(); Array::const_scalar_iterator blocked_it = callback.blocked.begin(); std::cout << std::setw(8) << "disp" << " " << std::setw(8) << "force" << " " << std::setw(8) << "blocked" << std::endl; for (; disp_it != callback.dispacement.end(); ++disp_it, ++force_it, ++blocked_it) { std::cout << std::setw(8) << *disp_it << " " << std::setw(8) << *force_it << " " << std::setw(8) << std::boolalpha << *blocked_it << std::endl; } finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_common/test_model_solver/test_model_solver_dynamic.cc b/test/test_model/test_common/test_model_solver/test_model_solver_dynamic.cc index 78f6d4b5d..a7057b440 100644 --- a/test/test_model/test_common/test_model_solver/test_model_solver_dynamic.cc +++ b/test/test_model/test_common/test_model_solver/test_model_solver_dynamic.cc @@ -1,247 +1,246 @@ /** * @file test_model_solver_dynamic.cc * * @author Nicolas Richart * * @date creation: Wed Apr 13 2016 * @date last modification: Wed Aug 14 2019 * * @brief Test default dof manager * * * @section LICENSE * * Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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 "element_group.hh" #include "mesh.hh" #include "mesh_accessor.hh" #include "non_linear_solver.hh" /* -------------------------------------------------------------------------- */ #include "dumpable_inline_impl.hh" #include "dumper_element_partition.hh" #include "dumper_iohelper_paraview.hh" /* -------------------------------------------------------------------------- */ #include "test_model_solver_my_model.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #ifndef EXPLICIT #define EXPLICIT true #endif using namespace akantu; class Sinusoidal : public BC::Dirichlet::DirichletFunctor { public: - Sinusoidal(MyModel & model, Real amplitude, Real pulse_width, Real t) + Sinusoidal(MyModel &model, Real amplitude, Real pulse_width, Real t) : model(model), A(amplitude), k(2 * M_PI / pulse_width), t(t), v{std::sqrt(model.E / model.rho)} {} - void operator()(Idx n, Vector & /*flags*/, Vector & disp, - const Vector & coord) const { + void operator()(Idx n, Vector & /*flags*/, Vector &disp, + const Vector &coord) const { auto x = coord(_x); model.velocity(n, _x) = k * v * A * sin(k * (x - v * t)); disp(_x) = A * cos(k * (x - v * t)); } private: - MyModel & model; + MyModel &model; Real A{1.}; Real k{2 * M_PI}; Real t{1.}; Real v{1.}; }; -static void genMesh(Mesh & mesh, UInt nb_nodes); +static void genMesh(Mesh &mesh, UInt nb_nodes); /* -------------------------------------------------------------------------- */ -int main(int argc, char * argv[]) { +int main(int argc, char *argv[]) { initialize(argc, argv); - UInt prank = Communicator::getStaticCommunicator().whoAmI(); - UInt global_nb_nodes = 201; - UInt max_steps = 400; + Int prank = Communicator::getStaticCommunicator().whoAmI(); + Int global_nb_nodes = 201; + Int max_steps = 400; Real time_step = 0.001; Mesh mesh(1); Real F = -9.81; bool _explicit = EXPLICIT; const Real pulse_width = 0.2; const Real A = 0.01; ID dof_manager_type = "default"; #if defined(DOF_MANAGER_TYPE) dof_manager_type = DOF_MANAGER_TYPE; #endif if (prank == 0) genMesh(mesh, global_nb_nodes); mesh.distribute(); // mesh.makePeriodic(_x); MyModel model(F, mesh, _explicit, dof_manager_type); model.forces.zero(); model.blocked.zero(); model.applyBC(Sinusoidal(model, A, pulse_width, 0.), "all"); model.applyBC(BC::Dirichlet::FlagOnly(_x), "border"); if (!_explicit) { model.getNewSolver("dynamic", TimeStepSolverType::_dynamic, NonLinearSolverType::_newton_raphson); model.setIntegrationScheme("dynamic", "disp", IntegrationSchemeType::_trapezoidal_rule_2, IntegrationScheme::_displacement); } else { model.getNewSolver("dynamic", TimeStepSolverType::_dynamic_lumped, NonLinearSolverType::_lumped); model.setIntegrationScheme("dynamic", "disp", IntegrationSchemeType::_central_difference, IntegrationScheme::_acceleration); } model.setTimeStep(time_step); if (prank == 0) { std::cout << std::scientific; std::cout << std::setw(14) << "time" << "," << std::setw(14) << "wext" << "," << std::setw(14) << "epot" << "," << std::setw(14) << "ekin" << "," << std::setw(14) << "total" << "," << std::setw(14) << "max_disp" << "," << std::setw(14) << "min_disp" << std::endl; } Real wext = 0.; model.getDOFManager().zeroResidual(); model.assembleResidual(); Real epot = 0; // model.getPotentialEnergy(); Real ekin = 0; // model.getKineticEnergy(); Real einit = ekin + epot; Real etot = ekin + epot - wext - einit; Real max_disp = 0., min_disp = 0.; - for (auto && disp : model.displacement) { + for (auto &&disp : model.displacement) { max_disp = std::max(max_disp, disp); min_disp = std::min(min_disp, disp); } if (prank == 0) { std::cout << std::setw(14) << 0. << "," << std::setw(14) << wext << "," << std::setw(14) << epot << "," << std::setw(14) << ekin << "," << std::setw(14) << etot << "," << std::setw(14) << max_disp << "," << std::setw(14) << min_disp << std::endl; } #if EXPLICIT == false - NonLinearSolver & solver = - model.getDOFManager().getNonLinearSolver("dynamic"); + NonLinearSolver &solver = model.getDOFManager().getNonLinearSolver("dynamic"); solver.set("max_iterations", 20); #endif - auto && dumper = std::make_shared("dynamic", "./paraview"); + auto &&dumper = std::make_shared("dynamic", "./paraview"); mesh.registerExternalDumper(dumper, "dynamic", true); mesh.addDumpMesh(mesh); mesh.addDumpFieldExternalToDumper("dynamic", "displacement", model.displacement); mesh.addDumpFieldExternalToDumper("dynamic", "velocity", model.velocity); mesh.addDumpFieldExternalToDumper("dynamic", "forces", model.forces); mesh.addDumpFieldExternalToDumper("dynamic", "internal_forces", model.internal_forces); mesh.addDumpFieldExternalToDumper("dynamic", "acceleration", model.acceleration); mesh.dump(); for (Int i = 1; i < max_steps + 1; ++i) { model.applyBC(Sinusoidal(model, A, pulse_width, time_step * (i - 1)), "border"); model.solveStep("dynamic"); mesh.dump(); epot = model.getPotentialEnergy(); ekin = model.getKineticEnergy(); wext += model.getExternalWorkIncrement(); etot = ekin + epot - wext - einit; Real max_disp = 0., min_disp = 0.; - for (auto && disp : model.displacement) { + for (auto &&disp : model.displacement) { max_disp = std::max(max_disp, disp); min_disp = std::min(min_disp, disp); } if (prank == 0) { std::cout << std::setw(14) << time_step * i << "," << std::setw(14) << wext << "," << std::setw(14) << epot << "," << std::setw(14) << ekin << "," << std::setw(14) << etot << "," << std::setw(14) << max_disp << "," << std::setw(14) << min_disp << std::endl; } } // output.close(); finalize(); return EXIT_SUCCESS; } /* -------------------------------------------------------------------------- */ -void genMesh(Mesh & mesh, UInt nb_nodes) { +void genMesh(Mesh &mesh, UInt nb_nodes) { MeshAccessor mesh_accessor(mesh); - auto & nodes = mesh_accessor.getNodes(); - auto & conn = mesh_accessor.getConnectivity(_segment_2); + auto &nodes = mesh_accessor.getNodes(); + auto &conn = mesh_accessor.getConnectivity(_segment_2); nodes.resize(nb_nodes); - auto & all = mesh.createNodeGroup("all_nodes"); + auto &all = mesh.createNodeGroup("all_nodes"); for (Int n = 0; n < nb_nodes; ++n) { nodes(n, _x) = n * (1. / (nb_nodes - 1)); all.add(n); } mesh.createElementGroupFromNodeGroup("all", "all_nodes"); conn.resize(nb_nodes - 1); for (Int n = 0; n < nb_nodes - 1; ++n) { conn(n, 0) = n; conn(n, 1) = n + 1; } - auto & conn_points = mesh_accessor.getConnectivity(_point_1); + auto &conn_points = mesh_accessor.getConnectivity(_point_1); conn_points.resize(2); conn_points(0, 0) = 0; conn_points(1, 0) = nb_nodes - 1; - auto & border = mesh.createElementGroup("border", 0); + auto &border = mesh.createElementGroup("border", 0); border.add({_point_1, 0, _not_ghost}, true); border.add({_point_1, 1, _not_ghost}, true); mesh_accessor.makeReady(); } diff --git a/test/test_model/test_common/test_model_solver/test_model_solver_my_model.hh b/test/test_model/test_common/test_model_solver/test_model_solver_my_model.hh index ff15d1eda..147865c90 100644 --- a/test/test_model/test_common/test_model_solver/test_model_solver_my_model.hh +++ b/test/test_model/test_common/test_model_solver/test_model_solver_my_model.hh @@ -1,451 +1,448 @@ /** * @file test_model_solver_my_model.hh * * @author Nicolas Richart * * @date creation: Wed Apr 13 2016 * @date last modification: Fri Jun 26 2020 * * @brief Test default dof manager * * * @section LICENSE * * Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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_iterators.hh" #include "boundary_condition.hh" #include "communicator.hh" #include "data_accessor.hh" #include "dof_manager_default.hh" #include "element_synchronizer.hh" #include "mesh.hh" #include "model_solver.hh" #include "periodic_node_synchronizer.hh" #include "solver_vector_default.hh" #include "sparse_matrix.hh" /* -------------------------------------------------------------------------- */ namespace akantu { #ifndef AKANTU_TEST_MODEL_SOLVER_MY_MODEL_HH_ #define AKANTU_TEST_MODEL_SOLVER_MY_MODEL_HH_ /** * =\o-----o-----o-> F * | | * |---- L ----| */ class MyModel : public ModelSolver, public BoundaryCondition, public DataAccessor { public: - MyModel(Real F, Mesh & mesh, bool lumped, - const ID & dof_manager_type = "default") + MyModel(Real F, Mesh &mesh, bool lumped, + const ID &dof_manager_type = "default") : ModelSolver(mesh, ModelType::_model, "model_solver"), nb_dofs(mesh.getNbNodes()), nb_elements(mesh.getNbElement(_segment_2)), lumped(lumped), E(1.), A(1.), rho(1.), mesh(mesh), displacement(nb_dofs, 1, "disp"), velocity(nb_dofs, 1, "velo"), acceleration(nb_dofs, 1, "accel"), blocked(nb_dofs, 1, "blocked"), forces(nb_dofs, 1, "force_ext"), internal_forces(nb_dofs, 1, "force_int"), stresses(nb_elements, 1, "stress"), strains(nb_elements, 1, "strain"), initial_lengths(nb_elements, 1, "L0") { this->initDOFManager(dof_manager_type); this->initBC(*this, displacement, forces); this->getDOFManager().registerDOFs("disp", displacement, _dst_nodal); this->getDOFManager().registerDOFsDerivative("disp", 1, velocity); this->getDOFManager().registerDOFsDerivative("disp", 2, acceleration); this->getDOFManager().registerBlockedDOFs("disp", blocked); displacement.set(0.); velocity.set(0.); acceleration.set(0.); forces.set(0.); blocked.set(false); - UInt global_nb_nodes = mesh.getNbGlobalNodes(); - for (auto && n : arange(nb_dofs)) { + Int global_nb_nodes = mesh.getNbGlobalNodes(); + for (auto &&n : arange(nb_dofs)) { auto global_id = mesh.getNodeGlobalId(n); if (global_id == (global_nb_nodes - 1)) forces(n, _x) = F; if (global_id == 0) blocked(n, _x) = true; } auto cit = this->mesh.getConnectivity(_segment_2).begin(2); auto cend = this->mesh.getConnectivity(_segment_2).end(2); auto L_it = this->initial_lengths.begin(); for (; cit != cend; ++cit, ++L_it) { - auto && conn = *cit; + auto &&conn = *cit; auto n1 = conn(0); auto n2 = conn(1); auto p1 = this->mesh.getNodes()(n1, _x); auto p2 = this->mesh.getNodes()(n2, _x); *L_it = std::abs(p2 - p1); } this->registerDataAccessor(*this); this->registerSynchronizer( const_cast(this->mesh.getElementSynchronizer()), SynchronizationTag::_user_1); } void assembleLumpedMass() { - auto & M = this->getDOFManager().getLumpedMatrix("M"); + auto &M = this->getDOFManager().getLumpedMatrix("M"); M.zero(); this->assembleLumpedMass(_not_ghost); if (this->mesh.getNbElement(_segment_2, _ghost) > 0) this->assembleLumpedMass(_ghost); is_lumped_mass_assembled = true; } void assembleLumpedMass(GhostType ghost_type) { Array M(nb_dofs, 1, 0.); Array m_all_el(this->mesh.getNbElement(_segment_2, ghost_type), 2); - for (auto && data : - zip(make_view(this->mesh.getConnectivity(_segment_2), 2), - make_view(m_all_el, 2))) { - const auto & conn = std::get<0>(data); - auto & m_el = std::get<1>(data); + for (auto &&data : zip(make_view(this->mesh.getConnectivity(_segment_2), 2), + make_view(m_all_el, 2))) { + const auto &conn = std::get<0>(data); + auto &m_el = std::get<1>(data); - UInt n1 = conn(0); - UInt n2 = conn(1); + Int n1 = conn(0); + Int n2 = conn(1); Real p1 = this->mesh.getNodes()(n1, _x); Real p2 = this->mesh.getNodes()(n2, _x); Real L = std::abs(p2 - p1); Real M_n = rho * A * L / 2; m_el(0) = m_el(1) = M_n; } this->getDOFManager().assembleElementalArrayLocalArray( m_all_el, M, _segment_2, ghost_type); this->getDOFManager().assembleToLumpedMatrix("disp", M, "M"); } void assembleMass() { - SparseMatrix & M = this->getDOFManager().getMatrix("M"); + SparseMatrix &M = this->getDOFManager().getMatrix("M"); M.zero(); Array m_all_el(this->nb_elements, 4); Matrix m(2, 2); m(0, 0) = m(1, 1) = 2; m(0, 1) = m(1, 0) = 1; // under integrated // m(0, 0) = m(1, 1) = 3./2.; // m(0, 1) = m(1, 0) = 3./2.; // lumping the mass matrix // m(0, 0) += m(0, 1); // m(1, 1) += m(1, 0); // m(0, 1) = m(1, 0) = 0; - for (auto && data : - zip(make_view(this->mesh.getConnectivity(_segment_2), 2), - make_view(m_all_el, 2, 2))) { - const auto & conn = std::get<0>(data); - auto & m_el = std::get<1>(data); - UInt n1 = conn(0); - UInt n2 = conn(1); + for (auto &&data : zip(make_view(this->mesh.getConnectivity(_segment_2), 2), + make_view(m_all_el, 2, 2))) { + const auto &conn = std::get<0>(data); + auto &m_el = std::get<1>(data); + Int n1 = conn(0); + Int n2 = conn(1); Real p1 = this->mesh.getNodes()(n1, _x); Real p2 = this->mesh.getNodes()(n2, _x); Real L = std::abs(p2 - p1); m_el = m; m_el *= rho * A * L / 6.; } this->getDOFManager().assembleElementalMatricesToMatrix( "M", "disp", m_all_el, _segment_2); is_mass_assembled = true; } MatrixType getMatrixType(const ID &) const override { return _symmetric; } - void assembleMatrix(const ID & matrix_id) override { + void assembleMatrix(const ID &matrix_id) override { if (matrix_id == "K") { if (not is_stiffness_assembled) this->assembleStiffness(); } else if (matrix_id == "M") { if (not is_mass_assembled) this->assembleMass(); } else if (matrix_id == "C") { // pass, no damping matrix } else { AKANTU_EXCEPTION("This solver does not know what to do with a matrix " << matrix_id); } } - void assembleLumpedMatrix(const ID & matrix_id) override { + void assembleLumpedMatrix(const ID &matrix_id) override { if (matrix_id == "M") { if (not is_lumped_mass_assembled) this->assembleLumpedMass(); } else { AKANTU_EXCEPTION("This solver does not know what to do with a matrix " << matrix_id); } } void assembleStiffness() { - SparseMatrix & K = this->getDOFManager().getMatrix("K"); + SparseMatrix &K = this->getDOFManager().getMatrix("K"); K.zero(); Matrix k(2, 2); k(0, 0) = k(1, 1) = 1; k(0, 1) = k(1, 0) = -1; Array k_all_el(this->nb_elements, 4); auto k_it = k_all_el.begin(2, 2); auto cit = this->mesh.getConnectivity(_segment_2).begin(2); auto cend = this->mesh.getConnectivity(_segment_2).end(2); for (; cit != cend; ++cit, ++k_it) { - const auto & conn = *cit; - UInt n1 = conn(0); - UInt n2 = conn(1); + const auto &conn = *cit; + auto n1 = conn(0); + auto n2 = conn(1); - Real p1 = this->mesh.getNodes()(n1, _x); - Real p2 = this->mesh.getNodes()(n2, _x); + auto p1 = this->mesh.getNodes()(n1, _x); + auto p2 = this->mesh.getNodes()(n2, _x); - Real L = std::abs(p2 - p1); + auto L = std::abs(p2 - p1); - auto & k_el = *k_it; + auto &k_el = *k_it; k_el = k; k_el *= E * A / L; } this->getDOFManager().assembleElementalMatricesToMatrix( "K", "disp", k_all_el, _segment_2); is_stiffness_assembled = true; } void assembleResidual() override { this->getDOFManager().assembleToResidual("disp", forces); internal_forces.zero(); this->assembleResidualInternal(_not_ghost); this->synchronize(SynchronizationTag::_user_1); this->getDOFManager().assembleToResidual("disp", internal_forces, -1.); } void assembleResidualInternal(GhostType ghost_type) { Array forces_internal_el( this->mesh.getNbElement(_segment_2, ghost_type), 2); - const auto & connectivity = + const auto &connectivity = this->mesh.getConnectivity(_segment_2, ghost_type); - for (auto && data : - zip(make_view<2>(connectivity), strains, stresses, initial_lengths, - make_view<2>(forces_internal_el))) { - const auto & conn = std::get<0>(data); + for (auto &&data : zip(make_view<2>(connectivity), strains, stresses, + initial_lengths, make_view<2>(forces_internal_el))) { + const auto &conn = std::get<0>(data); auto n1 = conn(0); auto n2 = conn(1); auto u1 = this->displacement(n1, _x); auto u2 = this->displacement(n2, _x); - auto & strain = std::get<1>(data); - auto & stress = std::get<2>(data); - const auto & L = std::get<3>(data); + auto &strain = std::get<1>(data); + auto &stress = std::get<2>(data); + const auto &L = std::get<3>(data); strain = (u2 - u1) / L; stress = E * strain; auto f_n = A * stress; - auto & f = std::get<4>(data); + auto &f = std::get<4>(data); f(0) = -f_n; f(1) = f_n; } this->getDOFManager().assembleElementalArrayLocalArray( forces_internal_el, internal_forces, _segment_2, ghost_type); } Real getPotentialEnergy() { Real res = 0; if (not lumped) { res = this->mulVectMatVect(this->displacement, "K", this->displacement); } else { - for (auto && data : zip(strains, stresses, initial_lengths)) { - auto & strain = std::get<0>(data); - auto & stress = std::get<1>(data); - const auto & L = std::get<2>(data); + for (auto &&data : zip(strains, stresses, initial_lengths)) { + auto &strain = std::get<0>(data); + auto &stress = std::get<1>(data); + const auto &L = std::get<2>(data); res += strain * stress * A * L; } mesh.getCommunicator().allReduce(res, SynchronizerOperation::_sum); } return res / 2.; } Real getKineticEnergy() { Real res = 0; if (not lumped) { res = this->mulVectMatVect(this->velocity, "M", this->velocity); } else { - Array & m = dynamic_cast( + Array &m = dynamic_cast( this->getDOFManager().getLumpedMatrix("M")); auto it = velocity.begin(); auto end = velocity.end(); auto m_it = m.begin(); for (Int node = 0; it != end; ++it, ++m_it, ++node) { if (mesh.isLocalOrMasterNode(node)) res += *m_it * *it * *it; } mesh.getCommunicator().allReduce(res, SynchronizerOperation::_sum); } return res / 2.; } Real getExternalWorkIncrement() { Real res = 0; auto it = velocity.begin(); auto end = velocity.end(); auto if_it = internal_forces.begin(); auto ef_it = forces.begin(); auto b_it = blocked.begin(); for (Int node = 0; it != end; ++it, ++if_it, ++ef_it, ++b_it, ++node) { if (mesh.isLocalOrMasterNode(node)) res += (*b_it ? -*if_it : *ef_it) * *it; } mesh.getCommunicator().allReduce(res, SynchronizerOperation::_sum); return res * this->getTimeStep(); } - Real mulVectMatVect(const Array & x, const ID & A_id, - const Array & y) { + Real mulVectMatVect(const Array &x, const ID &A_id, + const Array &y) { Array Ay(nb_dofs); this->getDOFManager().assembleMatMulVectToArray("disp", A_id, y, Ay); Real res = 0.; - for (auto && data : zip(arange(nb_dofs), make_view(Ay), make_view(x))) { + for (auto &&data : zip(arange(nb_dofs), make_view(Ay), make_view(x))) { res += std::get<2>(data) * std::get<1>(data) * mesh.isLocalOrMasterNode(std::get<0>(data)); } mesh.getCommunicator().allReduce(res, SynchronizerOperation::_sum); return res; } /* ------------------------------------------------------------------------ */ - Int getNbData(const Array & elements, + Int getNbData(const Array &elements, const SynchronizationTag &) const override { return elements.size() * sizeof(Real); } - void packData(CommunicationBuffer & buffer, const Array & elements, - const SynchronizationTag & tag) const override { + void packData(CommunicationBuffer &buffer, const Array &elements, + const SynchronizationTag &tag) const override { if (tag == SynchronizationTag::_user_1) { - for (const auto & el : elements) { + for (const auto &el : elements) { buffer << this->stresses(el.element); } } } - void unpackData(CommunicationBuffer & buffer, const Array & elements, - const SynchronizationTag & tag) override { + void unpackData(CommunicationBuffer &buffer, const Array &elements, + const SynchronizationTag &tag) override { if (tag == SynchronizationTag::_user_1) { auto cit = this->mesh.getConnectivity(_segment_2, _ghost).begin(2); - for (const auto & el : elements) { + for (const auto &el : elements) { Real stress; buffer >> stress; Real f = A * stress; - auto && conn = cit[el.element]; + auto &&conn = cit[el.element]; this->internal_forces(conn(0), _x) += -f; this->internal_forces(conn(1), _x) += f; } } } - const Mesh & getMesh() const { return mesh; } + const Mesh &getMesh() const { return mesh; } Int getSpatialDimension() const { return 1; } - auto & getBlockedDOFs() { return blocked; } + auto &getBlockedDOFs() { return blocked; } private: - UInt nb_dofs; - UInt nb_elements; + Int nb_dofs; + Int nb_elements; bool lumped; bool is_stiffness_assembled{false}; bool is_mass_assembled{false}; bool is_lumped_mass_assembled{false}; public: Real E, A, rho; - Mesh & mesh; + Mesh &mesh; Array displacement; Array velocity; Array acceleration; Array blocked; Array forces; Array internal_forces; Array stresses; Array strains; Array initial_lengths; }; #endif /* AKANTU_TEST_MODEL_SOLVER_MY_MODEL_HH_ */ } // namespace akantu diff --git a/test/test_model/test_common/test_non_local_toolbox/my_model.hh b/test/test_model/test_common/test_non_local_toolbox/my_model.hh index 043a66a69..ac9ad5deb 100644 --- a/test/test_model/test_common/test_non_local_toolbox/my_model.hh +++ b/test/test_model/test_common/test_non_local_toolbox/my_model.hh @@ -1,129 +1,127 @@ /** * @file my_model.hh * * @author Nicolas Richart * * @date creation: Mon Sep 11 2017 * @date last modification: Fri Jun 26 2020 * * @brief A dummy model for tests purposes * * * @section LICENSE * * Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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 "integrator_gauss.hh" #include "model.hh" #include "non_local_manager.hh" #include "non_local_manager_callback.hh" #include "non_local_neighborhood_base.hh" #include "shape_lagrange.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; class MyModel : public Model, public NonLocalManagerCallback { using MyFEEngineType = FEEngineTemplate; public: - MyModel(Mesh & mesh, Int spatial_dimension) + MyModel(Mesh &mesh, Int spatial_dimension) : Model(mesh, ModelType::_model, spatial_dimension), manager(*this, *this) { registerFEEngineObject("FEEngine", mesh, spatial_dimension); manager.registerNeighborhood("test_region", "test_region"); getFEEngine().initShapeFunctions(); manager.initialize(); } void initModel() override {} MatrixType getMatrixType(const ID &) const override { return _mt_not_defined; } std::tuple getDefaultSolverID(const AnalysisMethod & /*method*/) override { return std::make_tuple("test", TimeStepSolverType::_static); } void assembleMatrix(const ID &) override {} void assembleLumpedMatrix(const ID &) override {} void assembleResidual() override {} void onNodesAdded(const Array &, const NewNodesEvent &) override {} void onNodesRemoved(const Array &, const Array &, const RemovedNodesEvent &) override {} void onElementsAdded(const Array &, const NewElementsEvent &) override {} void onElementsRemoved(const Array &, const ElementTypeMapArray &, const RemovedElementsEvent &) override {} void onElementsChanged(const Array &, const Array &, const ElementTypeMapArray &, const ChangedElementsEvent &) override {} void insertIntegrationPointsInNeighborhoods(GhostType ghost_type) override { ElementTypeMapArray quadrature_points_coordinates( "quadrature_points_coordinates_tmp_nl", this->id); quadrature_points_coordinates.initialize(this->getFEEngine(), _nb_component = spatial_dimension, _ghost_type = ghost_type); IntegrationPoint q; q.ghost_type = ghost_type; q.global_num = 0; - auto & neighborhood = manager.getNeighborhood("test_region"); + auto &neighborhood = manager.getNeighborhood("test_region"); - for (const auto & type : quadrature_points_coordinates.elementTypes( + for (const auto &type : quadrature_points_coordinates.elementTypes( spatial_dimension, ghost_type)) { q.type = type; - auto nb_quads_per_elem = this->getFEEngine().getNbIntegrationPoints(type); - auto & quads = quadrature_points_coordinates(type, ghost_type); + auto &quads = quadrature_points_coordinates(type, ghost_type); this->getFEEngine().computeIntegrationPointsCoordinates(quads, type, ghost_type); auto quad_it = quads.begin(quads.getNbComponent()); auto quad_end = quads.end(quads.getNbComponent()); q.num_point = 0; for (; quad_it != quad_end; ++quad_it) { neighborhood.insertIntegrationPoint(q, *quad_it); ++q.num_point; ++q.global_num; } } } - void computeNonLocalStresses(GhostType) - override {} + void computeNonLocalStresses(GhostType) override {} - void updateLocalInternal(ElementTypeMapReal &, GhostType, ElementKind) - override {} + void updateLocalInternal(ElementTypeMapReal &, GhostType, + ElementKind) override {} - void updateNonLocalInternal(ElementTypeMapReal &, GhostType, ElementKind) - override {} + void updateNonLocalInternal(ElementTypeMapReal &, GhostType, + ElementKind) override {} - const auto & getNonLocalManager() const { return manager; } + const auto &getNonLocalManager() const { return manager; } private: NonLocalManager manager; }; diff --git a/test/test_model/test_phase_field_model/test_phase_solid_explicit.cc b/test/test_model/test_phase_field_model/test_phase_solid_explicit.cc index d86ad1b82..63b5c0928 100644 --- a/test/test_model/test_phase_field_model/test_phase_solid_explicit.cc +++ b/test/test_model/test_phase_field_model/test_phase_solid_explicit.cc @@ -1,154 +1,154 @@ /** * @file test_phase_solid_explicit.cc * * @author Mohit Pundir * * @date creation: Sun Feb 28 2021 * @date last modification: Fri Jun 25 2021 * * @brief test of the class PhaseFieldModel on the 2d square * * * @section LICENSE * * Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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 #include /* -------------------------------------------------------------------------- */ using namespace akantu; const Int spatial_dimension = 2; /* -------------------------------------------------------------------------- */ void applyDisplacement(SolidMechanicsModel &, Real &); /* -------------------------------------------------------------------------- */ -int main(int argc, char * argv[]) { +int main(int argc, char *argv[]) { std::ofstream os("data-explicit.csv"); os << "#strain stress damage analytical_sigma analytical_damage error_stress " "error_damage" << std::endl; initialize("material_coupling.dat", argc, argv); Mesh mesh(spatial_dimension); mesh.read("test_one_element.msh"); CouplerSolidPhaseField coupler(mesh); - auto & model = coupler.getSolidMechanicsModel(); - auto & phase = coupler.getPhaseFieldModel(); + auto &model = coupler.getSolidMechanicsModel(); + auto &phase = coupler.getPhaseFieldModel(); model.initFull(_analysis_method = _explicit_lumped_mass); Real time_factor = 0.8; Real stable_time_step = model.getStableTimeStep() * time_factor; model.setTimeStep(stable_time_step); - auto && selector = std::make_shared>( + auto &&selector = std::make_shared>( "physical_names", phase); phase.setPhaseFieldSelector(selector); phase.initFull(_analysis_method = _static); model.setBaseName("phase_solid"); model.addDumpField("stress"); model.addDumpField("grad_u"); model.addDumpFieldVector("displacement"); model.addDumpField("damage"); model.dump(); - UInt nbSteps = 1000; + Int nbSteps = 1000; Real increment = 1e-4; - auto & stress = model.getMaterial(0).getArray("stress", _quadrangle_4); - auto & damage = model.getMaterial(0).getArray("damage", _quadrangle_4); + auto &stress = model.getMaterial(0).getArray("stress", _quadrangle_4); + auto &damage = model.getMaterial(0).getArray("damage", _quadrangle_4); Real analytical_damage{0.}; Real analytical_sigma{0.}; - auto & phasefield = phase.getPhaseField(0); + auto &phasefield = phase.getPhaseField(0); const Real E = phasefield.getParam("E"); const Real nu = phasefield.getParam("nu"); Real c22 = E * (1 - nu) / ((1 + nu) * (1 - 2 * nu)); const Real gc = phasefield.getParam("gc"); const Real l0 = phasefield.getParam("l0"); Real error_stress{0.}; Real error_damage{0.}; for (Int s = 0; s < nbSteps; ++s) { Real axial_strain = increment * s; applyDisplacement(model, axial_strain); coupler.solve("explicit_lumped", "static"); analytical_damage = axial_strain * axial_strain * c22 / (gc / l0 + axial_strain * axial_strain * c22); analytical_sigma = c22 * axial_strain * (1 - analytical_damage) * (1 - analytical_damage); error_stress = std::abs(analytical_sigma - stress(0, 3)) / analytical_sigma; error_damage = std::abs(analytical_damage - damage(0)) / analytical_damage; if (error_damage > 1e-8 and error_stress > 1e-8) { return EXIT_FAILURE; } os << axial_strain << " " << stress(0, 3) << " " << damage(0) << " " << analytical_sigma << " " << analytical_damage << " " << error_stress << " " << error_damage << std::endl; model.dump(); } os.close(); finalize(); return EXIT_SUCCESS; } /* -------------------------------------------------------------------------- */ -void applyDisplacement(SolidMechanicsModel & model, Real & increment) { - auto & displacement = model.getDisplacement(); +void applyDisplacement(SolidMechanicsModel &model, Real &increment) { + auto &displacement = model.getDisplacement(); - auto & positions = model.getMesh().getNodes(); - auto & blocked_dofs = model.getBlockedDOFs(); + auto &positions = model.getMesh().getNodes(); + auto &blocked_dofs = model.getBlockedDOFs(); for (Int n = 0; n < model.getMesh().getNbNodes(); ++n) { if (positions(n, 1) == -0.5) { displacement(n, 0) = 0; displacement(n, 1) = 0; blocked_dofs(n, 0) = true; blocked_dofs(n, 1) = true; } else { displacement(n, 0) = 0; displacement(n, 1) = increment; blocked_dofs(n, 0) = true; blocked_dofs(n, 1) = true; } } } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_buildfragments/test_cohesive_buildfragments.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_buildfragments/test_cohesive_buildfragments.cc index 80f0b1915..712433926 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_buildfragments/test_cohesive_buildfragments.cc +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_buildfragments/test_cohesive_buildfragments.cc @@ -1,183 +1,183 @@ /** * @file test_cohesive_buildfragments.cc * * @author Marco Vocialta * * @date creation: Sun Oct 19 2014 * @date last modification: Thu May 09 2019 * * @brief Test for cohesive elements * * * @section LICENSE * * Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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 "fragment_manager.hh" #include "material_cohesive.hh" #include "solid_mechanics_model_cohesive.hh" /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ using namespace akantu; -int main(int argc, char * argv[]) { +int main(int argc, char *argv[]) { initialize("material.dat", argc, argv); Math::setTolerance(1e-14); const Int spatial_dimension = 2; const Int max_steps = 200; Real strain_rate = 1.e5; ElementType type = _quadrangle_4; Real L = 0.03; Real theoretical_mass = L * L / 20. * 2500; ElementType type_facet = Mesh::getFacetType(type); ElementType type_cohesive = FEEngine::getCohesiveElementType(type_facet); Mesh mesh(spatial_dimension); mesh.read("mesh.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; Real disp_increment = strain_rate * L / 2. * time_step; model.assembleMassLumped(); - Array & velocity = model.getVelocity(); - const Array & position = mesh.getNodes(); + Array &velocity = model.getVelocity(); + const Array &position = mesh.getNodes(); Int nb_nodes = mesh.getNbNodes(); /// initial conditions for (Int n = 0; n < nb_nodes; ++n) velocity(n, 0) = strain_rate * position(n, 0); /// boundary conditions model.applyBC(BC::Dirichlet::FixedValue(0, _x), "Left_side"); model.applyBC(BC::Dirichlet::FixedValue(0, _x), "Right_side"); - UInt cohesive_index = 1; + Int cohesive_index = 1; - UInt nb_quad_per_facet = + Int nb_quad_per_facet = model.getFEEngine("FacetsFEEngine").getNbIntegrationPoints(type_facet); - MaterialCohesive & mat_cohesive = + MaterialCohesive &mat_cohesive = dynamic_cast(model.getMaterial(cohesive_index)); - const Array & damage = mat_cohesive.getDamage(type_cohesive); + const Array &damage = mat_cohesive.getDamage(type_cohesive); FragmentManager fragment_manager(model, false); - const Array & fragment_mass = fragment_manager.getMass(); + const Array &fragment_mass = fragment_manager.getMass(); /// Main loop for (Int s = 1; s <= max_steps; ++s) { model.checkCohesiveStress(); model.solveStep(); /// apply boundary conditions model.applyBC(BC::Dirichlet::IncrementValue(-disp_increment, _x), "Left_side"); model.applyBC(BC::Dirichlet::IncrementValue(disp_increment, _x), "Right_side"); if (s % 1 == 0) { // model.dump(); std::cout << "passing step " << s << "/" << max_steps << std::endl; fragment_manager.computeAllData(); /// check number of fragments - auto nb_fragment_num = fragment_manager.getNbFragment(); + Int nb_fragment_num = fragment_manager.getNbFragment(); auto nb_cohesive_elements = mesh.getNbElement(type_cohesive); Int nb_fragment = 1; for (Int el = 0; el < nb_cohesive_elements; ++el) { - UInt q = 0; + Int q = 0; while (q < nb_quad_per_facet && Math::are_float_equal(damage(el * nb_quad_per_facet + q), 1)) ++q; if (q == nb_quad_per_facet) { ++nb_fragment; } } if (nb_fragment != nb_fragment_num) { std::cout << "The number of fragments is wrong!" << std::endl; return EXIT_FAILURE; } /// check mass computation Real total_mass = 0.; for (Int frag = 0; frag < nb_fragment_num; ++frag) { total_mass += fragment_mass(frag); } if (!Math::are_float_equal(theoretical_mass, total_mass)) { std::cout << "The fragments' mass is wrong!" << std::endl; return EXIT_FAILURE; } } } model.dump(); /// check velocities - auto nb_fragment = fragment_manager.getNbFragment(); - const Array & fragment_velocity = fragment_manager.getVelocity(); - const Array & fragment_center = fragment_manager.getCenterOfMass(); + Int nb_fragment = fragment_manager.getNbFragment(); + const Array &fragment_velocity = fragment_manager.getVelocity(); + const Array &fragment_center = fragment_manager.getCenterOfMass(); Real fragment_length = L / nb_fragment; Real initial_position = -L / 2. + fragment_length / 2.; for (Int frag = 0; frag < nb_fragment; ++frag) { Real theoretical_center = initial_position + fragment_length * frag; if (!Math::are_float_equal(fragment_center(frag, 0), theoretical_center)) { std::cout << "The fragments' center is wrong!" << std::endl; return EXIT_FAILURE; } Real initial_vel = fragment_center(frag, 0) * strain_rate; Math::setTolerance(100); if (!Math::are_float_equal(fragment_velocity(frag), initial_vel)) { std::cout << "The fragments' velocity is wrong!" << std::endl; return EXIT_FAILURE; } } finalize(); std::cout << "OK: test_cohesive_buildfragments was passed!" << std::endl; return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_materials/test_material_cohesive_fixture.hh b/test/test_model/test_solid_mechanics_model/test_cohesive/test_materials/test_material_cohesive_fixture.hh index cce18d83a..d77889743 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_materials/test_material_cohesive_fixture.hh +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_materials/test_material_cohesive_fixture.hh @@ -1,314 +1,314 @@ /** * @file test_material_cohesive_fixture.hh * * @author Nicolas Richart * * @date creation: Wed Feb 21 2018 * @date last modification: Sun Dec 30 2018 * * @brief Test the traction separations laws for cohesive elements * * * @section LICENSE * * Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * 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 "test_gtest_utils.hh" /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ using namespace akantu; //#define debug_ /* -------------------------------------------------------------------------- */ template