ceed-preconditioning.c (fddff3480f915e14d0e1949ec881b24caa5f6f46) ceed-preconditioning.c (edb2538e3dd6743c029967fc4e89c6fcafedb8c2)
1// Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors.
2// All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
3//
4// SPDX-License-Identifier: BSD-2-Clause
5//
6// This file is part of CEED: http://github.com/ceed
7
8#include <ceed-impl.h>

--- 744 unchanged lines hidden (view full) ---

753
754 @param[in] op_fine Fine grid operator
755 @param[in] p_mult_fine L-vector multiplicity in parallel gather/scatter, or NULL if not creating prolongation/restriction operators
756 @param[in] rstr_coarse Coarse grid restriction
757 @param[in] basis_coarse Coarse grid active vector basis
758 @param[in] basis_c_to_f Basis for coarse to fine interpolation, or NULL if not creating prolongation/restriction operators
759 @param[out] op_coarse Coarse grid operator
760 @param[out] op_prolong Coarse to fine operator, or NULL
1// Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors.
2// All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
3//
4// SPDX-License-Identifier: BSD-2-Clause
5//
6// This file is part of CEED: http://github.com/ceed
7
8#include <ceed-impl.h>

--- 744 unchanged lines hidden (view full) ---

753
754 @param[in] op_fine Fine grid operator
755 @param[in] p_mult_fine L-vector multiplicity in parallel gather/scatter, or NULL if not creating prolongation/restriction operators
756 @param[in] rstr_coarse Coarse grid restriction
757 @param[in] basis_coarse Coarse grid active vector basis
758 @param[in] basis_c_to_f Basis for coarse to fine interpolation, or NULL if not creating prolongation/restriction operators
759 @param[out] op_coarse Coarse grid operator
760 @param[out] op_prolong Coarse to fine operator, or NULL
761 @param[out] op_restrict Fine to coarse operator, or NULL
761 @param[out] op_rstrict Fine to coarse operator, or NULL
762
763 @return An error code: 0 - success, otherwise - failure
764
765 @ref Developer
766**/
767static int CeedSingleOperatorMultigridLevel(CeedOperator op_fine, CeedVector p_mult_fine, CeedElemRestriction rstr_coarse, CeedBasis basis_coarse,
762
763 @return An error code: 0 - success, otherwise - failure
764
765 @ref Developer
766**/
767static int CeedSingleOperatorMultigridLevel(CeedOperator op_fine, CeedVector p_mult_fine, CeedElemRestriction rstr_coarse, CeedBasis basis_coarse,
768 CeedBasis basis_c_to_f, CeedOperator *op_coarse, CeedOperator *op_prolong, CeedOperator *op_restrict) {
768 CeedBasis basis_c_to_f, CeedOperator *op_coarse, CeedOperator *op_prolong, CeedOperator *op_rstrict) {
769 bool is_composite;
770 Ceed ceed;
771 CeedInt num_comp;
772 CeedVector mult_vec = NULL;
773 CeedElemRestriction rstr_p_mult_fine = NULL, rstr_fine = NULL;
774
775 CeedCall(CeedOperatorGetCeed(op_fine, &ceed));
776

--- 21 unchanged lines hidden (view full) ---

798 CeedCall(CeedOperatorSetField(*op_coarse, op_fine->output_fields[i]->field_name, op_fine->output_fields[i]->elem_rstr,
799 op_fine->output_fields[i]->basis, op_fine->output_fields[i]->vec));
800 }
801 }
802 // -- Clone QFunctionAssemblyData
803 CeedCall(CeedQFunctionAssemblyDataReferenceCopy(op_fine->qf_assembled, &(*op_coarse)->qf_assembled));
804
805 // Multiplicity vector
769 bool is_composite;
770 Ceed ceed;
771 CeedInt num_comp;
772 CeedVector mult_vec = NULL;
773 CeedElemRestriction rstr_p_mult_fine = NULL, rstr_fine = NULL;
774
775 CeedCall(CeedOperatorGetCeed(op_fine, &ceed));
776

--- 21 unchanged lines hidden (view full) ---

