Line data Source code
1 : //* This file is part of the MOOSE framework
2 : //* https://mooseframework.inl.gov
3 : //*
4 : //* All rights reserved, see COPYRIGHT for full restrictions
5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 : //*
7 : //* Licensed under LGPL 2.1, please see LICENSE for details
8 : //* https://www.gnu.org/licenses/lgpl-2.1.html
9 :
10 : #include "ComputeMortarFunctor.h"
11 : #include "FEProblemBase.h"
12 : #include "SubProblem.h"
13 : #include "Assembly.h"
14 : #include "ADMortarConstraint.h"
15 : #include "AutomaticMortarGeneration.h"
16 : #include "MooseMesh.h"
17 : #include "Assembly.h"
18 : #include "MortarUtils.h"
19 : #include "MaterialBase.h"
20 :
21 : #include "libmesh/fe_base.h"
22 : #include "libmesh/quadrature.h"
23 : #include "libmesh/elem.h"
24 : #include "libmesh/point.h"
25 : #include "libmesh/mesh_base.h"
26 :
27 : // C++
28 : #include <cstring> // for "Jacobian" exception test
29 :
30 981 : ComputeMortarFunctor::ComputeMortarFunctor(
31 : const std::vector<std::shared_ptr<MortarConstraintBase>> & mortar_constraints,
32 : const AutomaticMortarGeneration & amg,
33 : SubProblem & subproblem,
34 : FEProblemBase & fe_problem,
35 : bool displaced,
36 981 : Assembly & assembly)
37 981 : : _amg(amg),
38 981 : _subproblem(subproblem),
39 981 : _fe_problem(fe_problem),
40 981 : _displaced(displaced),
41 981 : _assembly(assembly)
42 : {
43 : // Construct the mortar constraints we will later loop over
44 2311 : for (auto mc : mortar_constraints)
45 1330 : _mortar_constraints.push_back(mc.get());
46 :
47 981 : Moose::Mortar::setupMortarMaterials(_mortar_constraints,
48 : _fe_problem,
49 : _amg,
50 : 0,
51 981 : _secondary_ip_sub_to_mats,
52 981 : _primary_ip_sub_to_mats,
53 981 : _secondary_boundary_mats);
54 981 : }
55 :
56 : void
57 192 : ComputeMortarFunctor::setupMortarMaterials()
58 : {
59 192 : Moose::Mortar::setupMortarMaterials(_mortar_constraints,
60 : _fe_problem,
61 : _amg,
62 : /*thread id*/ 0,
63 192 : _secondary_ip_sub_to_mats,
64 192 : _primary_ip_sub_to_mats,
65 192 : _secondary_boundary_mats);
66 192 : }
67 :
68 : void
69 13819 : ComputeMortarFunctor::operator()(const Moose::ComputeType compute_type,
70 : const std::set<TagID> & vector_tag_ids,
71 : const std::set<TagID> & /*matrix_tag_ids*/)
72 : {
73 : libmesh_parallel_only(_fe_problem.comm());
74 :
75 13819 : unsigned int num_cached = 0;
76 13819 : const auto & vector_tags = _fe_problem.getVectorTags(vector_tag_ids);
77 :
78 13819 : const auto & secondary_elems_to_mortar_segments = _amg.secondariesToMortarSegments();
79 : typedef decltype(secondary_elems_to_mortar_segments.begin()) it_type;
80 :
81 13819 : std::vector<it_type> iterators;
82 13819 : for (auto it = secondary_elems_to_mortar_segments.begin();
83 102611 : it != secondary_elems_to_mortar_segments.end();
84 88792 : ++it)
85 : {
86 88792 : auto * const secondary_elem = _subproblem.mesh().getMesh().query_elem_ptr(it->first);
87 :
88 158588 : if (secondary_elem && secondary_elem->processor_id() == _subproblem.processor_id() &&
89 69796 : !it->second.empty())
90 : {
91 : // This is local and the mortar segment set isn't empty, so include
92 69796 : iterators.push_back(it);
93 : mooseAssert(secondary_elem->active(),
94 : "We loop over active elements when building the mortar segment mesh, so we golly "
95 : "well hope this is active.");
96 : }
97 : }
98 :
99 283073 : auto act_functor = [this, &num_cached, compute_type, &vector_tags]()
100 : {
101 283073 : ++num_cached;
102 :
103 283073 : switch (compute_type)
104 : {
105 191340 : case Moose::ComputeType::Residual:
106 : {
107 393972 : for (auto * const mc : _mortar_constraints)
108 : {
109 202632 : mc->setNormals();
110 202632 : mc->computeResidual();
111 : }
112 :
113 191340 : _assembly.cacheResidual(Assembly::GlobalDataKey{}, vector_tags);
114 191340 : _assembly.cacheResidualNeighbor(Assembly::GlobalDataKey{}, vector_tags);
115 191340 : _assembly.cacheResidualLower(Assembly::GlobalDataKey{}, vector_tags);
116 :
117 191340 : if (num_cached % 20 == 0)
118 6937 : _assembly.addCachedResiduals(Assembly::GlobalDataKey{}, vector_tags);
119 :
120 191340 : break;
121 : }
122 :
123 88425 : case Moose::ComputeType::Jacobian:
124 : {
125 182610 : for (auto * const mc : _mortar_constraints)
126 : {
127 94185 : mc->setNormals();
128 94185 : mc->computeJacobian();
129 : }
130 :
131 88425 : _assembly.cacheJacobianMortar(Assembly::GlobalDataKey{});
132 :
133 88425 : if (num_cached % 20 == 0)
134 3868 : _assembly.addCachedJacobian(Assembly::GlobalDataKey{});
135 88425 : break;
136 : }
137 :
138 3308 : case Moose::ComputeType::ResidualAndJacobian:
139 : {
140 6616 : for (auto * const mc : _mortar_constraints)
141 : {
142 3308 : mc->setNormals();
143 3308 : mc->computeResidualAndJacobian();
144 : }
145 :
146 3308 : _assembly.cacheResidual(Assembly::GlobalDataKey{}, vector_tags);
147 3308 : _assembly.cacheResidualNeighbor(Assembly::GlobalDataKey{}, vector_tags);
148 3308 : _assembly.cacheResidualLower(Assembly::GlobalDataKey{}, vector_tags);
149 3308 : _assembly.cacheJacobianMortar(Assembly::GlobalDataKey{});
150 :
151 3308 : if (num_cached % 20 == 0)
152 : {
153 0 : _assembly.addCachedResiduals(Assembly::GlobalDataKey{}, vector_tags);
154 0 : _assembly.addCachedJacobian(Assembly::GlobalDataKey{});
155 : }
156 3308 : break;
157 : }
158 : }
159 283073 : };
160 :
161 : PARALLEL_TRY
162 : {
163 : try
164 : {
165 13819 : Moose::Mortar::loopOverMortarSegments(iterators,
166 : _assembly,
167 : _subproblem,
168 : _fe_problem,
169 : _amg,
170 13819 : _displaced,
171 13819 : _mortar_constraints,
172 : 0,
173 13819 : _secondary_ip_sub_to_mats,
174 13819 : _primary_ip_sub_to_mats,
175 13819 : _secondary_boundary_mats,
176 : act_functor,
177 : /*reinit_mortar_user_objects=*/true);
178 : }
179 0 : catch (MooseException & e)
180 : {
181 0 : _fe_problem.setException(e.what());
182 0 : }
183 0 : catch (MetaPhysicL::LogicError & e)
184 : {
185 0 : moose::translateMetaPhysicLError(e);
186 0 : }
187 0 : catch (std::exception & e)
188 : {
189 0 : if (!strstr(e.what(), "Jacobian") && !strstr(e.what(), "singular") &&
190 0 : !strstr(e.what(), "det != 0"))
191 0 : throw;
192 :
193 0 : _fe_problem.setException(
194 0 : "We caught a libMesh degeneracy exception in ComputeMortarFunctor:\n" +
195 0 : std::string(e.what()));
196 0 : }
197 : }
198 13819 : PARALLEL_CATCH;
199 :
200 : // Call any post operations for our mortar constraints
201 30518 : for (auto * const mc : _mortar_constraints)
202 : {
203 16699 : if (_amg.incorrectEdgeDropping())
204 7270 : mc->incorrectEdgeDroppingPost(_amg.getInactiveLMNodes());
205 : else
206 9429 : mc->post();
207 :
208 16699 : mc->zeroInactiveLMDofs(_amg.getInactiveLMNodes(), _amg.getInactiveLMElems());
209 : }
210 :
211 : // Make sure any remaining cached residuals/Jacobians get added
212 13819 : if (_assembly.computingResidual())
213 11313 : _assembly.addCachedResiduals(Assembly::GlobalDataKey{}, vector_tags);
214 13819 : if (_assembly.computingJacobian())
215 3678 : _assembly.addCachedJacobian(Assembly::GlobalDataKey{});
216 13819 : }
|