xref: /libCEED/examples/fluids/src/inverse_multiplicity.c (revision 3a10b0eea181dc293479a0dbf82d5df1dcd22873)
1*3a10b0eeSJames Wright // Copyright (c) 2017-2024, Lawrence Livermore National Security, LLC and other CEED contributors.
2*3a10b0eeSJames Wright // All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
3*3a10b0eeSJames Wright //
4*3a10b0eeSJames Wright // SPDX-License-Identifier: BSD-2-Clause
5*3a10b0eeSJames Wright //
6*3a10b0eeSJames Wright // This file is part of CEED:  http://github.com/ceed
7*3a10b0eeSJames Wright 
8*3a10b0eeSJames Wright #include "../qfunctions/inverse_multiplicity.h"
9*3a10b0eeSJames Wright #include "../navierstokes.h"
10*3a10b0eeSJames Wright 
11*3a10b0eeSJames Wright /**
12*3a10b0eeSJames Wright  * @brief Get the inverse of the node multiplicity
13*3a10b0eeSJames Wright  *
14*3a10b0eeSJames Wright  * Local multiplicity concerns only the number of elements associated with a node in the current rank's partition.
15*3a10b0eeSJames Wright  * Global multiplicity is the multiplicity for the global mesh, including periodicity.
16*3a10b0eeSJames Wright  *
17*3a10b0eeSJames Wright  * @param[in]  ceed                        `Ceed` object for the output `CeedVector` and `CeedElemRestriction`
18*3a10b0eeSJames Wright  * @param[in]  dm                          `DM` for the grid
19*3a10b0eeSJames Wright  * @param[in]  domain_label                `DMLabel` for `DMPlex` domain
20*3a10b0eeSJames Wright  * @param[in]  label_value                 Stratum value
21*3a10b0eeSJames Wright  * @param[in]  height                      Height of `DMPlex` topology
22*3a10b0eeSJames Wright  * @param[in]  dm_field                    Index of `DMPlex` field
23*3a10b0eeSJames Wright  * @param[in]  get_global_multiplicity     Whether the multiplicity should be global or local
24*3a10b0eeSJames Wright  * @param[out] elem_restr_inv_multiplicity `CeedElemRestriction` needed to use the multiplicity vector
25*3a10b0eeSJames Wright  * @param[out] inv_multiplicity            `CeedVector` containing the inverse of the multiplicity
26*3a10b0eeSJames Wright  */
27*3a10b0eeSJames Wright PetscErrorCode GetInverseMultiplicity(Ceed ceed, DM dm, DMLabel domain_label, PetscInt label_value, PetscInt height, PetscInt dm_field,
28*3a10b0eeSJames Wright                                       PetscBool get_global_multiplicity, CeedElemRestriction *elem_restr_inv_multiplicity,
29*3a10b0eeSJames Wright                                       CeedVector *inv_multiplicity) {
30*3a10b0eeSJames Wright   Vec                 Multiplicity, Multiplicity_loc;
31*3a10b0eeSJames Wright   PetscMemType        m_mem_type;
32*3a10b0eeSJames Wright   CeedVector          multiplicity;
33*3a10b0eeSJames Wright   CeedQFunction       qf_multiplicity;
34*3a10b0eeSJames Wright   CeedOperator        op_multiplicity;
35*3a10b0eeSJames Wright   CeedInt             num_comp;
36*3a10b0eeSJames Wright   CeedElemRestriction elem_restr;
37*3a10b0eeSJames Wright 
38*3a10b0eeSJames Wright   PetscFunctionBeginUser;
39*3a10b0eeSJames Wright 
40*3a10b0eeSJames Wright   PetscCall(DMPlexCeedElemRestrictionCollocatedCreate(ceed, dm, domain_label, label_value, height, 1, elem_restr_inv_multiplicity));
41*3a10b0eeSJames Wright   PetscCallCeed(ceed, CeedElemRestrictionCreateVector(*elem_restr_inv_multiplicity, inv_multiplicity, NULL));
42*3a10b0eeSJames Wright 
43*3a10b0eeSJames Wright   PetscCall(DMPlexCeedElemRestrictionCreate(ceed, dm, domain_label, label_value, height, dm_field, &elem_restr));
44*3a10b0eeSJames Wright   PetscCallCeed(ceed, CeedElemRestrictionGetNumComponents(elem_restr, &num_comp));
45*3a10b0eeSJames Wright   PetscCallCeed(ceed, CeedElemRestrictionCreateVector(elem_restr, &multiplicity, NULL));
46*3a10b0eeSJames Wright 
47*3a10b0eeSJames Wright   if (get_global_multiplicity) {
48*3a10b0eeSJames Wright     // In order to get global multiplicity, we need to run through DMLocalToGlobal -> DMGlobalToLocal.
49*3a10b0eeSJames Wright     PetscCall(DMGetLocalVector(dm, &Multiplicity_loc));
50*3a10b0eeSJames Wright     PetscCall(DMGetGlobalVector(dm, &Multiplicity));
51*3a10b0eeSJames Wright 
52*3a10b0eeSJames Wright     PetscCall(VecPetscToCeed(Multiplicity_loc, &m_mem_type, multiplicity));
53*3a10b0eeSJames Wright     PetscCallCeed(ceed, CeedElemRestrictionGetMultiplicity(elem_restr, multiplicity));
54*3a10b0eeSJames Wright     PetscCall(VecCeedToPetsc(multiplicity, m_mem_type, Multiplicity_loc));
55*3a10b0eeSJames Wright     PetscCall(VecZeroEntries(Multiplicity));
56*3a10b0eeSJames Wright     PetscCall(DMLocalToGlobal(dm, Multiplicity_loc, ADD_VALUES, Multiplicity));
57*3a10b0eeSJames Wright     PetscCall(DMGlobalToLocal(dm, Multiplicity, INSERT_VALUES, Multiplicity_loc));
58*3a10b0eeSJames Wright     PetscCall(VecPetscToCeed(Multiplicity_loc, &m_mem_type, multiplicity));
59*3a10b0eeSJames Wright   } else {
60*3a10b0eeSJames Wright     PetscCallCeed(ceed, CeedElemRestrictionGetMultiplicity(elem_restr, multiplicity));
61*3a10b0eeSJames Wright   }
62*3a10b0eeSJames Wright 
63*3a10b0eeSJames Wright   PetscCallCeed(ceed, CeedQFunctionCreateInterior(ceed, 1, InverseMultiplicity, InverseMultiplicity_loc, &qf_multiplicity));
64*3a10b0eeSJames Wright   PetscCallCeed(ceed, CeedQFunctionAddInput(qf_multiplicity, "multiplicity", num_comp, CEED_EVAL_NONE));
65*3a10b0eeSJames Wright   PetscCallCeed(ceed, CeedQFunctionAddOutput(qf_multiplicity, "inverse multiplicity", 1, CEED_EVAL_NONE));
66*3a10b0eeSJames Wright 
67*3a10b0eeSJames Wright   PetscCallCeed(ceed, CeedOperatorCreate(ceed, qf_multiplicity, NULL, NULL, &op_multiplicity));
68*3a10b0eeSJames Wright   PetscCallCeed(ceed, CeedOperatorSetName(op_multiplicity, "InverseMultiplicity"));
69*3a10b0eeSJames Wright   PetscCallCeed(ceed, CeedOperatorSetField(op_multiplicity, "multiplicity", elem_restr, CEED_BASIS_NONE, CEED_VECTOR_ACTIVE));
70*3a10b0eeSJames Wright   PetscCallCeed(ceed,
71*3a10b0eeSJames Wright                 CeedOperatorSetField(op_multiplicity, "inverse multiplicity", *elem_restr_inv_multiplicity, CEED_BASIS_NONE, CEED_VECTOR_ACTIVE));
72*3a10b0eeSJames Wright 
73*3a10b0eeSJames Wright   PetscCallCeed(ceed, CeedOperatorApply(op_multiplicity, multiplicity, *inv_multiplicity, CEED_REQUEST_IMMEDIATE));
74*3a10b0eeSJames Wright 
75*3a10b0eeSJames Wright   if (get_global_multiplicity) {
76*3a10b0eeSJames Wright     PetscCall(VecCeedToPetsc(multiplicity, m_mem_type, Multiplicity_loc));
77*3a10b0eeSJames Wright     PetscCall(DMRestoreLocalVector(dm, &Multiplicity_loc));
78*3a10b0eeSJames Wright     PetscCall(DMRestoreGlobalVector(dm, &Multiplicity));
79*3a10b0eeSJames Wright   }
80*3a10b0eeSJames Wright   PetscCallCeed(ceed, CeedVectorDestroy(&multiplicity));
81*3a10b0eeSJames Wright   PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr));
82*3a10b0eeSJames Wright   PetscCallCeed(ceed, CeedQFunctionDestroy(&qf_multiplicity));
83*3a10b0eeSJames Wright   PetscCallCeed(ceed, CeedOperatorDestroy(&op_multiplicity));
84*3a10b0eeSJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
85*3a10b0eeSJames Wright }
86