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 891 : 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 891 : Assembly & assembly)
37 891 : : _amg(amg),
38 891 : _subproblem(subproblem),
39 891 : _fe_problem(fe_problem),
40 891 : _displaced(displaced),
41 891 : _assembly(assembly)
42 : {
43 : // Construct the mortar constraints we will later loop over
44 2109 : for (auto mc : mortar_constraints)
45 1218 : _mortar_constraints.push_back(mc.get());
46 :
47 891 : Moose::Mortar::setupMortarMaterials(_mortar_constraints,
48 : _fe_problem,
49 : _amg,
50 : 0,
51 891 : _secondary_ip_sub_to_mats,
52 891 : _primary_ip_sub_to_mats,
53 891 : _secondary_boundary_mats);
54 891 : }
55 :
56 : void
57 172 : ComputeMortarFunctor::setupMortarMaterials()
58 : {
59 172 : Moose::Mortar::setupMortarMaterials(_mortar_constraints,
60 : _fe_problem,
61 : _amg,
62 : /*thread id*/ 0,
63 172 : _secondary_ip_sub_to_mats,
64 172 : _primary_ip_sub_to_mats,
65 172 : _secondary_boundary_mats);
66 172 : }
67 :
68 : void
69 12378 : 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 12378 : unsigned int num_cached = 0;
76 12378 : const auto & vector_tags = _fe_problem.getVectorTags(vector_tag_ids);
77 :
78 12378 : const auto & secondary_elems_to_mortar_segments = _amg.secondariesToMortarSegments();
79 : typedef decltype(secondary_elems_to_mortar_segments.begin()) it_type;
80 :
81 12378 : std::vector<it_type> iterators;
82 12378 : for (auto it = secondary_elems_to_mortar_segments.begin();
83 88674 : it != secondary_elems_to_mortar_segments.end();
84 76296 : ++it)
85 : {
86 76296 : auto * const secondary_elem = _subproblem.mesh().getMesh().query_elem_ptr(it->first);
87 :
88 133596 : if (secondary_elem && secondary_elem->processor_id() == _subproblem.processor_id() &&
89 57300 : !it->second.empty())
90 : {
91 : // This is local and the mortar segment set isn't empty, so include
92 57300 : 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 252896 : auto act_functor = [this, &num_cached, compute_type, &vector_tags]()
100 : {
101 252896 : ++num_cached;
102 :
103 252896 : switch (compute_type)
104 : {
105 170678 : case Moose::ComputeType::Residual:
106 : {
107 352568 : for (auto * const mc : _mortar_constraints)
108 : {
109 181890 : mc->setNormals();
110 181890 : mc->computeResidual();
111 : }
112 :
113 170678 : _assembly.cacheResidual(Assembly::GlobalDataKey{}, vector_tags);
114 170678 : _assembly.cacheResidualNeighbor(Assembly::GlobalDataKey{}, vector_tags);
115 170678 : _assembly.cacheResidualLower(Assembly::GlobalDataKey{}, vector_tags);
116 :
117 170678 : if (num_cached % 20 == 0)
118 6289 : _assembly.addCachedResiduals(Assembly::GlobalDataKey{}, vector_tags);
119 :
120 170678 : break;
121 : }
122 :
123 79370 : case Moose::ComputeType::Jacobian:
124 : {
125 164756 : for (auto * const mc : _mortar_constraints)
126 : {
127 85386 : mc->setNormals();
128 85386 : mc->computeJacobian();
129 : }
130 :
131 79370 : _assembly.cacheJacobianMortar(Assembly::GlobalDataKey{});
132 :
133 79370 : if (num_cached % 20 == 0)
134 3501 : _assembly.addCachedJacobian(Assembly::GlobalDataKey{});
135 79370 : break;
136 : }
137 :
138 2848 : case Moose::ComputeType::ResidualAndJacobian:
139 : {
140 5696 : for (auto * const mc : _mortar_constraints)
141 : {
142 2848 : mc->setNormals();
143 2848 : mc->computeResidualAndJacobian();
144 : }
145 :
146 2848 : _assembly.cacheResidual(Assembly::GlobalDataKey{}, vector_tags);
147 2848 : _assembly.cacheResidualNeighbor(Assembly::GlobalDataKey{}, vector_tags);
148 2848 : _assembly.cacheResidualLower(Assembly::GlobalDataKey{}, vector_tags);
149 2848 : _assembly.cacheJacobianMortar(Assembly::GlobalDataKey{});
150 :
151 2848 : if (num_cached % 20 == 0)
152 : {
153 0 : _assembly.addCachedResiduals(Assembly::GlobalDataKey{}, vector_tags);
154 0 : _assembly.addCachedJacobian(Assembly::GlobalDataKey{});
155 : }
156 2848 : break;
157 : }
158 : }
159 252896 : };
160 :
161 : PARALLEL_TRY
162 : {
163 : try
164 : {
165 12378 : Moose::Mortar::loopOverMortarSegments(iterators,
166 : _assembly,
167 : _subproblem,
168 : _fe_problem,
169 : _amg,
170 12378 : _displaced,
171 12378 : _mortar_constraints,
172 : 0,
173 12378 : _secondary_ip_sub_to_mats,
174 12378 : _primary_ip_sub_to_mats,
175 12378 : _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 12378 : PARALLEL_CATCH;
199 :
200 : // Call any post operations for our mortar constraints
201 27448 : for (auto * const mc : _mortar_constraints)
202 : {
203 15070 : if (_amg.incorrectEdgeDropping())
204 6390 : mc->incorrectEdgeDroppingPost(_amg.getInactiveLMNodes());
205 : else
206 8680 : mc->post();
207 :
208 15070 : mc->zeroInactiveLMDofs(_amg.getInactiveLMNodes(), _amg.getInactiveLMElems());
209 : }
210 :
211 : // Make sure any remaining cached residuals/Jacobians get added
212 12378 : if (_assembly.computingResidual())
213 10145 : _assembly.addCachedResiduals(Assembly::GlobalDataKey{}, vector_tags);
214 12378 : if (_assembly.computingJacobian())
215 3290 : _assembly.addCachedJacobian(Assembly::GlobalDataKey{});
216 12378 : }
|