libMesh
Loading...
Searching...
No Matches
petscdmlibmeshimpl.C
Go to the documentation of this file.
1// The libMesh Finite Element Library.
2// Copyright (C) 2002-2026 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/petsc_macro.h"
21
22#ifdef LIBMESH_HAVE_PETSC
23
24#include "libmesh/ignore_warnings.h"
25
26// PETSc includes
27#if !PETSC_VERSION_LESS_THAN(3,6,0)
28# include <petsc/private/dmimpl.h>
29#else
30# include <petsc-private/dmimpl.h>
31#endif
32
33#include "libmesh/restore_warnings.h"
34
35// Local Includes
36#include "libmesh/libmesh_common.h"
37#include "libmesh/nonlinear_implicit_system.h"
38#include "libmesh/petsc_nonlinear_solver.h"
39#include "libmesh/petsc_linear_solver.h"
40#include "libmesh/petsc_vector.h"
41#include "libmesh/petsc_matrix_base.h"
42#include "libmesh/petscdmlibmesh.h"
43#include "libmesh/dof_map.h"
44#include "libmesh/preconditioner.h"
45#include "libmesh/elem.h"
46#include "libmesh/parallel.h"
47
48
49using namespace libMesh;
50
51
52#define DMLIBMESH_NO_DECOMPOSITION 0
53#define DMLIBMESH_FIELD_DECOMPOSITION 1
54#define DMLIBMESH_DOMAIN_DECOMPOSITION 2
55
56#define DMLIBMESH_NO_EMBEDDING 0
57#define DMLIBMESH_FIELD_EMBEDDING 1
58#define DMLIBMESH_DOMAIN_EMBEDDING 2
59
61{
63 std::map<std::string, unsigned int> * varids;
64 std::map<unsigned int, std::string> * varnames;
65 std::map<std::string, unsigned int> * blockids;
66 std::map<unsigned int, std::string> * blocknames;
67 unsigned int decomposition_type;
68 std::vector<std::set<unsigned int>> * decomposition;
69 unsigned int embedding_type;
71 unsigned int vec_count;
72};
73
75 std::string label;
76};
77
78#undef __FUNCT__
79#define __FUNCT__ "DMlibMeshGetVec_Private"
80PetscErrorCode DMlibMeshGetVec_Private(DM /*dm*/, const char * /*name*/, Vec *)
81{
82 PetscFunctionBegin;
83
84 PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
85}
86
87
88
89PetscErrorCode DMlibMeshSetUpName_Private(DM dm);
90
91#undef __FUNCT__
92#define __FUNCT__ "DMlibMeshSetSystem_libMesh"
94{
95 const Parallel::Communicator & comm = sys.comm();
96
97 PetscFunctionBegin;
98 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
99 PetscBool islibmesh;
100 LibmeshPetscCallQ(PetscObjectTypeCompare((PetscObject)dm, DMLIBMESH,&islibmesh));
101 if (!islibmesh) LIBMESH_SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "Got DM of type %s, not of type %s", ((PetscObject)dm)->type_name, DMLIBMESH);
102
103 if (dm->setupcalled) SETERRQ(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Cannot reset the libMesh system after DM has been set up.");
104 DM_libMesh * dlm = (DM_libMesh *)(dm->data);
105 dlm->sys =&sys;
106 /* Initially populate the sets of active blockids and varids using all of the
107 existing blocks/variables (only variables are supported at the moment). */
108 DofMap & dofmap = dlm->sys->get_dof_map();
109 dlm->varids->clear();
110 dlm->varnames->clear();
111 for (auto v : make_range(dofmap.n_variables())) {
112 std::string vname = dofmap.variable(v).name();
113 dlm->varids->insert(std::pair<std::string,unsigned int>(vname,v));
114 dlm->varnames->insert(std::pair<unsigned int,std::string>(v,vname));
115 }
116 const MeshBase & mesh = dlm->sys->get_mesh();
117 dlm->blockids->clear();
118 dlm->blocknames->clear();
119 std::set<subdomain_id_type> blocks;
120 /* The following effectively is a verbatim copy of MeshBase::n_subdomains(). */
121 // This requires an inspection on every processor
122 libmesh_parallel_only(mesh.comm());
123 for (const auto & elem : mesh.active_element_ptr_range())
124 blocks.insert(elem->subdomain_id());
125 // Some subdomains may only live on other processors
126 comm.set_union(blocks);
127
128 std::set<subdomain_id_type>::iterator bit = blocks.begin();
129 std::set<subdomain_id_type>::iterator bend = blocks.end();
130 if (bit == bend) SETERRQ(((PetscObject)dm)->comm, PETSC_ERR_PLIB, "No mesh blocks found.");
131
132 for (; bit != bend; ++bit) {
133 subdomain_id_type bid = *bit;
134 std::string bname = mesh.subdomain_name(bid);
135 if (!bname.length()) {
136 /* Block names are currently implemented for Exodus II meshes
137 only, so we might have to make up our own block names and
138 maintain our own mapping of block ids to names.
139 */
140 std::ostringstream ss;
141 ss << "dm" << bid;
142 bname = ss.str();
143 }
144 dlm->blockids->insert(std::pair<std::string,unsigned int>(bname,bid));
145 dlm->blocknames->insert(std::pair<unsigned int,std::string>(bid,bname));
146 }
148 PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
149}
150
151#undef __FUNCT__
152#define __FUNCT__ "DMlibMeshGetSystem_libMesh"
154{
155 PetscFunctionBegin;
156 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
157 PetscBool islibmesh;
158 LibmeshPetscCallQ(PetscObjectTypeCompare((PetscObject)dm, DMLIBMESH,&islibmesh));
159 if (!islibmesh) LIBMESH_SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "Got DM of type %s, not of type %s", ((PetscObject)dm)->type_name, DMLIBMESH);
160 DM_libMesh * dlm = (DM_libMesh *)(dm->data);
161 sys = dlm->sys;
162 PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
163}
164
165
166#undef __FUNCT__
167#define __FUNCT__ "DMlibMeshGetBlocks"
168PetscErrorCode DMlibMeshGetBlocks(DM dm, PetscInt * n, char *** blocknames)
169{
170 PetscInt i;
171 PetscFunctionBegin;
172 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
173 PetscBool islibmesh;
174 LibmeshPetscCallQ(PetscObjectTypeCompare((PetscObject)dm, DMLIBMESH,&islibmesh));
175 if (!islibmesh) LIBMESH_SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "Got DM of type %s, not of type %s", ((PetscObject)dm)->type_name, DMLIBMESH);
176 DM_libMesh * dlm = (DM_libMesh *)(dm->data);
177#if PETSC_RELEASE_GREATER_EQUALS(3,20,0)
178 PetscAssertPointer(n,2);
179#else
180 PetscValidPointer(n,2);
181#endif
182 *n = cast_int<unsigned int>(dlm->blockids->size());
183 if (!blocknames) PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
184 LibmeshPetscCallQ(PetscMalloc(*n*sizeof(char *), blocknames));
185 i = 0;
186 for (const auto & pr : *(dlm->blockids))
187 {
188 LibmeshPetscCallQ(PetscStrallocpy(pr.first.c_str(), *blocknames+i));
189 ++i;
190 }
191 PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
192}
193
194#undef __FUNCT__
195#define __FUNCT__ "DMlibMeshGetVariables"
196PetscErrorCode DMlibMeshGetVariables(DM dm, PetscInt * n, char *** varnames)
197{
198 PetscFunctionBegin;
199 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
200 PetscBool islibmesh;
201 PetscInt i;
202 LibmeshPetscCallQ(PetscObjectTypeCompare((PetscObject)dm, DMLIBMESH,&islibmesh));
203 if (!islibmesh) LIBMESH_SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "Got DM of type %s, not of type %s", ((PetscObject)dm)->type_name, DMLIBMESH);
204 DM_libMesh * dlm = (DM_libMesh *)(dm->data);
205#if PETSC_RELEASE_GREATER_EQUALS(3,20,0)
206 PetscAssertPointer(n,2);
207#else
208 PetscValidPointer(n,2);
209#endif
210 *n = cast_int<unsigned int>(dlm->varids->size());
211 if (!varnames) PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
212 LibmeshPetscCallQ(PetscMalloc(*n*sizeof(char *), varnames));
213 i = 0;
214 for (const auto & pr : *(dlm->varids))
215 {
216 LibmeshPetscCallQ(PetscStrallocpy(pr.first.c_str(), *varnames+i));
217 ++i;
218 }
219 PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
220}
221
222#undef __FUNCT__
223#define __FUNCT__ "DMlibMeshSetUpName_Private"
224PetscErrorCode DMlibMeshSetUpName_Private(DM dm)
225{
226 DM_libMesh * dlm = (DM_libMesh *)dm->data;
227 PetscFunctionBegin;
228 std::string name = dlm->sys->name();
229 std::map<unsigned int, std::string> * dnames = LIBMESH_PETSC_NULLPTR,
230 * enames = LIBMESH_PETSC_NULLPTR;
231 if (dlm->decomposition_type == DMLIBMESH_FIELD_DECOMPOSITION) {
232 name += ":dec:var:";
233 dnames = dlm->varnames;
234 }
235 if (dlm->decomposition_type == DMLIBMESH_DOMAIN_DECOMPOSITION) {
236 name += ":dec:block:";
237 dnames = dlm->blocknames;
238 }
239 if (dnames) {
240 for (auto decomp : *dlm->decomposition) {
241 for (std::set<unsigned int>::iterator dit_begin = decomp.begin(),
242 dit = dit_begin,
243 dit_end = decomp.end();
244 dit != dit_end; ++dit) {
245 unsigned int id = *dit;
246 if (dit != dit_begin)
247 name += ",";
248 name += (*dnames)[id];
249 }
250 name += ";";
251 }
252 }
253 if (dlm->embedding_type == DMLIBMESH_FIELD_EMBEDDING) {
254 name += ":emb:var:";
255 enames = dlm->varnames;
256 }
257 if (dlm->embedding_type == DMLIBMESH_DOMAIN_EMBEDDING) {
258 name += ":emb:block:";
259 enames = dlm->blocknames;
260 }
261 if (enames) {
262 for (auto eit = enames->begin(),
263 eit_end = enames->end(); eit != eit_end; ++eit) {
264 std::string & ename = eit->second;
265 if (eit != enames->begin())
266 name += ",";
267 name += ename;
268 }
269 name += ";";
270 }
271 LibmeshPetscCallQ(PetscObjectSetName((PetscObject)dm, name.c_str()));
272 PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
273}
274
275
276#undef __FUNCT__
277#define __FUNCT__ "DMCreateFieldDecomposition_libMesh"
278static PetscErrorCode DMCreateFieldDecomposition_libMesh(DM dm, PetscInt * len, char *** namelist, IS ** islist, DM ** dmlist)
279{
280 PetscFunctionBegin;
281 DM_libMesh * dlm = (DM_libMesh *)(dm->data);
282 NonlinearImplicitSystem * sys = dlm->sys;
283 IS emb;
284 if (dlm->decomposition_type != DMLIBMESH_FIELD_DECOMPOSITION) PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
285
286 *len = cast_int<unsigned int>(dlm->decomposition->size());
287 if (namelist) {LibmeshPetscCallQ(PetscMalloc(*len*sizeof(char *), namelist));}
288 if (islist) {LibmeshPetscCallQ(PetscMalloc(*len*sizeof(IS), islist));}
289 if (dmlist) {LibmeshPetscCallQ(PetscMalloc(*len*sizeof(DM), dmlist));}
290 DofMap & dofmap = dlm->sys->get_dof_map();
291 for (auto d : index_range(*dlm->decomposition)) {
292 std::set<numeric_index_type> dindices;
293 std::string dname;
294 std::map<std::string, unsigned int> dvarids;
295 std::map<unsigned int, std::string> dvarnames;
296 unsigned int dvcount = 0;
297 for (const auto & v : (*dlm->decomposition)[d]) {
298 std::string vname = (*dlm->varnames)[v];
299 dvarids.insert(std::pair<std::string, unsigned int>(vname,v));
300 dvarnames.insert(std::pair<unsigned int,std::string>(v,vname));
301 if (!dvcount) dname = vname;
302 else dname += "_" + vname;
303 ++dvcount;
304 if (!islist) continue;
305 // Iterate only over this DM's blocks.
306 for (const auto & pr : *(dlm->blockids)) {
307 const subdomain_id_type sbd_id = cast_int<subdomain_id_type>(pr.second);
308 for (const auto & elem :
309 as_range(sys->get_mesh().active_local_subdomain_elements_begin(sbd_id),
310 sys->get_mesh().active_local_subdomain_elements_end(sbd_id))) {
311 //unsigned int e_subdomain = elem->subdomain_id();
312 std::vector<numeric_index_type> evindices;
313 // Get the degree of freedom indices for the given variable off the current element.
314 dofmap.dof_indices(elem, evindices, v);
315 for (numeric_index_type dof : evindices) {
316 if (dof >= dofmap.first_dof() && dof < dofmap.end_dof()) // might want to use variable_first/last_local_dof instead
317 dindices.insert(dof);
318 }
319 }
320 }
321 }
322 if (namelist) {
323 LibmeshPetscCallQ(PetscStrallocpy(dname.c_str(),(*namelist)+d));
324 }
325 if (islist) {
326 IS dis;
327 PetscInt * darray;
328 LibmeshPetscCallQ(PetscMalloc(sizeof(PetscInt)*dindices.size(), &darray));
329 numeric_index_type i = 0;
330 for (const auto & id : dindices) {
331 darray[i] = id;
332 ++i;
333 }
334 LibmeshPetscCallQ(ISCreateGeneral(((PetscObject)dm)->comm,
335 cast_int<PetscInt>(dindices.size()),
336 darray, PETSC_OWN_POINTER, &dis));
337 if (dlm->embedding) {
338 /* Create a relative embedding into the parent's index space. */
339 LibmeshPetscCallQ(ISEmbed(dis,dlm->embedding, PETSC_TRUE, &emb));
340 PetscInt elen, dlen;
341 LibmeshPetscCallQ(ISGetLocalSize(emb, &elen));
342 LibmeshPetscCallQ(ISGetLocalSize(dis, &dlen));
343 if (elen != dlen) LIBMESH_SETERRQ1(((PetscObject)dm)->comm, PETSC_ERR_PLIB, "Failed to embed subdomain %zu", d);
344 LibmeshPetscCallQ(ISDestroy(&dis));
345 dis = emb;
346 }
347 else {
348 emb = dis;
349 }
350 (*islist)[d] = dis;
351 }
352 if (dmlist) {
353 DM ddm;
354 LibmeshPetscCallQ(DMCreate(((PetscObject)dm)->comm, &ddm));
355 LibmeshPetscCallQ(DMSetType(ddm, DMLIBMESH));
356 DM_libMesh * ddlm = (DM_libMesh *)(ddm->data);
357 ddlm->sys = dlm->sys;
358 /* copy over the block ids and names */
359 *ddlm->blockids = *dlm->blockids;
360 *ddlm->blocknames = *dlm->blocknames;
361 /* set the vars from the d-th part of the decomposition. */
362 *ddlm->varids = dvarids;
363 *ddlm->varnames = dvarnames;
364 LibmeshPetscCallQ(PetscObjectReference((PetscObject)emb));
365 ddlm->embedding = emb;
366 ddlm->embedding_type = DMLIBMESH_FIELD_EMBEDDING;
367
369 LibmeshPetscCallQ(DMSetFromOptions(ddm));
370 (*dmlist)[d] = ddm;
371 }
372 }
373 PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
374}
375
376#undef __FUNCT__
377#define __FUNCT__ "DMCreateDomainDecomposition_libMesh"
378static PetscErrorCode DMCreateDomainDecomposition_libMesh(DM dm, PetscInt * len, char *** namelist, IS ** innerislist, IS ** outerislist, DM ** dmlist)
379{
380 PetscFunctionBegin;
381 DM_libMesh * dlm = (DM_libMesh *)(dm->data);
382 NonlinearImplicitSystem * sys = dlm->sys;
383 IS emb;
384 if (dlm->decomposition_type != DMLIBMESH_DOMAIN_DECOMPOSITION) PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
385 *len = cast_int<unsigned int>(dlm->decomposition->size());
386 if (namelist) {LibmeshPetscCallQ(PetscMalloc(*len*sizeof(char *), namelist));}
387 if (innerislist) {LibmeshPetscCallQ(PetscMalloc(*len*sizeof(IS), innerislist));}
388 if (outerislist) *outerislist = LIBMESH_PETSC_NULLPTR; /* FIX: allow mesh-based overlap. */
389 if (dmlist) {LibmeshPetscCallQ(PetscMalloc(*len*sizeof(DM), dmlist));}
390 for (auto d : index_range(*dlm->decomposition)) {
391 std::set<numeric_index_type> dindices;
392 std::string dname;
393 std::map<std::string, unsigned int> dblockids;
394 std::map<unsigned int,std::string> dblocknames;
395 unsigned int dbcount = 0;
396 for (const auto & b : (*dlm->decomposition)[d]) {
397 std::string bname = (*dlm->blocknames)[b];
398 dblockids.insert(std::pair<std::string, unsigned int>(bname,b));
399 dblocknames.insert(std::pair<unsigned int,std::string>(b,bname));
400 if (!dbcount) dname = bname;
401 else dname += "_" + bname;
402 ++dbcount;
403 if (!innerislist) continue;
404 const subdomain_id_type b_sbd_id = cast_int<subdomain_id_type>(b);
405 MeshBase::const_element_iterator el = sys->get_mesh().active_local_subdomain_elements_begin(b_sbd_id);
406 const MeshBase::const_element_iterator end_el = sys->get_mesh().active_local_subdomain_elements_end(b_sbd_id);
407 for ( ; el != end_el; ++el) {
408 const Elem * elem = *el;
409 std::vector<numeric_index_type> evindices;
410 // Iterate only over this DM's variables.
411 for (const auto & pr : *(dlm->varids)) {
412 // Get the degree of freedom indices for the given variable off the current element.
413 sys->get_dof_map().dof_indices(elem, evindices, pr.second);
414 for (const auto & dof : evindices) {
415 if (dof >= sys->get_dof_map().first_dof() && dof < sys->get_dof_map().end_dof()) // might want to use variable_first/last_local_dof instead
416 dindices.insert(dof);
417 }
418 }
419 }
420 }
421 if (namelist) {
422 LibmeshPetscCallQ(PetscStrallocpy(dname.c_str(),(*namelist)+d));
423 }
424 if (innerislist) {
425 PetscInt * darray;
426 IS dis;
427 LibmeshPetscCallQ(PetscMalloc(sizeof(PetscInt)*dindices.size(), &darray));
428 numeric_index_type i = 0;
429 for (const auto & id : dindices) {
430 darray[i] = id;
431 ++i;
432 }
433 LibmeshPetscCallQ(ISCreateGeneral(((PetscObject)dm)->comm,
434 cast_int<PetscInt>(dindices.size()),
435 darray, PETSC_OWN_POINTER, &dis));
436 if (dlm->embedding) {
437 /* Create a relative embedding into the parent's index space. */
438 LibmeshPetscCallQ(ISEmbed(dis,dlm->embedding, PETSC_TRUE, &emb));
439 PetscInt elen, dlen;
440 LibmeshPetscCallQ(ISGetLocalSize(emb, &elen));
441 LibmeshPetscCallQ(ISGetLocalSize(dis, &dlen));
442 if (elen != dlen) LIBMESH_SETERRQ1(((PetscObject)dm)->comm, PETSC_ERR_PLIB, "Failed to embed field %zu" , d);
443 LibmeshPetscCallQ(ISDestroy(&dis));
444 dis = emb;
445 }
446 else {
447 emb = dis;
448 }
449 if (innerislist) {
450 LibmeshPetscCallQ(PetscObjectReference((PetscObject)dis));
451 (*innerislist)[d] = dis;
452 }
453 LibmeshPetscCallQ(ISDestroy(&dis));
454 }
455 if (dmlist) {
456 DM ddm;
457 LibmeshPetscCallQ(DMCreate(((PetscObject)dm)->comm, &ddm));
458 LibmeshPetscCallQ(DMSetType(ddm, DMLIBMESH));
459 DM_libMesh * ddlm = (DM_libMesh *)(ddm->data);
460 ddlm->sys = dlm->sys;
461 /* copy over the varids and varnames */
462 *ddlm->varids = *dlm->varids;
463 *ddlm->varnames = *dlm->varnames;
464 /* set the blocks from the d-th part of the decomposition. */
465 *ddlm->blockids = dblockids;
466 *ddlm->blocknames = dblocknames;
467 LibmeshPetscCallQ(PetscObjectReference((PetscObject)emb));
468 ddlm->embedding = emb;
469 ddlm->embedding_type = DMLIBMESH_DOMAIN_EMBEDDING;
470
472 LibmeshPetscCallQ(DMSetFromOptions(ddm));
473 (*dmlist)[d] = ddm;
474 }
475 }
476 PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
477}
478
479
480#undef __FUNCT__
481#define __FUNCT__ "DMlibMeshCreateFieldDecompositionDM"
482PetscErrorCode DMlibMeshCreateFieldDecompositionDM(DM dm, PetscInt dnumber, PetscInt * dsizes, char *** dvarlists, DM * ddm)
483{
484 PetscBool islibmesh;
485 PetscFunctionBegin;
486 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
487 LibmeshPetscCallQ(PetscObjectTypeCompare((PetscObject)dm, DMLIBMESH,&islibmesh));
488 if (!islibmesh) LIBMESH_SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "Got DM of type %s, not of type %s", ((PetscObject)dm)->type_name, DMLIBMESH);
489 if (dnumber < 0) LIBMESH_SETERRQ1(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "Negative number %" LIBMESH_PETSCINT_FMT " of decomposition parts", dnumber);
490#if PETSC_RELEASE_GREATER_EQUALS(3,20,0)
491 PetscAssertPointer(ddm,5);
492#else
493 PetscValidPointer(ddm,5);
494#endif
495 DM_libMesh * dlm = (DM_libMesh *)(dm->data);
496 LibmeshPetscCallQ(DMCreate(((PetscObject)dm)->comm, ddm));
497 LibmeshPetscCallQ(DMSetType(*ddm, DMLIBMESH));
498 DM_libMesh * ddlm = (DM_libMesh *)((*ddm)->data);
499 ddlm->sys = dlm->sys;
500 ddlm->varids = dlm->varids;
501 ddlm->varnames = dlm->varnames;
502 ddlm->blockids = dlm->blockids;
503 ddlm->blocknames = dlm->blocknames;
504 ddlm->decomposition = new(std::vector<std::set<unsigned int>>);
505 ddlm->decomposition_type = DMLIBMESH_FIELD_DECOMPOSITION;
506 if (dnumber) {
507 for (PetscInt d = 0; d < dnumber; ++d) {
508 if (dsizes[d] < 0) LIBMESH_SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "Negative size %" LIBMESH_PETSCINT_FMT " of decomposition part %" LIBMESH_PETSCINT_FMT, dsizes[d],d);
509 ddlm->decomposition->push_back(std::set<unsigned int>());
510 for (PetscInt v = 0; v < dsizes[d]; ++v) {
511 std::string vname(dvarlists[d][v]);
512 std::map<std::string, unsigned int>::const_iterator vit = dlm->varids->find(vname);
513 if (vit == dlm->varids->end())
514 LIBMESH_SETERRQ3(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "Variable %" LIBMESH_PETSCINT_FMT " on the %" LIBMESH_PETSCINT_FMT "-th list with name %s is not owned by this DM", v, d, dvarlists[d][v]);
515 unsigned int vid = vit->second;
516 (*ddlm->decomposition)[d].insert(vid);
517 }
518 }
519 }
520 else { // Empty splits indicate default: split all variables with one per split.
521 PetscInt d = 0;
522 for (const auto & pr : (*ddlm->varids)) {
523 ddlm->decomposition->push_back(std::set<unsigned int>());
524 unsigned int vid = pr.second;
525 (*ddlm->decomposition)[d].insert(vid);
526 ++d;
527 }
528 }
530 LibmeshPetscCallQ(DMSetFromOptions(*ddm));
531 LibmeshPetscCallQ(DMSetUp(*ddm));
532 PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
533}
534
535#undef __FUNCT__
536#define __FUNCT__ "DMlibMeshCreateDomainDecompositionDM"
537PetscErrorCode DMlibMeshCreateDomainDecompositionDM(DM dm, PetscInt dnumber, PetscInt * dsizes, char *** dblocklists, DM * ddm)
538{
539 PetscBool islibmesh;
540 PetscFunctionBegin;
541 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
542 LibmeshPetscCallQ(PetscObjectTypeCompare((PetscObject)dm, DMLIBMESH,&islibmesh));
543 if (!islibmesh) LIBMESH_SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "Got DM of type %s, not of type %s", ((PetscObject)dm)->type_name, DMLIBMESH);
544 if (dnumber < 0) LIBMESH_SETERRQ1(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "Negative number %" LIBMESH_PETSCINT_FMT " of decomposition parts", dnumber);
545#if PETSC_RELEASE_GREATER_EQUALS(3,20,0)
546 PetscAssertPointer(ddm,5);
547#else
548 PetscValidPointer(ddm,5);
549#endif
550 DM_libMesh * dlm = (DM_libMesh *)(dm->data);
551 LibmeshPetscCallQ(DMCreate(((PetscObject)dm)->comm, ddm));
552 LibmeshPetscCallQ(DMSetType(*ddm, DMLIBMESH));
553 DM_libMesh * ddlm = (DM_libMesh *)((*ddm)->data);
554 ddlm->sys = dlm->sys;
555 ddlm->varids = dlm->varids;
556 ddlm->varnames = dlm->varnames;
557 ddlm->blockids = dlm->blockids;
558 ddlm->blocknames = dlm->blocknames;
559 ddlm->decomposition = new(std::vector<std::set<unsigned int>>);
560 ddlm->decomposition_type = DMLIBMESH_DOMAIN_DECOMPOSITION;
561 if (dnumber) {
562 for (PetscInt d = 0; d < dnumber; ++d) {
563 if (dsizes[d] < 0) LIBMESH_SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "Negative size %" LIBMESH_PETSCINT_FMT " of decomposition part %" LIBMESH_PETSCINT_FMT, dsizes[d],d);
564 ddlm->decomposition->push_back(std::set<unsigned int>());
565 for (PetscInt b = 0; b < dsizes[d]; ++b) {
566 std::string bname(dblocklists[d][b]);
567 std::map<std::string, unsigned int>::const_iterator bit = dlm->blockids->find(bname);
568 if (bit == dlm->blockids->end())
569 LIBMESH_SETERRQ3(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "Block %" LIBMESH_PETSCINT_FMT " on the %" LIBMESH_PETSCINT_FMT "-th list with name %s is not owned by this DM", b, d, dblocklists[d][b]);
570 unsigned int bid = bit->second;
571 (*ddlm->decomposition)[d].insert(bid);
572 }
573 }
574 }
575 else { // Empty splits indicate default: split all blocks with one per split.
576 PetscInt d = 0;
577 for (const auto & pr : (*ddlm->blockids)) {
578 ddlm->decomposition->push_back(std::set<unsigned int>());
579 unsigned int bid = pr.second;
580 (*ddlm->decomposition)[d].insert(bid);
581 ++d;
582 }
583 }
585 LibmeshPetscCallQ(DMSetFromOptions(*ddm));
586 LibmeshPetscCallQ(DMSetUp(*ddm));
587 PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
588}
589
590struct token {
591 const char * s;
592 struct token * next;
593};
594
595
596
597#undef __FUNCT__
598#define __FUNCT__ "DMlibMeshFunction"
599static PetscErrorCode DMlibMeshFunction(DM dm, Vec x, Vec r)
600{
601 PetscFunctionBegin;
604
607 NonlinearImplicitSystem & sys = *_sys;
608 PetscVector<Number> & X_sys = *cast_ptr<PetscVector<Number> *>(sys.solution.get());
609 PetscVector<Number> & R_sys = *cast_ptr<PetscVector<Number> *>(sys.rhs);
610 PetscVector<Number> X_global(x, _sys->comm()), R(r, _sys->comm());
611
612 // Use the systems update() to get a good local version of the parallel solution
613 X_global.swap(X_sys);
614 R.swap(R_sys);
615
617 _sys->update();
618
619 // Swap back
620 X_global.swap(X_sys);
621 R.swap(R_sys);
622 R.zero();
623
624 // if the user has provided both function pointers and objects only the pointer
625 // will be used, so catch that as an error
626 libmesh_error_msg_if(_sys->nonlinear_solver->residual && _sys->nonlinear_solver->residual_object,
627 "ERROR: cannot specify both a function and object to compute the Residual!");
628
629 libmesh_error_msg_if(_sys->nonlinear_solver->matvec && _sys->nonlinear_solver->residual_and_jacobian_object,
630 "ERROR: cannot specify both a function and object to compute the combined Residual & Jacobian!");
631
632 if (_sys->nonlinear_solver->residual != nullptr)
633 _sys->nonlinear_solver->residual(*(_sys->current_local_solution.get()), R, *_sys);
634
635 else if (_sys->nonlinear_solver->residual_object != nullptr)
636 _sys->nonlinear_solver->residual_object->residual(*(_sys->current_local_solution.get()), R, *_sys);
637
638 else if (_sys->nonlinear_solver->matvec != nullptr)
639 _sys->nonlinear_solver->matvec(*(_sys->current_local_solution.get()), &R, nullptr, *_sys);
640
641 else if (_sys->nonlinear_solver->residual_and_jacobian_object != nullptr)
642 _sys->nonlinear_solver->residual_and_jacobian_object->residual_and_jacobian(*(_sys->current_local_solution.get()), &R, nullptr, *_sys);
643
644 else
645 libmesh_error_msg("Error! Unable to compute residual and/or Jacobian!");
646
647 R.close();
648 X_global.close();
649 PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
650}
651
652#undef __FUNCT__
653#define __FUNCT__ "SNESFunction_DMlibMesh"
654static PetscErrorCode SNESFunction_DMlibMesh(SNES, Vec x, Vec r, void * ctx)
655{
656 DM dm = (DM)ctx;
657 PetscFunctionBegin;
659 PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
660}
661
662
663#undef __FUNCT__
664#define __FUNCT__ "DMlibMeshJacobian"
665static PetscErrorCode DMlibMeshJacobian(DM dm, Vec x, Mat jac, Mat pc)
666{
667 PetscFunctionBegin;
670 NonlinearImplicitSystem & sys = *_sys;
671
672 libmesh_assert(pc);
673 libmesh_assert(jac);
676 PetscVector<Number> & X_sys = *cast_ptr<PetscVector<Number> *>(sys.solution.get());
677 PetscMatrixBase<Number> & Jac_sys = *cast_ptr<PetscMatrixBase<Number> *>(sys.matrix);
678 PetscVector<Number> X_global(x, sys.comm());
679
680 // Set the dof maps
681 the_pc.attach_dof_map(sys.get_dof_map());
682 Jac.attach_dof_map(sys.get_dof_map());
683
684 // Use the systems update() to get a good local version of the parallel solution
685 X_global.swap(X_sys);
686 Jac.swap(Jac_sys);
687
689 sys.update();
690
691 X_global.swap(X_sys);
692 Jac.swap(Jac_sys);
693
694 the_pc.zero();
695
696 // if the user has provided both function pointers and objects only the pointer
697 // will be used, so catch that as an error
698 libmesh_error_msg_if(sys.nonlinear_solver->jacobian && sys.nonlinear_solver->jacobian_object,
699 "ERROR: cannot specify both a function and object to compute the Jacobian!");
700
701 libmesh_error_msg_if(sys.nonlinear_solver->matvec && sys.nonlinear_solver->residual_and_jacobian_object,
702 "ERROR: cannot specify both a function and object to compute the combined Residual & Jacobian!");
703
704 if (sys.nonlinear_solver->jacobian != nullptr)
705 sys.nonlinear_solver->jacobian(*(sys.current_local_solution.get()), the_pc, sys);
706
707 else if (sys.nonlinear_solver->jacobian_object != nullptr)
708 sys.nonlinear_solver->jacobian_object->jacobian(*(sys.current_local_solution.get()), the_pc, sys);
709
710 else if (sys.nonlinear_solver->matvec != nullptr)
711 sys.nonlinear_solver->matvec(*(sys.current_local_solution.get()), nullptr, &the_pc, sys);
712
713 else if (sys.nonlinear_solver->residual_and_jacobian_object != nullptr)
714 sys.nonlinear_solver->residual_and_jacobian_object->residual_and_jacobian(*(sys.current_local_solution.get()), nullptr, &the_pc, sys);
715
716 else
717 libmesh_error_msg("Error! Unable to compute residual and/or Jacobian!");
718
719 the_pc.close();
720 Jac.close();
721 X_global.close();
722 PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
723}
724
725#undef __FUNCT__
726#define __FUNCT__ "SNESJacobian_DMlibMesh"
727static PetscErrorCode SNESJacobian_DMlibMesh(SNES, Vec x, Mat jac, Mat pc, void * ctx)
728{
729 DM dm = (DM)ctx;
730 PetscFunctionBegin;
732 PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
733}
734
735#undef __FUNCT__
736#define __FUNCT__ "DMVariableBounds_libMesh"
737static PetscErrorCode DMVariableBounds_libMesh(DM dm, Vec xl, Vec xu)
738{
741 NonlinearImplicitSystem & sys = *_sys;
742 PetscVector<Number> XL(xl, sys.comm());
743 PetscVector<Number> XU(xu, sys.comm());
744 PetscFunctionBegin;
745 // Workaround for nonstandard Q suffix warning with quad precision
746 const PetscReal petsc_inf = std::numeric_limits<PetscReal>::max() / 4;
747 LibmeshPetscCallQ(VecSet(xl, -petsc_inf));
748 LibmeshPetscCallQ(VecSet(xu, petsc_inf));
749 if (sys.nonlinear_solver->bounds != nullptr)
750 sys.nonlinear_solver->bounds(XL,XU,sys);
751 else if (sys.nonlinear_solver->bounds_object != nullptr)
752 sys.nonlinear_solver->bounds_object->bounds(XL,XU, sys);
753 else
754 SETERRQ(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "No bounds calculation in this libMesh object");
755
756 PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
757}
758
759
760#undef __FUNCT__
761#define __FUNCT__ "DMCreateGlobalVector_libMesh"
762static PetscErrorCode DMCreateGlobalVector_libMesh(DM dm, Vec *x)
763{
764 PetscFunctionBegin;
765 DM_libMesh * dlm = (DM_libMesh *)(dm->data);
766 PetscBool eq;
767
768 LibmeshPetscCallQ(PetscObjectTypeCompare((PetscObject)dm, DMLIBMESH, &eq));
769
770 if (!eq)
771 LIBMESH_SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "DM of type %s, not of type %s", ((PetscObject)dm)->type_name, DMLIBMESH);
772
773 if (!dlm->sys)
774 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE, "No libMesh system set for DM_libMesh");
775
776 NumericVector<Number> * nv = (dlm->sys->solution).get();
777 PetscVector<Number> * pv = dynamic_cast<PetscVector<Number> *>(nv);
778 Vec v = pv->vec();
779 /* Unfortunately, currently this does not produce a ghosted vector, so nonlinear subproblem solves aren't going to be easily available.
780 Should work fine for getting vectors out for linear subproblem solvers. */
781 if (dlm->embedding) {
782 PetscInt n;
783 LibmeshPetscCallQ(VecCreate(((PetscObject)v)->comm, x));
784 LibmeshPetscCallQ(ISGetLocalSize(dlm->embedding, &n));
785 LibmeshPetscCallQ(VecSetSizes(*x,n,PETSC_DETERMINE));
786 LibmeshPetscCallQ(VecSetType(*x,((PetscObject)v)->type_name));
787 LibmeshPetscCallQ(VecSetFromOptions(*x));
788 LibmeshPetscCallQ(VecSetUp(*x));
789 }
790 else {
791 LibmeshPetscCallQ(VecDuplicate(v,x));
792 }
793
794#if PETSC_VERSION_LESS_THAN(3,13,0)
795 LibmeshPetscCallQ(PetscObjectCompose((PetscObject)*x,"DM",(PetscObject)dm));
796#else
797 LibmeshPetscCallQ(VecSetDM(*x, dm));
798#endif
799
800 PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
801}
802
803
804
805
806#undef __FUNCT__
807#define __FUNCT__ "DMCreateMatrix_libMesh"
808static PetscErrorCode DMCreateMatrix_libMesh(DM dm, Mat * A)
809{
810 PetscFunctionBegin;
811 DM_libMesh * dlm = (DM_libMesh *)(dm->data);
812 PetscBool eq;
813
814 LibmeshPetscCallQ(PetscObjectTypeCompare((PetscObject)dm, DMLIBMESH, &eq));
815
816 if (!eq)
817 LIBMESH_SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "DM of type %s, not of type %s", ((PetscObject)dm)->type_name, DMLIBMESH);
818
819 if (!dlm->sys)
820 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE, "No libMesh system set for DM_libMesh");
821
822 *A = (dynamic_cast<PetscMatrixBase<Number> *>(dlm->sys->matrix))->mat();
823 LibmeshPetscCallQ(PetscObjectReference((PetscObject)(*A)));
824 PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
825}
826
827
828#undef __FUNCT__
829#define __FUNCT__ "DMView_libMesh"
830static PetscErrorCode DMView_libMesh(DM dm, PetscViewer viewer)
831{
832 PetscBool isascii;
833 const char * name, * prefix;
834 DM_libMesh * dlm = (DM_libMesh *)dm->data;
835 PetscFunctionBegin;
836 LibmeshPetscCallQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
837 if (isascii) {
838 LibmeshPetscCallQ(PetscObjectGetName((PetscObject)dm, &name));
839 LibmeshPetscCallQ(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
840 LibmeshPetscCallQ(PetscViewerASCIIPrintf(viewer, "DM libMesh with name %s and prefix %s\n", name, prefix));
841 LibmeshPetscCallQ(PetscViewerASCIIPrintf(viewer, "blocks:"));
842 std::map<std::string,unsigned int>::iterator bit = dlm->blockids->begin();
843 std::map<std::string,unsigned int>::const_iterator bend = dlm->blockids->end();
844 for (; bit != bend; ++bit) {
845 LibmeshPetscCallQ(PetscViewerASCIIPrintf(viewer, "(%s,%d) ", bit->first.c_str(), bit->second));
846 }
847 LibmeshPetscCallQ(PetscViewerASCIIPrintf(viewer, "\n"));
848 LibmeshPetscCallQ(PetscViewerASCIIPrintf(viewer, "variables:"));
849 std::map<std::string,unsigned int>::iterator vit = dlm->varids->begin();
850 std::map<std::string,unsigned int>::const_iterator vend = dlm->varids->end();
851 for (; vit != vend; ++vit) {
852 LibmeshPetscCallQ(PetscViewerASCIIPrintf(viewer, "(%s,%d) ", vit->first.c_str(), vit->second));
853 }
854 LibmeshPetscCallQ(PetscViewerASCIIPrintf(viewer, "\n"));
855 if (dlm->decomposition_type == DMLIBMESH_NO_DECOMPOSITION) {
856 LibmeshPetscCallQ(PetscViewerASCIIPrintf(viewer, "No decomposition\n"));
857 }
858 else {
859 if (dlm->decomposition_type == DMLIBMESH_FIELD_DECOMPOSITION) {
860 LibmeshPetscCallQ(PetscViewerASCIIPrintf(viewer, "Field decomposition by variable: "));
861 }
862 else if (dlm->decomposition_type == DMLIBMESH_DOMAIN_DECOMPOSITION) {
863 LibmeshPetscCallQ(PetscViewerASCIIPrintf(viewer, "Domain decomposition by block: "));
864 }
865 else LIBMESH_SETERRQ1(((PetscObject)dm)->comm, PETSC_ERR_PLIB, "Unexpected decomposition type: %d", dlm->decomposition_type);
866 /* FIX: decompositions might have different sizes and components on different ranks. */
867 for (auto d : index_range(*dlm->decomposition)) {
868 std::set<unsigned int>::iterator dbegin = (*dlm->decomposition)[d].begin();
869 std::set<unsigned int>::iterator dit = (*dlm->decomposition)[d].begin();
870 std::set<unsigned int>::iterator dend = (*dlm->decomposition)[d].end();
871 for (; dit != dend; ++dit) {
872 if (dit != dbegin) {
873 LibmeshPetscCallQ(PetscViewerASCIIPrintf(viewer, ","));
874 }
875 LibmeshPetscCallQ(PetscViewerASCIIPrintf(viewer, "%u", *dit));
876 }
877 LibmeshPetscCallQ(PetscViewerASCIIPrintf(viewer, ";"));
878 }
879 LibmeshPetscCallQ(PetscViewerASCIIPrintf(viewer, "\n"));
880 }
881 }
882
883 PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
884}
885
886#undef __FUNCT__
887#define __FUNCT__ "DMSetUp_libMesh"
888static PetscErrorCode DMSetUp_libMesh(DM dm)
889{
890 PetscFunctionBegin;
891 DM_libMesh * dlm = (DM_libMesh *)(dm->data);
892 PetscBool eq;
893
894 LibmeshPetscCallQ(PetscObjectTypeCompare((PetscObject)dm, DMLIBMESH, &eq));
895
896 if (!eq)
897 LIBMESH_SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "DM of type %s, not of type %s", ((PetscObject)dm)->type_name, DMLIBMESH);
898
899 if (!dlm->sys)
900 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE, "No libMesh system set for DM_libMesh");
901 /*
902 Do not evaluate function, Jacobian or bounds for an embedded DM -- the subproblem might not have enough information for that.
903 */
904 if (!dlm->embedding) {
905 LibmeshPetscCallQ(DMSNESSetFunction(dm, SNESFunction_DMlibMesh, (void *)dm));
906 LibmeshPetscCallQ(DMSNESSetJacobian(dm, SNESJacobian_DMlibMesh, (void *)dm));
907 if (dlm->sys->nonlinear_solver->bounds || dlm->sys->nonlinear_solver->bounds_object)
908 LibmeshPetscCallQ(DMSetVariableBounds(dm, DMVariableBounds_libMesh));
909 }
910 else {
911 /*
912 Fow now we don't implement even these, although a linear "Dirichlet" subproblem is well-defined.
913 Creating the submatrix, however, might require extracting the submatrix preallocation from an unassembled matrix.
914 */
915 dm->ops->createglobalvector = 0;
916 dm->ops->creatematrix = 0;
917 }
918 PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
919}
920
921
922
923
924#undef __FUNCT__
925#define __FUNCT__ "DMDestroy_libMesh"
926static PetscErrorCode DMDestroy_libMesh(DM dm)
927{
928 DM_libMesh * dlm = (DM_libMesh *)(dm->data);
929 PetscFunctionBegin;
930 delete dlm->varids;
931 delete dlm->varnames;
932 delete dlm->blockids;
933 delete dlm->blocknames;
934 delete dlm->decomposition;
935 LibmeshPetscCallQ(ISDestroy(&dlm->embedding));
936 LibmeshPetscCallQ(PetscFree(dm->data));
937
938 PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
939}
940
941EXTERN_C_BEGIN
942#undef __FUNCT__
943#define __FUNCT__ "DMCreate_libMesh"
944PetscErrorCode DMCreate_libMesh(DM dm)
945{
946 DM_libMesh * dlm;
947
948 PetscFunctionBegin;
949 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
950 LibmeshPetscCallQ(PetscNew(&dlm));
951 dm->data = dlm;
952
953 /* DMlibMesh impl */
954 dlm->varids = new(std::map<std::string, unsigned int>);
955 dlm->blockids = new(std::map<std::string, unsigned int>);
956 dlm->varnames = new(std::map<unsigned int, std::string>);
957 dlm->blocknames = new(std::map<unsigned int, std::string>);
958 dlm->decomposition = LIBMESH_PETSC_NULLPTR;
959 dlm->decomposition_type = DMLIBMESH_NO_DECOMPOSITION;
960
961 /* DM API */
962 dm->ops->createglobalvector = DMCreateGlobalVector_libMesh;
963 dm->ops->createlocalvector = 0; // DMCreateLocalVector_libMesh;
964 dm->ops->getcoloring = 0; // DMGetColoring_libMesh;
965 dm->ops->creatematrix = DMCreateMatrix_libMesh;
966 dm->ops->createinterpolation= 0; // DMCreateInterpolation_libMesh;
967
968 dm->ops->refine = 0; // DMRefine_libMesh;
969 dm->ops->coarsen = 0; // DMCoarsen_libMesh;
970
971 // * dm->ops->getinjection was renamed to dm->ops->createinjection in PETSc 5a84ad338 (5 Jul 2019)
972 // * dm->ops-getaggregates was removed in PETSc 97779f9a (5 Jul 2019)
973 // * Both changes were merged into PETSc master in 94aad3ce (7 Jul 2019).
974#if PETSC_VERSION_LESS_THAN(3,12,0)
975 dm->ops->getinjection = 0; // DMGetInjection_libMesh;
976 dm->ops->getaggregates = 0; // DMGetAggregates_libMesh;
977#else
978 dm->ops->createinjection = 0;
979#endif
980
981
982 dm->ops->createfielddecomposition = DMCreateFieldDecomposition_libMesh;
983 dm->ops->createdomaindecomposition = DMCreateDomainDecomposition_libMesh;
984
985 dm->ops->destroy = DMDestroy_libMesh;
986 dm->ops->view = DMView_libMesh;
987 dm->ops->setfromoptions = 0; // DMSetFromOptions_libMesh;
988 dm->ops->setup = DMSetUp_libMesh;
989
990 /* DMlibMesh API */
991 LibmeshPetscCallQ(PetscObjectComposeFunction((PetscObject)dm,"DMlibMeshSetSystem_C",DMlibMeshSetSystem_libMesh));
992 LibmeshPetscCallQ(PetscObjectComposeFunction((PetscObject)dm,"DMlibMeshGetSystem_C",DMlibMeshGetSystem_libMesh));
993
994 PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
995}
996EXTERN_C_END
997
998#endif // LIBMESH_HAVE_PETSC
void set_union(T &data, const unsigned int root_id) const
dof_id_type first_dof(const processor_id_type proc) const
dof_id_type end_dof(const processor_id_type proc) const
This class handles the numbering of degrees of freedom on a mesh.
Definition dof_map.h:181
unsigned int n_variables() const override
Definition dof_map.h:736
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
Definition dof_map.C:2201
const Variable & variable(const unsigned int c) const override
Definition dof_map.h:2358
void enforce_constraints_exactly(const System &system, NumericVector< Number > *v=nullptr, bool homogeneous=false) const
Constrains the numeric vector v, which represents a solution defined on the mesh.
Definition dof_map.h:2518
This is the base class from which all geometric element types are derived.
Definition elem.h:96
NumericVector< Number > * rhs
The system matrix.
SparseMatrix< Number > * matrix
The system matrix.
This is the MeshBase class.
Definition mesh_base.h:81
std::string & subdomain_name(subdomain_id_type id)
Definition mesh_base.C:1887
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and non-linear solv...
std::unique_ptr< NonlinearSolver< Number > > nonlinear_solver
The NonlinearSolver defines the default interface used to solve the nonlinear_implicit system.
Provides a uniform interface to vector storage schemes for different linear algebra libraries.
const Parallel::Communicator & comm() const
This class provides a nice interface to the PETSc C-based data structures for parallel,...
void swap(PetscMatrixBase< T > &)
Swaps the internal data pointers of two PetscMatrices, no actual values are swapped.
static PetscMatrixBase< T > * get_context(Mat mat, const TIMPI::Communicator &comm)
virtual void close() override
Calls the SparseMatrix's internal assembly routines, ensuring that the values are consistent across p...
This class provides a nice interface to PETSc's Vec object.
void attach_dof_map(const DofMap &dof_map)
Set a pointer to the DofMap to use.
virtual void zero()=0
Set all entries to 0.
const std::string & name() const
Definition system.h:2385
std::unique_ptr< NumericVector< Number > > current_local_solution
All the values I need to compute my contribution to the simulation at hand.
Definition system.h:1667
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
Definition system.h:1655
virtual void update()
Update the local values to reflect the solution on neighboring processors.
Definition system.C:498
const DofMap & get_dof_map() const
Definition system.h:2417
const MeshBase & get_mesh() const
Definition system.h:2401
const std::string & name() const
Definition variable.h:122
static const Real b
MeshBase & mesh
The libMesh namespace provides an interface to certain functionality in the library.
PetscFunctionReturn(LIBMESH_PETSC_SUCCESS)
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition int_range.h:153
libmesh_assert(ctx)
dof_id_type numeric_index_type
Definition id_types.h:99
LibmeshPetscCallQ(DMShellGetContext(dm, &ctx))
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Definition int_range.h:176
PETSC_EXTERN PetscErrorCode DMlibMeshGetSystem(DM, libMesh::NonlinearImplicitSystem *&)
static PetscErrorCode DMlibMeshFunction(DM dm, Vec x, Vec r)
static PetscErrorCode DMCreateGlobalVector_libMesh(DM dm, Vec *x)
static PetscErrorCode SNESFunction_DMlibMesh(SNES, Vec x, Vec r, void *ctx)
static PetscErrorCode DMView_libMesh(DM dm, PetscViewer viewer)
static PetscErrorCode DMSetUp_libMesh(DM dm)
PetscErrorCode DMlibMeshGetBlocks(DM dm, PetscInt *n, char ***blocknames)
static PetscErrorCode DMlibMeshJacobian(DM dm, Vec x, Mat jac, Mat pc)
static PetscErrorCode DMCreateMatrix_libMesh(DM dm, Mat *A)
PetscErrorCode DMlibMeshSetUpName_Private(DM dm)
static PetscErrorCode SNESJacobian_DMlibMesh(SNES, Vec x, Mat jac, Mat pc, void *ctx)
PetscErrorCode DMlibMeshCreateFieldDecompositionDM(DM dm, PetscInt dnumber, PetscInt *dsizes, char ***dvarlists, DM *ddm)
PetscErrorCode DMlibMeshGetVec_Private(DM, const char *, Vec *)
PetscErrorCode DMCreate_libMesh(DM dm)
static PetscErrorCode DMDestroy_libMesh(DM dm)
static PetscErrorCode DMVariableBounds_libMesh(DM dm, Vec xl, Vec xu)
PetscErrorCode DMlibMeshGetVariables(DM dm, PetscInt *n, char ***varnames)
PetscErrorCode DMlibMeshGetSystem_libMesh(DM dm, NonlinearImplicitSystem *&sys)
PetscErrorCode DMlibMeshSetSystem_libMesh(DM dm, NonlinearImplicitSystem &sys)
static PetscErrorCode DMCreateFieldDecomposition_libMesh(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist)
static PetscErrorCode DMCreateDomainDecomposition_libMesh(DM dm, PetscInt *len, char ***namelist, IS **innerislist, IS **outerislist, DM **dmlist)
PetscErrorCode DMlibMeshCreateDomainDecompositionDM(DM dm, PetscInt dnumber, PetscInt *dsizes, char ***dblocklists, DM *ddm)
unsigned int decomposition_type
std::vector< std::set< unsigned int > > * decomposition
std::map< std::string, unsigned int > * varids
unsigned int embedding_type
std::map< unsigned int, std::string > * blocknames
unsigned int vec_count
NonlinearImplicitSystem * sys
std::map< std::string, unsigned int > * blockids
std::map< unsigned int, std::string > * varnames
The definition of the const_element_iterator struct.
Definition mesh_base.h:2556
const char * s
struct token * next