798 CeedCall(CeedOperatorSetField(*op_coarse, op_fine->output_fields[i]->field_name, op_fine->output_fields[i]->elem_rstr,
799 op_fine->output_fields[i]->basis, op_fine->output_fields[i]->vec));
800 }
801 }
802 // -- Clone QFunctionAssemblyData
803 CeedCall(CeedQFunctionAssemblyDataReferenceCopy(op_fine->qf_assembled, &(*op_coarse)->qf_assembled));
804
805 // Multiplicity vector
806 if (op_restrict || op_prolong) {
806 if (op_rstrict || op_prolong) {
807 CeedVector mult_e_vec;
808 CeedRestrictionType rstr_type;
809
810 CeedCall(CeedElemRestrictionGetType(rstr_fine, &rstr_type));
811 CeedCheck(rstr_type != CEED_RESTRICTION_CURL_ORIENTED, ceed, CEED_ERROR_UNSUPPORTED,
812 "Element restrictions created with CeedElemRestrictionCreateCurlOriented are not supported");
813 CeedCheck(p_mult_fine, ceed, CEED_ERROR_INCOMPATIBLE, "Prolongation or restriction operator creation requires fine grid multiplicity vector");
814 CeedCall(CeedElemRestrictionCreateUnsignedCopy(rstr_fine, &rstr_p_mult_fine));

--- 6 unchanged lines hidden (view full) ---

821 CeedCall(CeedVectorReciprocal(mult_vec));
822 }
823
824 // Clone name
825 bool has_name = op_fine->name;
826 size_t name_len = op_fine->name ? strlen(op_fine->name) : 0;
827 CeedCall(CeedOperatorSetName(*op_coarse, op_fine->name));
828
807 CeedVector mult_e_vec;
808 CeedRestrictionType rstr_type;
809
810 CeedCall(CeedElemRestrictionGetType(rstr_fine, &rstr_type));
811 CeedCheck(rstr_type != CEED_RESTRICTION_CURL_ORIENTED, ceed, CEED_ERROR_UNSUPPORTED,
812 "Element restrictions created with CeedElemRestrictionCreateCurlOriented are not supported");
813 CeedCheck(p_mult_fine, ceed, CEED_ERROR_INCOMPATIBLE, "Prolongation or restriction operator creation requires fine grid multiplicity vector");
814 CeedCall(CeedElemRestrictionCreateUnsignedCopy(rstr_fine, &rstr_p_mult_fine));

--- 6 unchanged lines hidden (view full) ---

821 CeedCall(CeedVectorReciprocal(mult_vec));
822 }
823
824 // Clone name
825 bool has_name = op_fine->name;
826 size_t name_len = op_fine->name ? strlen(op_fine->name) : 0;
827 CeedCall(CeedOperatorSetName(*op_coarse, op_fine->name));
828
829 // Check that coarse to fine basis is provided if prolong/restrict operators are requested
830 CeedCheck(basis_c_to_f || (!op_restrict && !op_prolong), ceed, CEED_ERROR_INCOMPATIBLE,
829 // Check that coarse to fine basis is provided if prolong/rstrict operators are requested
830 CeedCheck(basis_c_to_f || (!op_rstrict && !op_prolong), ceed, CEED_ERROR_INCOMPATIBLE,
831 "Prolongation or restriction operator creation requires coarse-to-fine basis");
832
833 // Restriction/Prolongation Operators
834 CeedCall(CeedBasisGetNumComponents(basis_coarse, &num_comp));
835
836 // Restriction
831 "Prolongation or restriction operator creation requires coarse-to-fine basis");
832
833 // Restriction/Prolongation Operators
834 CeedCall(CeedBasisGetNumComponents(basis_coarse, &num_comp));
835
836 // Restriction
837 if (op_restrict) {
837 if (op_rstrict) {
838 CeedInt *num_comp_r_data;
839 CeedQFunctionContext ctx_r;
838 CeedInt *num_comp_r_data;
839 CeedQFunctionContext ctx_r;
840 CeedQFunction qf_restrict;
840 CeedQFunction qf_rstrict;
841
841
842 CeedCall(CeedQFunctionCreateInteriorByName(ceed, "Scale", &qf_restrict));
842 CeedCall(CeedQFunctionCreateInteriorByName(ceed, "Scale", &qf_rstrict));
843 CeedCall(CeedCalloc(1, &num_comp_r_data));
844 num_comp_r_data[0] = num_comp;
845 CeedCall(CeedQFunctionContextCreate(ceed, &ctx_r));
846 CeedCall(CeedQFunctionContextSetData(ctx_r, CEED_MEM_HOST, CEED_OWN_POINTER, sizeof(*num_comp_r_data), num_comp_r_data));
843 CeedCall(CeedCalloc(1, &num_comp_r_data));
844 num_comp_r_data[0] = num_comp;
845 CeedCall(CeedQFunctionContextCreate(ceed, &ctx_r));
846 CeedCall(CeedQFunctionContextSetData(ctx_r, CEED_MEM_HOST, CEED_OWN_POINTER, sizeof(*num_comp_r_data), num_comp_r_data));
847 CeedCall(CeedQFunctionSetContext(qf_restrict, ctx_r));
847 CeedCall(CeedQFunctionSetContext(qf_rstrict, ctx_r));
848 CeedCall(CeedQFunctionContextDestroy(&ctx_r));
848 CeedCall(CeedQFunctionContextDestroy(&ctx_r));
849 CeedCall(CeedQFunctionAddInput(qf_restrict, "input", num_comp, CEED_EVAL_NONE));
850 CeedCall(CeedQFunctionAddInput(qf_restrict, "scale", num_comp, CEED_EVAL_NONE));
851 CeedCall(CeedQFunctionAddOutput(qf_restrict, "output", num_comp, CEED_EVAL_INTERP));
852 CeedCall(CeedQFunctionSetUserFlopsEstimate(qf_restrict, num_comp));
849 CeedCall(CeedQFunctionAddInput(qf_rstrict, "input", num_comp, CEED_EVAL_NONE));
850 CeedCall(CeedQFunctionAddInput(qf_rstrict, "scale", num_comp, CEED_EVAL_NONE));
851 CeedCall(CeedQFunctionAddOutput(qf_rstrict, "output", num_comp, CEED_EVAL_INTERP));
852 CeedCall(CeedQFunctionSetUserFlopsEstimate(qf_rstrict, num_comp));
853
853
854 CeedCall(CeedOperatorCreate(ceed, qf_restrict, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE, op_restrict));
855 CeedCall(CeedOperatorSetField(*op_restrict, "input", rstr_fine, CEED_BASIS_NONE, CEED_VECTOR_ACTIVE));
856 CeedCall(CeedOperatorSetField(*op_restrict, "scale", rstr_p_mult_fine, CEED_BASIS_NONE, mult_vec));
857 CeedCall(CeedOperatorSetField(*op_restrict, "output", rstr_coarse, basis_c_to_f, CEED_VECTOR_ACTIVE));
854 CeedCall(CeedOperatorCreate(ceed, qf_rstrict, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE, op_rstrict));
855 CeedCall(CeedOperatorSetField(*op_rstrict, "input", rstr_fine, CEED_BASIS_NONE, CEED_VECTOR_ACTIVE));
856 CeedCall(CeedOperatorSetField(*op_rstrict, "scale", rstr_p_mult_fine, CEED_BASIS_NONE, mult_vec));
857 CeedCall(CeedOperatorSetField(*op_rstrict, "output", rstr_coarse, basis_c_to_f, CEED_VECTOR_ACTIVE));
858
859 // Set name
860 char *restriction_name;
861
862 CeedCall(CeedCalloc(17 + name_len, &restriction_name));
863 sprintf(restriction_name, "restriction%s%s", has_name ? " for " : "", has_name ? op_fine->name : "");
858
859 // Set name
860 char *restriction_name;
861
862 CeedCall(CeedCalloc(17 + name_len, &restriction_name));
863 sprintf(restriction_name, "restriction%s%s", has_name ? " for " : "", has_name ? op_fine->name : "");
864 CeedCall(CeedOperatorSetName(*op_restrict, restriction_name));
864 CeedCall(CeedOperatorSetName(*op_rstrict, restriction_name));
865 CeedCall(CeedFree(&restriction_name));
866
867 // Check
865 CeedCall(CeedFree(&restriction_name));
866
867 // Check
868 CeedCall(CeedOperatorCheckReady(*op_restrict));
868 CeedCall(CeedOperatorCheckReady(*op_rstrict));
869
870 // Cleanup
869
870 // Cleanup
871 CeedCall(CeedQFunctionDestroy(&qf_restrict));
871 CeedCall(CeedQFunctionDestroy(&qf_rstrict));
872 }
873
874 // Prolongation
875 if (op_prolong) {
876 CeedInt *num_comp_p_data;
877 CeedQFunctionContext ctx_p;
878 CeedQFunction qf_prolong;
879

--- 295 unchanged lines hidden (view full) ---

1175**/
1176int CeedOperatorAssemblyDataCreate(Ceed ceed, CeedOperator op, CeedOperatorAssemblyData *data) {
1177 CeedInt num_active_bases = 0, num_input_fields, *num_eval_modes_in = NULL, *num_eval_modes_out = NULL, offset = 0, num_output_fields;
1178 CeedSize **eval_mode_offsets_in = NULL, **eval_mode_offsets_out = NULL;
1179 CeedEvalMode **eval_modes_in = NULL, **eval_modes_out = NULL;
1180 CeedQFunctionField *qf_fields;
1181 CeedQFunction qf;
1182 CeedOperatorField *op_fields;
872 }
873
874 // Prolongation
875 if (op_prolong) {
876 CeedInt *num_comp_p_data;
877 CeedQFunctionContext ctx_p;
878 CeedQFunction qf_prolong;
879

--- 295 unchanged lines hidden (view full) ---

1175**/
1176int CeedOperatorAssemblyDataCreate(Ceed ceed, CeedOperator op, CeedOperatorAssemblyData *data) {
1177 CeedInt num_active_bases = 0, num_input_fields, *num_eval_modes_in = NULL, *num_eval_modes_out = NULL, offset = 0, num_output_fields;
1178 CeedSize **eval_mode_offsets_in = NULL, **eval_mode_offsets_out = NULL;
1179 CeedEvalMode **eval_modes_in = NULL, **eval_modes_out = NULL;
1180 CeedQFunctionField *qf_fields;
1181 CeedQFunction qf;
1182 CeedOperatorField *op_fields;
1183 bool is_composite;
1184
1183
1185 CeedCall(CeedOperatorIsComposite(op, &is_composite));
1186 CeedCheck(!is_composite, ceed, CEED_ERROR_INCOMPATIBLE, "Can only create CeedOperator assembly data for non-composite operators.");
1187
1188 // Allocate
1189 CeedCall(CeedCalloc(1, data));
1190 (*data)->ceed = ceed;
1191 CeedCall(CeedReference(ceed));
1192
1193 // Build OperatorAssembly data
1194 CeedCall(CeedOperatorGetQFunction(op, &qf));
1195 CeedCall(CeedQFunctionGetFields(qf, &num_input_fields, &qf_fields, NULL, NULL));

--- 582 unchanged lines hidden (view full) ---

1778 CeedCall(CeedCompositeOperatorLinearAssembleAddDiagonal(op, request, false, assembled));
1779 } else {
1780 CeedCall(CeedSingleOperatorAssembleAddDiagonal_Core(op, request, false, assembled));
1781 }
1782 return CEED_ERROR_SUCCESS;
1783}
1784
1785/**
1184 // Allocate
1185 CeedCall(CeedCalloc(1, data));
1186 (*data)->ceed = ceed;
1187 CeedCall(CeedReference(ceed));
1188
1189 // Build OperatorAssembly data
1190 CeedCall(CeedOperatorGetQFunction(op, &qf));
1191 CeedCall(CeedQFunctionGetFields(qf, &num_input_fields, &qf_fields, NULL, NULL));

--- 582 unchanged lines hidden (view full) ---

1774 CeedCall(CeedCompositeOperatorLinearAssembleAddDiagonal(op, request, false, assembled));
1775 } else {
1776 CeedCall(CeedSingleOperatorAssembleAddDiagonal_Core(op, request, false, assembled));
1777 }
1778 return CEED_ERROR_SUCCESS;
1779}
1780
1781/**
1786 @brief Fully assemble the point-block diagonal pattern of a linear operator.
1787
1788 Expected to be used in conjunction with CeedOperatorLinearAssemblePointBlockDiagonal().
1789
1790 The assembly routines use coordinate format, with `num_entries` tuples of the form (i, j, value) which indicate that value should be added to the
1791matrix in entry (i, j).
1792 Note that the (i, j) pairs are unique.
1793 This function returns the number of entries and their (i, j) locations, while CeedOperatorLinearAssemblePointBlockDiagonal() provides the values in
1794the same ordering.
1795
1796 This will generally be slow unless your operator is low-order.
1797
1798 Note: Calling this function asserts that setup is complete and sets the CeedOperator as immutable.
1799
1800 @param[in] op CeedOperator to assemble
1801 @param[out] num_entries Number of entries in coordinate nonzero pattern
1802 @param[out] rows Row number for each entry
1803 @param[out] cols Column number for each entry
1804
1805 @ref User
1806**/
1807int CeedOperatorLinearAssemblePointBlockDiagonalSymbolic(CeedOperator op, CeedSize *num_entries, CeedInt **rows, CeedInt **cols) {
1808 Ceed ceed;
1809 bool is_composite;
1810 CeedInt num_active_components, num_sub_operators;
1811 CeedOperator *sub_operators;
1812
1813 CeedCall(CeedOperatorGetCeed(op, &ceed));
1814 CeedCall(CeedOperatorIsComposite(op, &is_composite));
1815
1816 CeedSize input_size = 0, output_size = 0;
1817 CeedCall(CeedOperatorGetActiveVectorLengths(op, &input_size, &output_size));
1818 CeedCheck(input_size == output_size, ceed, CEED_ERROR_DIMENSION, "Operator must be square");
1819
1820 if (is_composite) {
1821 CeedCall(CeedCompositeOperatorGetNumSub(op, &num_sub_operators));
1822 CeedCall(CeedCompositeOperatorGetSubList(op, &sub_operators));
1823 } else {
1824 sub_operators = &op;
1825 num_sub_operators = 1;
1826 }
1827
1828 { // Verify operator can be assembled correctly
1829 CeedInt num_active_elem_rstrs, comp_stride;
1830 CeedOperatorAssemblyData data;
1831 CeedElemRestriction *active_elem_rstrs;
1832
1833 // Get initial values to check against
1834 CeedCall(CeedOperatorGetOperatorAssemblyData(sub_operators[0], &data));
1835 CeedCall(CeedOperatorAssemblyDataGetElemRestrictions(data, &num_active_elem_rstrs, &active_elem_rstrs));
1836 CeedCall(CeedElemRestrictionGetCompStride(active_elem_rstrs[0], &comp_stride));
1837 CeedCall(CeedElemRestrictionGetNumComponents(active_elem_rstrs[0], &num_active_components));
1838
1839 for (CeedInt k = 0; k < num_sub_operators; k++) {
1840 CeedCall(CeedOperatorGetOperatorAssemblyData(sub_operators[k], &data));
1841
1842 // Verify that all active element restrictions have same component stride and number of components
1843 CeedCall(CeedOperatorAssemblyDataGetElemRestrictions(data, &num_active_elem_rstrs, &active_elem_rstrs));
1844 CeedCall(CeedElemRestrictionGetCompStride(active_elem_rstrs[0], &comp_stride));
1845 for (CeedInt i = 0; i < num_active_elem_rstrs; i++) {
1846 CeedInt comp_stride_sub;
1847 CeedCall(CeedElemRestrictionGetCompStride(active_elem_rstrs[i], &comp_stride_sub));
1848 CeedCheck(comp_stride == comp_stride_sub, ceed, CEED_ERROR_DIMENSION,
1849 "Active element restrictions must have the same component stride: %d vs %d", comp_stride, comp_stride_sub);
1850
1851 CeedInt num_active_components_sub;
1852 CeedCall(CeedElemRestrictionGetNumComponents(active_elem_rstrs[i], &num_active_components_sub));
1853 CeedCheck(num_active_components == num_active_components_sub, ceed, CEED_ERROR_INCOMPATIBLE,
1854 "All suboperators must have the same number of output components");
1855 }
1856 }
1857 }
1858
1859 *num_entries = input_size * num_active_components;
1860 CeedCall(CeedCalloc(*num_entries, rows));
1861 CeedCall(CeedCalloc(*num_entries, cols));
1862
1863 for (CeedInt o = 0; o < num_sub_operators; o++) {
1864 CeedElemRestriction active_elem_rstr, pb_active_elem_rstr;
1865 CeedInt comp_stride, num_elem, elem_size;
1866 const CeedInt *offsets, *pb_offsets;
1867
1868 CeedCall(CeedOperatorGetActiveElemRestriction(sub_operators[o], &active_elem_rstr));
1869 CeedCall(CeedElemRestrictionGetCompStride(active_elem_rstr, &comp_stride));
1870 CeedCall(CeedElemRestrictionGetNumElements(active_elem_rstr, &num_elem));
1871 CeedCall(CeedElemRestrictionGetElementSize(active_elem_rstr, &elem_size));
1872 CeedCall(CeedElemRestrictionGetOffsets(active_elem_rstr, CEED_MEM_HOST, &offsets));
1873
1874 CeedCall(CeedOperatorCreateActivePointBlockRestriction(active_elem_rstr, &pb_active_elem_rstr));
1875 CeedCall(CeedElemRestrictionGetOffsets(pb_active_elem_rstr, CEED_MEM_HOST, &pb_offsets));
1876
1877 for (CeedSize i = 0; i < num_elem * elem_size; i++) {
1878 for (CeedInt c_out = 0; c_out < num_active_components; c_out++) {
1879 for (CeedInt c_in = 0; c_in < num_active_components; c_in++) {
1880 (*rows)[pb_offsets[i] + c_out * num_active_components + c_in] = offsets[i] + c_out * comp_stride;
1881 (*cols)[pb_offsets[i] + c_out * num_active_components + c_in] = offsets[i] + c_in * comp_stride;
1882 }
1883 }
1884 }
1885
1886 CeedCall(CeedElemRestrictionRestoreOffsets(active_elem_rstr, &offsets));
1887 CeedCall(CeedElemRestrictionRestoreOffsets(pb_active_elem_rstr, &pb_offsets));
1888 CeedCall(CeedElemRestrictionDestroy(&pb_active_elem_rstr));
1889 }
1890 return CEED_ERROR_SUCCESS;
1891}
1892
1893/**
1894 @brief Assemble the point block diagonal of a square linear CeedOperator
1895
1896 This overwrites a CeedVector with the point block diagonal of a linear CeedOperator.
1897
1898 Note: Currently only non-composite CeedOperators with a single field and composite CeedOperators with single field sub-operators are supported.
1899
1900 Note: Calling this function asserts that setup is complete and sets the CeedOperator as immutable.
1901

--- 335 unchanged lines hidden (view full) ---

2237 Note: Calling this function asserts that setup is complete and sets all four CeedOperators as immutable.
2238
2239 @param[in] op_fine Fine grid operator
2240 @param[in] p_mult_fine L-vector multiplicity in parallel gather/scatter, or NULL if not creating prolongation/restriction operators
2241 @param[in] rstr_coarse Coarse grid restriction
2242 @param[in] basis_coarse Coarse grid active vector basis
2243 @param[out] op_coarse Coarse grid operator
2244 @param[out] op_prolong Coarse to fine operator, or NULL
1782 @brief Assemble the point block diagonal of a square linear CeedOperator
1783
1784 This overwrites a CeedVector with the point block diagonal of a linear CeedOperator.
1785
1786 Note: Currently only non-composite CeedOperators with a single field and composite CeedOperators with single field sub-operators are supported.
1787
1788 Note: Calling this function asserts that setup is complete and sets the CeedOperator as immutable.
1789

--- 335 unchanged lines hidden (view full) ---

2125 Note: Calling this function asserts that setup is complete and sets all four CeedOperators as immutable.
2126
2127 @param[in] op_fine Fine grid operator
2128 @param[in] p_mult_fine L-vector multiplicity in parallel gather/scatter, or NULL if not creating prolongation/restriction operators
2129 @param[in] rstr_coarse Coarse grid restriction
2130 @param[in] basis_coarse Coarse grid active vector basis
2131 @param[out] op_coarse Coarse grid operator
2132 @param[out] op_prolong Coarse to fine operator, or NULL
2245 @param[out] op_restrict Fine to coarse operator, or NULL
2133 @param[out] op_rstrict Fine to coarse operator, or NULL
2246
2247 @return An error code: 0 - success, otherwise - failure
2248
2249 @ref User
2250**/
2251int CeedOperatorMultigridLevelCreate(CeedOperator op_fine, CeedVector p_mult_fine, CeedElemRestriction rstr_coarse, CeedBasis basis_coarse,
2134
2135 @return An error code: 0 - success, otherwise - failure
2136
2137 @ref User
2138**/
2139int CeedOperatorMultigridLevelCreate(CeedOperator op_fine, CeedVector p_mult_fine, CeedElemRestriction rstr_coarse, CeedBasis basis_coarse,
2252 CeedOperator *op_coarse, CeedOperator *op_prolong, CeedOperator *op_restrict) {
2140 CeedOperator *op_coarse, CeedOperator *op_prolong, CeedOperator *op_rstrict) {
2253 CeedBasis basis_c_to_f = NULL;
2254
2255 CeedCall(CeedOperatorCheckReady(op_fine));
2256
2257 // Build prolongation matrix, if required
2141 CeedBasis basis_c_to_f = NULL;
2142
2143 CeedCall(CeedOperatorCheckReady(op_fine));
2144
2145 // Build prolongation matrix, if required
2258 if (op_prolong || op_restrict) {
2146 if (op_prolong || op_rstrict) {
2259 CeedBasis basis_fine;
2260
2261 CeedCall(CeedOperatorGetActiveBasis(op_fine, &basis_fine));
2262 CeedCall(CeedBasisCreateProjection(basis_coarse, basis_fine, &basis_c_to_f));
2263 }
2264
2265 // Core code
2147 CeedBasis basis_fine;
2148
2149 CeedCall(CeedOperatorGetActiveBasis(op_fine, &basis_fine));
2150 CeedCall(CeedBasisCreateProjection(basis_coarse, basis_fine, &basis_c_to_f));
2151 }
2152
2153 // Core code
2266 CeedCall(CeedSingleOperatorMultigridLevel(op_fine, p_mult_fine, rstr_coarse, basis_coarse, basis_c_to_f, op_coarse, op_prolong, op_restrict));
2154 CeedCall(CeedSingleOperatorMultigridLevel(op_fine, p_mult_fine, rstr_coarse, basis_coarse, basis_c_to_f, op_coarse, op_prolong, op_rstrict));
2267 return CEED_ERROR_SUCCESS;
2268}
2269
2270/**
2271 @brief Create a multigrid coarse operator and level transfer operators for a CeedOperator with a tensor basis for the active basis
2272
2273 Note: Calling this function asserts that setup is complete and sets all four CeedOperators as immutable.
2274
2275 @param[in] op_fine Fine grid operator
2276 @param[in] p_mult_fine L-vector multiplicity in parallel gather/scatter, or NULL if not creating prolongation/restriction operators
2277 @param[in] rstr_coarse Coarse grid restriction
2278 @param[in] basis_coarse Coarse grid active vector basis
2279 @param[in] interp_c_to_f Matrix for coarse to fine interpolation, or NULL if not creating prolongation/restriction operators
2280 @param[out] op_coarse Coarse grid operator
2281 @param[out] op_prolong Coarse to fine operator, or NULL
2155 return CEED_ERROR_SUCCESS;
2156}
2157
2158/**
2159 @brief Create a multigrid coarse operator and level transfer operators for a CeedOperator with a tensor basis for the active basis
2160
2161 Note: Calling this function asserts that setup is complete and sets all four CeedOperators as immutable.
2162
2163 @param[in] op_fine Fine grid operator
2164 @param[in] p_mult_fine L-vector multiplicity in parallel gather/scatter, or NULL if not creating prolongation/restriction operators
2165 @param[in] rstr_coarse Coarse grid restriction
2166 @param[in] basis_coarse Coarse grid active vector basis
2167 @param[in] interp_c_to_f Matrix for coarse to fine interpolation, or NULL if not creating prolongation/restriction operators
2168 @param[out] op_coarse Coarse grid operator
2169 @param[out] op_prolong Coarse to fine operator, or NULL
2282 @param[out] op_restrict Fine to coarse operator, or NULL
2170 @param[out] op_rstrict Fine to coarse operator, or NULL
2283
2284 @return An error code: 0 - success, otherwise - failure
2285
2286 @ref User
2287**/
2288int CeedOperatorMultigridLevelCreateTensorH1(CeedOperator op_fine, CeedVector p_mult_fine, CeedElemRestriction rstr_coarse, CeedBasis basis_coarse,
2289 const CeedScalar *interp_c_to_f, CeedOperator *op_coarse, CeedOperator *op_prolong,
2171
2172 @return An error code: 0 - success, otherwise - failure
2173
2174 @ref User
2175**/
2176int CeedOperatorMultigridLevelCreateTensorH1(CeedOperator op_fine, CeedVector p_mult_fine, CeedElemRestriction rstr_coarse, CeedBasis basis_coarse,
2177 const CeedScalar *interp_c_to_f, CeedOperator *op_coarse, CeedOperator *op_prolong,
2290 CeedOperator *op_restrict) {
2178 CeedOperator *op_rstrict) {
2291 Ceed ceed;
2292 CeedInt Q_f, Q_c;
2293 CeedBasis basis_fine, basis_c_to_f = NULL;
2294
2295 CeedCall(CeedOperatorCheckReady(op_fine));
2296 CeedCall(CeedOperatorGetCeed(op_fine, &ceed));
2297
2298 // Check for compatible quadrature spaces
2299 CeedCall(CeedOperatorGetActiveBasis(op_fine, &basis_fine));
2300 CeedCall(CeedBasisGetNumQuadraturePoints(basis_fine, &Q_f));
2301 CeedCall(CeedBasisGetNumQuadraturePoints(basis_coarse, &Q_c));
2302 CeedCheck(Q_f == Q_c, ceed, CEED_ERROR_DIMENSION, "Bases must have compatible quadrature spaces");
2303
2304 // Create coarse to fine basis, if required
2179 Ceed ceed;
2180 CeedInt Q_f, Q_c;
2181 CeedBasis basis_fine, basis_c_to_f = NULL;
2182
2183 CeedCall(CeedOperatorCheckReady(op_fine));
2184 CeedCall(CeedOperatorGetCeed(op_fine, &ceed));
2185
2186 // Check for compatible quadrature spaces
2187 CeedCall(CeedOperatorGetActiveBasis(op_fine, &basis_fine));
2188 CeedCall(CeedBasisGetNumQuadraturePoints(basis_fine, &Q_f));
2189 CeedCall(CeedBasisGetNumQuadraturePoints(basis_coarse, &Q_c));
2190 CeedCheck(Q_f == Q_c, ceed, CEED_ERROR_DIMENSION, "Bases must have compatible quadrature spaces");
2191
2192 // Create coarse to fine basis, if required
2305 if (op_prolong || op_restrict) {
2193 if (op_prolong || op_rstrict) {
2306 CeedInt dim, num_comp, num_nodes_c, P_1d_f, P_1d_c;
2307 CeedScalar *q_ref, *q_weight, *grad;
2308
2309 // Check if interpolation matrix is provided
2310 CeedCheck(interp_c_to_f, ceed, CEED_ERROR_INCOMPATIBLE,
2311 "Prolongation or restriction operator creation requires coarse-to-fine interpolation matrix");
2312 CeedCall(CeedBasisGetDimension(basis_fine, &dim));
2313 CeedCall(CeedBasisGetNumComponents(basis_fine, &num_comp));

--- 5 unchanged lines hidden (view full) ---

2319 CeedCall(CeedCalloc(P_1d_f * P_1d_c * dim, &grad));
2320 CeedCall(CeedBasisCreateTensorH1(ceed, dim, num_comp, P_1d_c, P_1d_f, interp_c_to_f, grad, q_ref, q_weight, &basis_c_to_f));
2321 CeedCall(CeedFree(&q_ref));
2322 CeedCall(CeedFree(&q_weight));
2323 CeedCall(CeedFree(&grad));
2324 }
2325
2326 // Core code
2194 CeedInt dim, num_comp, num_nodes_c, P_1d_f, P_1d_c;
2195 CeedScalar *q_ref, *q_weight, *grad;
2196
2197 // Check if interpolation matrix is provided
2198 CeedCheck(interp_c_to_f, ceed, CEED_ERROR_INCOMPATIBLE,
2199 "Prolongation or restriction operator creation requires coarse-to-fine interpolation matrix");
2200 CeedCall(CeedBasisGetDimension(basis_fine, &dim));
2201 CeedCall(CeedBasisGetNumComponents(basis_fine, &num_comp));

--- 5 unchanged lines hidden (view full) ---

2207 CeedCall(CeedCalloc(P_1d_f * P_1d_c * dim, &grad));
2208 CeedCall(CeedBasisCreateTensorH1(ceed, dim, num_comp, P_1d_c, P_1d_f, interp_c_to_f, grad, q_ref, q_weight, &basis_c_to_f));
2209 CeedCall(CeedFree(&q_ref));
2210 CeedCall(CeedFree(&q_weight));
2211 CeedCall(CeedFree(&grad));
2212 }
2213
2214 // Core code
2327 CeedCall(CeedSingleOperatorMultigridLevel(op_fine, p_mult_fine, rstr_coarse, basis_coarse, basis_c_to_f, op_coarse, op_prolong, op_restrict));
2215 CeedCall(CeedSingleOperatorMultigridLevel(op_fine, p_mult_fine, rstr_coarse, basis_coarse, basis_c_to_f, op_coarse, op_prolong, op_rstrict));
2328 return CEED_ERROR_SUCCESS;
2329}
2330
2331/**
2332 @brief Create a multigrid coarse operator and level transfer operators for a CeedOperator with a non-tensor basis for the active vector
2333
2334 Note: Calling this function asserts that setup is complete and sets all four CeedOperators as immutable.
2335
2336 @param[in] op_fine Fine grid operator
2337 @param[in] p_mult_fine L-vector multiplicity in parallel gather/scatter, or NULL if not creating prolongation/restriction operators
2338 @param[in] rstr_coarse Coarse grid restriction
2339 @param[in] basis_coarse Coarse grid active vector basis
2340 @param[in] interp_c_to_f Matrix for coarse to fine interpolation, or NULL if not creating prolongation/restriction operators
2341 @param[out] op_coarse Coarse grid operator
2342 @param[out] op_prolong Coarse to fine operator, or NULL
2216 return CEED_ERROR_SUCCESS;
2217}
2218
2219/**
2220 @brief Create a multigrid coarse operator and level transfer operators for a CeedOperator with a non-tensor basis for the active vector
2221
2222 Note: Calling this function asserts that setup is complete and sets all four CeedOperators as immutable.
2223
2224 @param[in] op_fine Fine grid operator
2225 @param[in] p_mult_fine L-vector multiplicity in parallel gather/scatter, or NULL if not creating prolongation/restriction operators
2226 @param[in] rstr_coarse Coarse grid restriction
2227 @param[in] basis_coarse Coarse grid active vector basis
2228 @param[in] interp_c_to_f Matrix for coarse to fine interpolation, or NULL if not creating prolongation/restriction operators
2229 @param[out] op_coarse Coarse grid operator
2230 @param[out] op_prolong Coarse to fine operator, or NULL
2343 @param[out] op_restrict Fine to coarse operator, or NULL
2231 @param[out] op_rstrict Fine to coarse operator, or NULL
2344
2345 @return An error code: 0 - success, otherwise - failure
2346
2347 @ref User
2348**/
2349int CeedOperatorMultigridLevelCreateH1(CeedOperator op_fine, CeedVector p_mult_fine, CeedElemRestriction rstr_coarse, CeedBasis basis_coarse,
2232
2233 @return An error code: 0 - success, otherwise - failure
2234
2235 @ref User
2236**/
2237int CeedOperatorMultigridLevelCreateH1(CeedOperator op_fine, CeedVector p_mult_fine, CeedElemRestriction rstr_coarse, CeedBasis basis_coarse,
2350 const CeedScalar *interp_c_to_f, CeedOperator *op_coarse, CeedOperator *op_prolong,
2351 CeedOperator *op_restrict) {
2238 const CeedScalar *interp_c_to_f, CeedOperator *op_coarse, CeedOperator *op_prolong, CeedOperator *op_rstrict) {
2352 Ceed ceed;
2353 CeedInt Q_f, Q_c;
2354 CeedBasis basis_fine, basis_c_to_f = NULL;
2355
2356 CeedCall(CeedOperatorCheckReady(op_fine));
2357 CeedCall(CeedOperatorGetCeed(op_fine, &ceed));
2358
2359 // Check for compatible quadrature spaces
2360 CeedCall(CeedOperatorGetActiveBasis(op_fine, &basis_fine));
2361 CeedCall(CeedBasisGetNumQuadraturePoints(basis_fine, &Q_f));
2362 CeedCall(CeedBasisGetNumQuadraturePoints(basis_coarse, &Q_c));
2363 CeedCheck(Q_f == Q_c, ceed, CEED_ERROR_DIMENSION, "Bases must have compatible quadrature spaces");
2364
2365 // Coarse to fine basis
2239 Ceed ceed;
2240 CeedInt Q_f, Q_c;
2241 CeedBasis basis_fine, basis_c_to_f = NULL;
2242
2243 CeedCall(CeedOperatorCheckReady(op_fine));
2244 CeedCall(CeedOperatorGetCeed(op_fine, &ceed));
2245
2246 // Check for compatible quadrature spaces
2247 CeedCall(CeedOperatorGetActiveBasis(op_fine, &basis_fine));
2248 CeedCall(CeedBasisGetNumQuadraturePoints(basis_fine, &Q_f));
2249 CeedCall(CeedBasisGetNumQuadraturePoints(basis_coarse, &Q_c));
2250 CeedCheck(Q_f == Q_c, ceed, CEED_ERROR_DIMENSION, "Bases must have compatible quadrature spaces");
2251
2252 // Coarse to fine basis
2366 if (op_prolong || op_restrict) {
2253 if (op_prolong || op_rstrict) {
2367 CeedInt dim, num_comp, num_nodes_c, num_nodes_f;
2368 CeedScalar *q_ref, *q_weight, *grad;
2369 CeedElemTopology topo;
2370
2371 // Check if interpolation matrix is provided
2372 CeedCheck(interp_c_to_f, ceed, CEED_ERROR_INCOMPATIBLE,
2373 "Prolongation or restriction operator creation requires coarse-to-fine interpolation matrix");
2374 CeedCall(CeedBasisGetTopology(basis_fine, &topo));

--- 6 unchanged lines hidden (view full) ---

2381 CeedCall(CeedCalloc(num_nodes_f * num_nodes_c * dim, &grad));
2382 CeedCall(CeedBasisCreateH1(ceed, topo, num_comp, num_nodes_c, num_nodes_f, interp_c_to_f, grad, q_ref, q_weight, &basis_c_to_f));
2383 CeedCall(CeedFree(&q_ref));
2384 CeedCall(CeedFree(&q_weight));
2385 CeedCall(CeedFree(&grad));
2386 }
2387
2388 // Core code
2254 CeedInt dim, num_comp, num_nodes_c, num_nodes_f;
2255 CeedScalar *q_ref, *q_weight, *grad;
2256 CeedElemTopology topo;
2257
2258 // Check if interpolation matrix is provided
2259 CeedCheck(interp_c_to_f, ceed, CEED_ERROR_INCOMPATIBLE,
2260 "Prolongation or restriction operator creation requires coarse-to-fine interpolation matrix");
2261 CeedCall(CeedBasisGetTopology(basis_fine, &topo));

--- 6 unchanged lines hidden (view full) ---

2268 CeedCall(CeedCalloc(num_nodes_f * num_nodes_c * dim, &grad));
2269 CeedCall(CeedBasisCreateH1(ceed, topo, num_comp, num_nodes_c, num_nodes_f, interp_c_to_f, grad, q_ref, q_weight, &basis_c_to_f));
2270 CeedCall(CeedFree(&q_ref));
2271 CeedCall(CeedFree(&q_weight));
2272 CeedCall(CeedFree(&grad));
2273 }
2274
2275 // Core code
2389 CeedCall(CeedSingleOperatorMultigridLevel(op_fine, p_mult_fine, rstr_coarse, basis_coarse, basis_c_to_f, op_coarse, op_prolong, op_restrict));
2276 CeedCall(CeedSingleOperatorMultigridLevel(op_fine, p_mult_fine, rstr_coarse, basis_coarse, basis_c_to_f, op_coarse, op_prolong, op_rstrict));
2390 return CEED_ERROR_SUCCESS;
2391}
2392
2393/**
2394 @brief Build a FDM based approximate inverse for each element for a CeedOperator
2395
2396 This returns a CeedOperator and CeedVector to apply a Fast Diagonalization Method based approximate inverse.
2397 This function obtains the simultaneous diagonalization for the 1D mass and Laplacian operators, \f$M = V^T V, K = V^T S V\f$.

--- 234 unchanged lines hidden ---
2277 return CEED_ERROR_SUCCESS;
2278}
2279
2280/**
2281 @brief Build a FDM based approximate inverse for each element for a CeedOperator
2282
2283 This returns a CeedOperator and CeedVector to apply a Fast Diagonalization Method based approximate inverse.
2284 This function obtains the simultaneous diagonalization for the 1D mass and Laplacian operators, \f$M = V^T V, K = V^T S V\f$.

--- 234 unchanged lines hidden ---