LCOV - code coverage report
Current view: top level - src/physics - fem_physics.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 29 32 90.6 %
Date: 2025-08-19 19:27:09 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // The libMesh Finite Element Library.
       2             : // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
       3             : 
       4             : // This library is free software; you can redistribute it and/or
       5             : // modify it under the terms of the GNU Lesser General Public
       6             : // License as published by the Free Software Foundation; either
       7             : // version 2.1 of the License, or (at your option) any later version.
       8             : 
       9             : // This library is distributed in the hope that it will be useful,
      10             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             : // Lesser General Public License for more details.
      13             : 
      14             : // You should have received a copy of the GNU Lesser General Public
      15             : // License along with this library; if not, write to the Free Software
      16             : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      17             : 
      18             : 
      19             : 
      20             : #include "libmesh/dof_map.h"
      21             : #include "libmesh/elem.h"
      22             : #include "libmesh/equation_systems.h"
      23             : #include "libmesh/fe_base.h"
      24             : #include "libmesh/fem_context.h"
      25             : #include "libmesh/fem_system.h"
      26             : #include "libmesh/libmesh_logging.h"
      27             : #include "libmesh/mesh_base.h"
      28             : #include "libmesh/numeric_vector.h"
      29             : #include "libmesh/quadrature.h"
      30             : #include "libmesh/sparse_matrix.h"
      31             : #include "libmesh/time_solver.h"
      32             : #include "libmesh/unsteady_solver.h" // For eulerian_residual
      33             : 
      34             : 
      35             : namespace libMesh
      36             : {
      37             : 
      38    20563472 : bool FEMPhysics::eulerian_residual (bool request_jacobian,
      39             :                                     DiffContext & /*c*/)
      40             : {
      41             :   // Only calculate a mesh movement residual if it's necessary
      42    20563472 :   if (!_mesh_sys)
      43     1845168 :     return request_jacobian;
      44             : 
      45           0 :   libmesh_not_implemented();
      46             : 
      47             : #if 0
      48             :   FEMContext & context = cast_ref<FEMContext &>(c);
      49             : 
      50             :   // This function only supports fully coupled mesh motion for now
      51             :   libmesh_assert_equal_to (_mesh_sys, this);
      52             : 
      53             :   unsigned int n_qpoints = (context.get_element_qrule())->n_points();
      54             : 
      55             :   const unsigned int n_x_dofs = (_mesh_x_var == libMesh::invalid_uint) ?
      56             :     0 : context.dof_indices_var[_mesh_x_var].size();
      57             :   const unsigned int n_y_dofs = (_mesh_y_var == libMesh::invalid_uint) ?
      58             :     0 : context.dof_indices_var[_mesh_y_var].size();
      59             :   const unsigned int n_z_dofs = (_mesh_z_var == libMesh::invalid_uint) ?
      60             :     0 : context.dof_indices_var[_mesh_z_var].size();
      61             : 
      62             :   const unsigned int mesh_xyz_var = n_x_dofs ? _mesh_x_var :
      63             :     (n_y_dofs ? _mesh_y_var :
      64             :      (n_z_dofs ? _mesh_z_var :
      65             :       libMesh::invalid_uint));
      66             : 
      67             :   // If we're our own _mesh_sys, we'd better be in charge of
      68             :   // at least one coordinate, and we'd better have the same
      69             :   // FE type for all coordinates we are in charge of
      70             :   libmesh_assert_not_equal_to (mesh_xyz_var, libMesh::invalid_uint);
      71             :   libmesh_assert(!n_x_dofs || context.element_fe_var[_mesh_x_var] ==
      72             :                  context.element_fe_var[mesh_xyz_var]);
      73             :   libmesh_assert(!n_y_dofs || context.element_fe_var[_mesh_y_var] ==
      74             :                  context.element_fe_var[mesh_xyz_var]);
      75             :   libmesh_assert(!n_z_dofs || context.element_fe_var[_mesh_z_var] ==
      76             :                  context.element_fe_var[mesh_xyz_var]);
      77             : 
      78             :   const std::vector<std::vector<Real>>     & psi =
      79             :     context.element_fe_var[mesh_xyz_var]->get_phi();
      80             : 
      81             :   for (auto var : make_range(context.n_vars()))
      82             :     {
      83             :       // Mesh motion only affects time-evolving variables
      84             :       if (this->is_time_evolving(var))
      85             :         continue;
      86             : 
      87             :       // The mesh coordinate variables themselves are Lagrangian,
      88             :       // not Eulerian, and no convective term is desired.
      89             :       if (/*_mesh_sys == this && */
      90             :           (var == _mesh_x_var ||
      91             :            var == _mesh_y_var ||
      92             :            var == _mesh_z_var))
      93             :         continue;
      94             : 
      95             :       // Some of this code currently relies on the assumption that
      96             :       // we can pull mesh coordinate data from our own system
      97             :       if (_mesh_sys != this)
      98             :         libmesh_not_implemented();
      99             : 
     100             :       // This residual should only be called by unsteady solvers:
     101             :       // if the mesh is steady, there's no mesh convection term!
     102             :       UnsteadySolver * unsteady;
     103             :       if (this->time_solver->is_steady())
     104             :         return request_jacobian;
     105             :       else
     106             :         unsteady = cast_ptr<UnsteadySolver*>(this->time_solver.get());
     107             : 
     108             :       const std::vector<Real> & JxW =
     109             :         context.element_fe_var[var]->get_JxW();
     110             : 
     111             :       const std::vector<std::vector<Real>> & phi =
     112             :         context.element_fe_var[var]->get_phi();
     113             : 
     114             :       const std::vector<std::vector<RealGradient>> & dphi =
     115             :         context.element_fe_var[var]->get_dphi();
     116             : 
     117             :       const unsigned int n_u_dofs = context.dof_indices_var[var].size();
     118             : 
     119             :       DenseSubVector<Number> & Fu = *context.elem_subresiduals[var];
     120             :       DenseSubMatrix<Number> & Kuu = *context.elem_subjacobians[var][var];
     121             : 
     122             :       DenseSubMatrix<Number> * Kux = n_x_dofs ?
     123             :         context.elem_subjacobians[var][_mesh_x_var] : nullptr;
     124             :       DenseSubMatrix<Number> * Kuy = n_y_dofs ?
     125             :         context.elem_subjacobians[var][_mesh_y_var] : nullptr;
     126             :       DenseSubMatrix<Number> * Kuz = n_z_dofs ?
     127             :         context.elem_subjacobians[var][_mesh_z_var] : nullptr;
     128             : 
     129             :       std::vector<Real> delta_x(n_x_dofs, 0.);
     130             :       std::vector<Real> delta_y(n_y_dofs, 0.);
     131             :       std::vector<Real> delta_z(n_z_dofs, 0.);
     132             : 
     133             :       for (unsigned int i = 0; i != n_x_dofs; ++i)
     134             :         {
     135             :           unsigned int j = context.dof_indices_var[_mesh_x_var][i];
     136             :           delta_x[i] = libmesh_real(this->current_solution(j)) -
     137             :             libmesh_real(unsteady->old_nonlinear_solution(j));
     138             :         }
     139             : 
     140             :       for (unsigned int i = 0; i != n_y_dofs; ++i)
     141             :         {
     142             :           unsigned int j = context.dof_indices_var[_mesh_y_var][i];
     143             :           delta_y[i] = libmesh_real(this->current_solution(j)) -
     144             :             libmesh_real(unsteady->old_nonlinear_solution(j));
     145             :         }
     146             : 
     147             :       for (unsigned int i = 0; i != n_z_dofs; ++i)
     148             :         {
     149             :           unsigned int j = context.dof_indices_var[_mesh_z_var][i];
     150             :           delta_z[i] = libmesh_real(this->current_solution(j)) -
     151             :             libmesh_real(unsteady->old_nonlinear_solution(j));
     152             :         }
     153             : 
     154             :       for (unsigned int qp = 0; qp != n_qpoints; ++qp)
     155             :         {
     156             :           Gradient grad_u = context.interior_gradient(var, qp);
     157             :           RealGradient convection(0.);
     158             : 
     159             :           for (unsigned int i = 0; i != n_x_dofs; ++i)
     160             :             convection(0) += delta_x[i] * psi[i][qp];
     161             :           for (unsigned int i = 0; i != n_y_dofs; ++i)
     162             :             convection(1) += delta_y[i] * psi[i][qp];
     163             :           for (unsigned int i = 0; i != n_z_dofs; ++i)
     164             :             convection(2) += delta_z[i] * psi[i][qp];
     165             : 
     166             :           for (unsigned int i = 0; i != n_u_dofs; ++i)
     167             :             {
     168             :               Number JxWxPhiI = JxW[qp] * phi[i][qp];
     169             :               Fu(i) += (convection * grad_u) * JxWxPhiI;
     170             :               if (request_jacobian)
     171             :                 {
     172             :                   Number JxWxPhiI = JxW[qp] * phi[i][qp];
     173             :                   for (unsigned int j = 0; j != n_u_dofs; ++j)
     174             :                     Kuu(i,j) += JxWxPhiI * (convection * dphi[j][qp]);
     175             : 
     176             :                   Number JxWxPhiIoverDT = JxWxPhiI/this->deltat;
     177             : 
     178             :                   Number JxWxPhiIxDUDXoverDT = JxWxPhiIoverDT * grad_u(0);
     179             :                   for (unsigned int j = 0; j != n_x_dofs; ++j)
     180             :                     (*Kux)(i,j) += JxWxPhiIxDUDXoverDT * psi[j][qp];
     181             : 
     182             :                   Number JxWxPhiIxDUDYoverDT = JxWxPhiIoverDT * grad_u(1);
     183             :                   for (unsigned int j = 0; j != n_y_dofs; ++j)
     184             :                     (*Kuy)(i,j) += JxWxPhiIxDUDYoverDT * psi[j][qp];
     185             : 
     186             :                   Number JxWxPhiIxDUDZoverDT = JxWxPhiIoverDT * grad_u(2);
     187             :                   for (unsigned int j = 0; j != n_z_dofs; ++j)
     188             :                     (*Kuz)(i,j) += JxWxPhiIxDUDZoverDT * psi[j][qp];
     189             :                 }
     190             :             }
     191             :         }
     192             :     }
     193             : #endif // 0
     194             : 
     195             :   return request_jacobian;
     196             : }
     197             : 
     198             : 
     199             : 
     200    16452128 : bool FEMPhysics::mass_residual (bool request_jacobian,
     201             :                                 DiffContext & c)
     202             : {
     203     1495648 :   FEMContext & context = cast_ref<FEMContext &>(c);
     204             : 
     205     1495648 :   unsigned int n_qpoints = context.get_element_qrule().n_points();
     206             : 
     207    32904256 :   for (auto var : make_range(context.n_vars()))
     208             :     {
     209    17947776 :       if (!this->is_time_evolving(var))
     210           0 :         continue;
     211             : 
     212    14956480 :       FEBase * elem_fe = nullptr;
     213    14956480 :       context.get_element_fe( var, elem_fe );
     214             : 
     215    16452128 :       const std::vector<Real> & JxW = elem_fe->get_JxW();
     216             : 
     217     1495648 :       const std::vector<std::vector<Real>> & phi = elem_fe->get_phi();
     218             : 
     219             :       const unsigned int n_dofs = cast_int<unsigned int>
     220     2991296 :         (context.get_dof_indices(var).size());
     221             : 
     222     1495648 :       DenseSubVector<Number> & Fu = context.get_elem_residual(var);
     223     1495648 :       DenseSubMatrix<Number> & Kuu = context.get_elem_jacobian( var, var );
     224             : 
     225    89504800 :       for (unsigned int qp = 0; qp != n_qpoints; ++qp)
     226             :         {
     227           0 :           Number uprime;
     228    73052672 :           context.interior_rate(var, qp, uprime);
     229    79693824 :           const Number JxWxU = JxW[qp] * uprime;
     230   365263360 :           for (unsigned int i = 0; i != n_dofs; ++i)
     231             :             {
     232   345339904 :               Fu(i) -= JxWxU * phi[i][qp];
     233   292210688 :               if (request_jacobian && context.elem_solution_rate_derivative)
     234             :                 {
     235    87408640 :                   const Number JxWxPhiIxDeriv = JxW[qp] * phi[i][qp] *
     236    87408640 :                     context.elem_solution_rate_derivative;
     237    87408640 :                   Kuu(i,i) -= JxWxPhiIxDeriv * phi[i][qp];
     238   218521600 :                   for (unsigned int j = i+1; j < n_dofs; ++j)
     239             :                     {
     240   154951680 :                       const Number Kij = JxWxPhiIxDeriv * phi[j][qp];
     241   131112960 :                       Kuu(i,j) -= Kij;
     242   131112960 :                       Kuu(j,i) -= Kij;
     243             :                     }
     244             :                 }
     245             :             }
     246             :         }
     247             :     }
     248             : 
     249    16452128 :   return request_jacobian;
     250             : }
     251             : 
     252             : } // namespace libMesh

Generated by: LCOV version 1.14