19dbcead6SJeremy L Thompson // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors. 29dbcead6SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 39dbcead6SJeremy L Thompson // 49dbcead6SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause 59dbcead6SJeremy L Thompson // 69dbcead6SJeremy L Thompson // This file is part of CEED: http://github.com/ceed 79dbcead6SJeremy L Thompson 89dbcead6SJeremy L Thompson // libCEED + PETSc DMSwarm Example 99dbcead6SJeremy L Thompson // 109dbcead6SJeremy L Thompson // This example demonstrates a simple usage of libCEED with DMSwarm. 119dbcead6SJeremy L Thompson // This example combines elements of PETSc src/impls/dm/swam/tutorials/ex1.c and src/impls/dm/swarm/tests/ex6.c 129dbcead6SJeremy L Thompson // 139dbcead6SJeremy L Thompson // Build with: 149dbcead6SJeremy L Thompson // 159dbcead6SJeremy L Thompson // make dmswarm [PETSC_DIR=</path/to/petsc>] [CEED_DIR=</path/to/libceed>] 169dbcead6SJeremy L Thompson // 179dbcead6SJeremy L Thompson // Sample runs: 189dbcead6SJeremy L Thompson // 199dbcead6SJeremy L Thompson // ./dmswarm -dm_plex_dim 3 -dm_plex_box_faces 3,3,3 -dm_plex_box_lower -1.0,-1.0,-1.0 -dm_plex_simplex 0 -num_comp 2 -swarm gauss 209dbcead6SJeremy L Thompson // 219dbcead6SJeremy L Thompson //TESTARGS(name="Uniform swarm, CG projection") -ceed {ceed_resource} -test -dm_plex_dim 3 -dm_plex_box_faces 3,3,3 -dm_plex_box_lower -1.0,-1.0,-1.0 -dm_plex_simplex 0 -dm_plex_hash_location true -num_comp 2 -swarm uniform -solution_order 3 -points_per_cell 125 229dbcead6SJeremy L Thompson //TESTARGS(name="Gauss swarm, lumped projection") -ceed {ceed_resource} -test -dm_plex_dim 3 -dm_plex_box_faces 3,3,3 -dm_plex_box_lower -1.0,-1.0,-1.0 -dm_plex_simplex 0 -dm_plex_hash_location true -num_comp 2 -swarm gauss -ksp_type preonly -pc_type jacobi -pc_jacobi_type rowsum -tolerance 9e-2 239dbcead6SJeremy L Thompson 249dbcead6SJeremy L Thompson /// @file 259dbcead6SJeremy L Thompson /// libCEED example using PETSc with DMSwarm 269dbcead6SJeremy L Thompson const char help[] = "libCEED example using PETSc with DMSwarm\n"; 279dbcead6SJeremy L Thompson 289dbcead6SJeremy L Thompson #include <ceed.h> 299dbcead6SJeremy L Thompson #include <math.h> 309dbcead6SJeremy L Thompson #include <petscdmplex.h> 319dbcead6SJeremy L Thompson #include <petscdmswarm.h> 329dbcead6SJeremy L Thompson #include <petscds.h> 339dbcead6SJeremy L Thompson #include <petscfe.h> 349dbcead6SJeremy L Thompson #include <petscksp.h> 359dbcead6SJeremy L Thompson #include <petsc/private/petscfeimpl.h> /* For interpolation */ 369dbcead6SJeremy L Thompson 379dbcead6SJeremy L Thompson #include "include/petscutils.h" 38d31f425aSJeremy L Thompson #include "include/petscversion.h" 399dbcead6SJeremy L Thompson 409dbcead6SJeremy L Thompson const char DMSwarmPICField_u[] = "u"; 419dbcead6SJeremy L Thompson 429dbcead6SJeremy L Thompson // libCEED context data 439dbcead6SJeremy L Thompson typedef struct DMSwarmCeedContext_ *DMSwarmCeedContext; 449dbcead6SJeremy L Thompson struct DMSwarmCeedContext_ { 459dbcead6SJeremy L Thompson Ceed ceed; 469dbcead6SJeremy L Thompson CeedVector u_mesh_loc, v_mesh_loc, u_mesh_elem, u_points_loc, u_points_elem, x_ref_points_loc, x_ref_points_elem; 479dbcead6SJeremy L Thompson CeedElemRestriction restriction_u_mesh, restriction_x_points, restriction_u_points; 489dbcead6SJeremy L Thompson CeedBasis basis_u; 499dbcead6SJeremy L Thompson }; 509dbcead6SJeremy L Thompson 519dbcead6SJeremy L Thompson PetscErrorCode DMSwarmCeedContextCreate(DM dm_swarm, const char *ceed_resource, DMSwarmCeedContext *ctx); 529dbcead6SJeremy L Thompson PetscErrorCode DMSwarmCeedContextDestroy(DMSwarmCeedContext *ctx); 539dbcead6SJeremy L Thompson 549dbcead6SJeremy L Thompson // Target functions 559dbcead6SJeremy L Thompson typedef enum { TARGET_TANH = 0, TARGET_POLYNOMIAL = 1, TARGET_SPHERE = 2 } TargetType; 569dbcead6SJeremy L Thompson static const char *const target_types[] = {"tanh", "polynomial", "sphere", "TargetType", "TARGET", 0}; 579dbcead6SJeremy L Thompson 589dbcead6SJeremy L Thompson typedef PetscErrorCode (*TargetFunc)(PetscInt dim, const PetscScalar x[]); 599dbcead6SJeremy L Thompson typedef PetscErrorCode (*TargetFuncProj)(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx); 609dbcead6SJeremy L Thompson 619dbcead6SJeremy L Thompson PetscScalar EvalU_Tanh(PetscInt dim, const PetscScalar x[]); 629dbcead6SJeremy L Thompson PetscScalar EvalU_Poly(PetscInt dim, const PetscScalar x[]); 639dbcead6SJeremy L Thompson PetscScalar EvalU_Sphere(PetscInt dim, const PetscScalar x[]); 649dbcead6SJeremy L Thompson PetscErrorCode EvalU_Tanh_proj(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt num_comp, PetscScalar *u, void *ctx); 659dbcead6SJeremy L Thompson PetscErrorCode EvalU_Poly_proj(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt num_comp, PetscScalar *u, void *ctx); 669dbcead6SJeremy L Thompson PetscErrorCode EvalU_Sphere_proj(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt num_comp, PetscScalar *u, void *ctx); 679dbcead6SJeremy L Thompson 689dbcead6SJeremy L Thompson // Swarm point distribution 699dbcead6SJeremy L Thompson typedef enum { SWARM_GAUSS = 0, SWARM_UNIFORM = 1, SWARM_CELL_RANDOM = 2, SWARM_SINUSOIDAL = 3 } PointSwarmType; 709dbcead6SJeremy L Thompson static const char *const point_swarm_types[] = {"gauss", "uniform", "cell_random", "sinusoidal", "PointSwarmType", "SWARM", 0}; 719dbcead6SJeremy L Thompson 729dbcead6SJeremy L Thompson // Swarm helper function 739dbcead6SJeremy L Thompson PetscErrorCode DMSwarmInitalizePointLocations(DM dm_swarm, PointSwarmType point_swarm_type, PetscInt num_points, PetscInt num_points_per_cell); 749dbcead6SJeremy L Thompson 759dbcead6SJeremy L Thompson // Memory utilities 769dbcead6SJeremy L Thompson PetscErrorCode VecP2C(Vec X_petsc, PetscMemType *mem_type, CeedVector x_ceed); 779dbcead6SJeremy L Thompson PetscErrorCode VecC2P(CeedVector x_ceed, PetscMemType mem_type, Vec X_petsc); 789dbcead6SJeremy L Thompson PetscErrorCode VecReadP2C(Vec X_petsc, PetscMemType *mem_type, CeedVector x_ceed); 799dbcead6SJeremy L Thompson PetscErrorCode VecReadC2P(CeedVector x_ceed, PetscMemType mem_type, Vec X_petsc); 809dbcead6SJeremy L Thompson PetscErrorCode DMSwarmPICFieldP2C(DM dm_swarm, const char *field, CeedVector x_ceed); 819dbcead6SJeremy L Thompson PetscErrorCode DMSwarmPICFieldC2P(DM dm_swarm, const char *field, CeedVector x_ceed); 829dbcead6SJeremy L Thompson 839dbcead6SJeremy L Thompson // Swarm to mesh and mesh to swarm 849dbcead6SJeremy L Thompson PetscErrorCode DMSwarmCreateReferenceCoordinates(DM dm_swarm, IS *is_points, Vec *ref_coords); 859dbcead6SJeremy L Thompson PetscErrorCode DMSwarmInterpolateFromCellToSwarm_Petsc(DM dm_swarm, const char *field, Vec U_mesh); 869dbcead6SJeremy L Thompson PetscErrorCode DMSwarmInterpolateFromCellToSwarm_Ceed(DM dm_swarm, const char *field, Vec U_mesh); 879dbcead6SJeremy L Thompson PetscErrorCode DMSwarmCheckSwarmValues(DM dm_swarm, const char *field, PetscScalar tolerance, TargetFuncProj TrueSolution); 889dbcead6SJeremy L Thompson 899dbcead6SJeremy L Thompson PetscErrorCode DMSwarmCreateProjectionRHS(DM dm_swarm, const char *field, Vec B_mesh); 909dbcead6SJeremy L Thompson PetscErrorCode MatMult_SwarmMass(Mat A, Vec U_mesh, Vec V_mesh); 919dbcead6SJeremy L Thompson 929dbcead6SJeremy L Thompson // ------------------------------------------------------------------------------------------------ 939dbcead6SJeremy L Thompson // main driver 949dbcead6SJeremy L Thompson // ------------------------------------------------------------------------------------------------ 959dbcead6SJeremy L Thompson int main(int argc, char **argv) { 969dbcead6SJeremy L Thompson MPI_Comm comm; 979dbcead6SJeremy L Thompson char ceed_resource[PETSC_MAX_PATH_LEN] = "/cpu/self"; 989dbcead6SJeremy L Thompson PetscBool test_mode = PETSC_FALSE, view_petsc_swarm = PETSC_FALSE, view_ceed_swarm = PETSC_FALSE; 999dbcead6SJeremy L Thompson PetscInt dim = 3, num_comp = 1, num_points = 1728, num_points_per_cell = 64, mesh_order = 1, solution_order = 2, q_extra = 3; 1009dbcead6SJeremy L Thompson PetscScalar tolerance = 1E-3; 1019dbcead6SJeremy L Thompson DM dm_mesh, dm_swarm; 1029dbcead6SJeremy L Thompson Vec U_mesh; 1039dbcead6SJeremy L Thompson DMSwarmCeedContext swarm_ceed_context; 1049dbcead6SJeremy L Thompson PointSwarmType point_swarm_type = SWARM_UNIFORM; 1059dbcead6SJeremy L Thompson TargetType target_type = TARGET_TANH; 1069dbcead6SJeremy L Thompson TargetFuncProj target_function_proj = EvalU_Tanh_proj; 1079dbcead6SJeremy L Thompson 1089dbcead6SJeremy L Thompson PetscCall(PetscInitialize(&argc, &argv, NULL, help)); 1099dbcead6SJeremy L Thompson comm = PETSC_COMM_WORLD; 1109dbcead6SJeremy L Thompson 1119dbcead6SJeremy L Thompson // Read command line options 1129dbcead6SJeremy L Thompson PetscOptionsBegin(comm, NULL, "libCEED example using PETSc with DMSwarm", NULL); 1139dbcead6SJeremy L Thompson 1149dbcead6SJeremy L Thompson PetscCall(PetscOptionsBool("-test", "Testing mode (do not print unless error is large)", NULL, test_mode, &test_mode, NULL)); 1159dbcead6SJeremy L Thompson PetscCall( 1169dbcead6SJeremy L Thompson PetscOptionsBool("-u_petsc_swarm_view", "View XDMF of swarm values interpolated by PETSc", NULL, view_petsc_swarm, &view_petsc_swarm, NULL)); 1179dbcead6SJeremy L Thompson PetscCall( 1189dbcead6SJeremy L Thompson PetscOptionsBool("-u_ceed_swarm_view", "View XDMF of swarm values interpolated by libCEED", NULL, view_ceed_swarm, &view_ceed_swarm, NULL)); 1199dbcead6SJeremy L Thompson PetscCall(PetscOptionsEnum("-target", "Target field function", NULL, target_types, (PetscEnum)target_type, (PetscEnum *)&target_type, NULL)); 1209dbcead6SJeremy L Thompson PetscCall(PetscOptionsInt("-solution_order", "Order of mesh solution space", NULL, solution_order, &solution_order, NULL)); 1219dbcead6SJeremy L Thompson PetscCall(PetscOptionsInt("-mesh_order", "Order of mesh coordinate space", NULL, mesh_order, &mesh_order, NULL)); 1229dbcead6SJeremy L Thompson PetscCall(PetscOptionsInt("-q_extra", "Number of extra quadrature points", NULL, q_extra, &q_extra, NULL)); 1239dbcead6SJeremy L Thompson PetscCall(PetscOptionsInt("-num_comp", "Number of components in solution", NULL, num_comp, &num_comp, NULL)); 1249dbcead6SJeremy L Thompson PetscCall(PetscOptionsEnum("-swarm", "Swarm points distribution", NULL, point_swarm_types, (PetscEnum)point_swarm_type, 1259dbcead6SJeremy L Thompson (PetscEnum *)&point_swarm_type, NULL)); 1269dbcead6SJeremy L Thompson { 1279dbcead6SJeremy L Thompson PetscBool user_set_num_points_per_cell = PETSC_FALSE; 1289dbcead6SJeremy L Thompson PetscInt dim = 3, num_cells_total = 1; 1299dbcead6SJeremy L Thompson PetscInt num_cells[] = {1, 1, 1}; 1309dbcead6SJeremy L Thompson 1319dbcead6SJeremy L Thompson PetscCall(PetscOptionsInt("-points_per_cell", "Total number of swarm points in each cell", NULL, num_points_per_cell, &num_points_per_cell, 1329dbcead6SJeremy L Thompson &user_set_num_points_per_cell)); 1339dbcead6SJeremy L Thompson PetscCall(PetscOptionsInt("-dm_plex_dim", "Background mesh dimension", NULL, dim, &dim, NULL)); 1349dbcead6SJeremy L Thompson PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of cells", NULL, num_cells, &dim, NULL)); 1359dbcead6SJeremy L Thompson 1369dbcead6SJeremy L Thompson num_cells_total = num_cells[0] * num_cells[1] * num_cells[2]; 1379dbcead6SJeremy L Thompson PetscCheck(!user_set_num_points_per_cell || point_swarm_type != SWARM_SINUSOIDAL, comm, PETSC_ERR_USER, 1389dbcead6SJeremy L Thompson "Cannot specify points per cell with sinusoidal points locations"); 1399dbcead6SJeremy L Thompson if (!user_set_num_points_per_cell) { 1409dbcead6SJeremy L Thompson PetscCall(PetscOptionsInt("-points", "Total number of swarm points", NULL, num_points, &num_points, NULL)); 1419dbcead6SJeremy L Thompson num_points_per_cell = PetscCeilInt(num_points, num_cells_total); 1429dbcead6SJeremy L Thompson } 1439dbcead6SJeremy L Thompson if (point_swarm_type != SWARM_SINUSOIDAL) { 1449dbcead6SJeremy L Thompson PetscInt num_points_per_cell_1d = round(cbrt(num_points_per_cell * 1.0)); 1459dbcead6SJeremy L Thompson 1469dbcead6SJeremy L Thompson num_points_per_cell = 1; 1479dbcead6SJeremy L Thompson for (PetscInt i = 0; i < dim; i++) num_points_per_cell *= num_points_per_cell_1d; 1489dbcead6SJeremy L Thompson } 1499dbcead6SJeremy L Thompson num_points = num_points_per_cell * num_cells_total; 1509dbcead6SJeremy L Thompson } 1519dbcead6SJeremy L Thompson PetscCall(PetscOptionsScalar("-tolerance", "Tolerance for swarm point values and projection relative L2 error", NULL, tolerance, &tolerance, NULL)); 1529dbcead6SJeremy L Thompson PetscCall(PetscOptionsString("-ceed", "CEED resource specifier", NULL, ceed_resource, ceed_resource, sizeof(ceed_resource), NULL)); 1539dbcead6SJeremy L Thompson 1549dbcead6SJeremy L Thompson PetscOptionsEnd(); 1559dbcead6SJeremy L Thompson 1569dbcead6SJeremy L Thompson // Create background mesh 1579dbcead6SJeremy L Thompson { 1589dbcead6SJeremy L Thompson PetscCall(DMCreate(comm, &dm_mesh)); 1599dbcead6SJeremy L Thompson PetscCall(DMSetType(dm_mesh, DMPLEX)); 1609dbcead6SJeremy L Thompson PetscCall(DMSetFromOptions(dm_mesh)); 1619dbcead6SJeremy L Thompson 1629dbcead6SJeremy L Thompson // -- Check for tensor product mesh 1639dbcead6SJeremy L Thompson { 1649dbcead6SJeremy L Thompson PetscBool is_simplex; 1659dbcead6SJeremy L Thompson 1669dbcead6SJeremy L Thompson PetscCall(DMPlexIsSimplex(dm_mesh, &is_simplex)); 1679dbcead6SJeremy L Thompson PetscCheck(!is_simplex, comm, PETSC_ERR_USER, "Only tensor-product background meshes supported"); 1689dbcead6SJeremy L Thompson } 1699dbcead6SJeremy L Thompson 1709dbcead6SJeremy L Thompson // -- Mesh FE space 1719dbcead6SJeremy L Thompson PetscCall(DMGetDimension(dm_mesh, &dim)); 1729dbcead6SJeremy L Thompson { 1739dbcead6SJeremy L Thompson PetscFE fe; 1749dbcead6SJeremy L Thompson 1759dbcead6SJeremy L Thompson PetscCall(DMGetDimension(dm_mesh, &dim)); 1769dbcead6SJeremy L Thompson PetscCall(PetscFECreateLagrange(comm, dim, num_comp, PETSC_FALSE, solution_order, solution_order + q_extra, &fe)); 1779dbcead6SJeremy L Thompson PetscCall(DMAddField(dm_mesh, NULL, (PetscObject)fe)); 1789dbcead6SJeremy L Thompson PetscCall(PetscFEDestroy(&fe)); 1799dbcead6SJeremy L Thompson } 1809dbcead6SJeremy L Thompson PetscCall(DMCreateDS(dm_mesh)); 1819dbcead6SJeremy L Thompson 1829dbcead6SJeremy L Thompson // -- Coordinate FE space 1839dbcead6SJeremy L Thompson { 1849dbcead6SJeremy L Thompson PetscFE fe_coord; 1859dbcead6SJeremy L Thompson 1869dbcead6SJeremy L Thompson PetscCall(PetscFECreateLagrange(comm, dim, dim, PETSC_FALSE, mesh_order, solution_order + q_extra, &fe_coord)); 187*49a40c8aSKenneth E. Jansen PetscCall(DMSetCoordinateDisc(dm_mesh, fe_coord, PETSC_TRUE)); 1889dbcead6SJeremy L Thompson PetscCall(PetscFEDestroy(&fe_coord)); 1899dbcead6SJeremy L Thompson } 1909dbcead6SJeremy L Thompson 1919dbcead6SJeremy L Thompson // -- Set tensor permutation 1929dbcead6SJeremy L Thompson { 1939dbcead6SJeremy L Thompson DM dm_coord; 1949dbcead6SJeremy L Thompson 1959dbcead6SJeremy L Thompson PetscCall(DMGetCoordinateDM(dm_mesh, &dm_coord)); 1969dbcead6SJeremy L Thompson PetscCall(DMPlexSetClosurePermutationTensor(dm_mesh, PETSC_DETERMINE, NULL)); 1979dbcead6SJeremy L Thompson PetscCall(DMPlexSetClosurePermutationTensor(dm_coord, PETSC_DETERMINE, NULL)); 1989dbcead6SJeremy L Thompson } 1999dbcead6SJeremy L Thompson 2009dbcead6SJeremy L Thompson // -- Final background mesh 2019dbcead6SJeremy L Thompson PetscCall(PetscObjectSetName((PetscObject)dm_mesh, "Background Mesh")); 2029dbcead6SJeremy L Thompson PetscCall(DMViewFromOptions(dm_mesh, NULL, "-dm_mesh_view")); 2039dbcead6SJeremy L Thompson } 2049dbcead6SJeremy L Thompson 2059dbcead6SJeremy L Thompson // Create particle swarm 2069dbcead6SJeremy L Thompson { 2079dbcead6SJeremy L Thompson PetscCall(DMCreate(comm, &dm_swarm)); 2089dbcead6SJeremy L Thompson PetscCall(DMSetType(dm_swarm, DMSWARM)); 2099dbcead6SJeremy L Thompson PetscCall(DMSetDimension(dm_swarm, dim)); 2109dbcead6SJeremy L Thompson PetscCall(DMSwarmSetType(dm_swarm, DMSWARM_PIC)); 2119dbcead6SJeremy L Thompson PetscCall(DMSwarmSetCellDM(dm_swarm, dm_mesh)); 2129dbcead6SJeremy L Thompson 2139dbcead6SJeremy L Thompson // -- Swarm field 2149dbcead6SJeremy L Thompson PetscCall(DMSwarmRegisterPetscDatatypeField(dm_swarm, DMSwarmPICField_u, num_comp, PETSC_SCALAR)); 2159dbcead6SJeremy L Thompson PetscCall(DMSwarmFinalizeFieldRegister(dm_swarm)); 2169dbcead6SJeremy L Thompson PetscCall(DMSwarmSetLocalSizes(dm_swarm, num_points, 0)); 2179dbcead6SJeremy L Thompson PetscCall(DMSetFromOptions(dm_swarm)); 2189dbcead6SJeremy L Thompson 2199dbcead6SJeremy L Thompson // -- Set swarm point locations 2209dbcead6SJeremy L Thompson PetscCall(DMSwarmInitalizePointLocations(dm_swarm, point_swarm_type, num_points, num_points_per_cell)); 2219dbcead6SJeremy L Thompson 2229dbcead6SJeremy L Thompson // -- Final particle swarm 2239dbcead6SJeremy L Thompson PetscCall(PetscObjectSetName((PetscObject)dm_swarm, "Particle Swarm")); 2249dbcead6SJeremy L Thompson PetscCall(DMViewFromOptions(dm_swarm, NULL, "-dm_swarm_view")); 2259dbcead6SJeremy L Thompson } 2269dbcead6SJeremy L Thompson 2279dbcead6SJeremy L Thompson // Set field values on background mesh 2289dbcead6SJeremy L Thompson PetscCall(DMCreateGlobalVector(dm_mesh, &U_mesh)); 2299dbcead6SJeremy L Thompson switch (target_type) { 2309dbcead6SJeremy L Thompson case TARGET_TANH: 2319dbcead6SJeremy L Thompson target_function_proj = EvalU_Tanh_proj; 2329dbcead6SJeremy L Thompson break; 2339dbcead6SJeremy L Thompson case TARGET_POLYNOMIAL: 2349dbcead6SJeremy L Thompson target_function_proj = EvalU_Poly_proj; 2359dbcead6SJeremy L Thompson break; 2369dbcead6SJeremy L Thompson case TARGET_SPHERE: 2379dbcead6SJeremy L Thompson target_function_proj = EvalU_Sphere_proj; 2389dbcead6SJeremy L Thompson break; 2399dbcead6SJeremy L Thompson } 2409dbcead6SJeremy L Thompson { 2419dbcead6SJeremy L Thompson TargetFuncProj mesh_solution[1] = {target_function_proj}; 2429dbcead6SJeremy L Thompson 2439dbcead6SJeremy L Thompson PetscCall(DMProjectFunction(dm_mesh, 0.0, mesh_solution, NULL, INSERT_VALUES, U_mesh)); 2449dbcead6SJeremy L Thompson } 2459dbcead6SJeremy L Thompson 2469dbcead6SJeremy L Thompson // Visualize background mesh 2479dbcead6SJeremy L Thompson PetscCall(PetscObjectSetName((PetscObject)U_mesh, "U on Background Mesh")); 2489dbcead6SJeremy L Thompson PetscCall(VecViewFromOptions(U_mesh, NULL, "-u_mesh_view")); 2499dbcead6SJeremy L Thompson 2509dbcead6SJeremy L Thompson // libCEED objects for swarm and background mesh 2519dbcead6SJeremy L Thompson PetscCall(DMSwarmCeedContextCreate(dm_swarm, ceed_resource, &swarm_ceed_context)); 2529dbcead6SJeremy L Thompson 2539dbcead6SJeremy L Thompson // Interpolate from mesh to points via PETSc 2549dbcead6SJeremy L Thompson { 2559dbcead6SJeremy L Thompson PetscCall(DMSwarmInterpolateFromCellToSwarm_Petsc(dm_swarm, DMSwarmPICField_u, U_mesh)); 2569dbcead6SJeremy L Thompson if (view_petsc_swarm) PetscCall(DMSwarmViewXDMF(dm_swarm, "swarm_petsc.xmf")); 2579dbcead6SJeremy L Thompson PetscCall(DMSwarmCheckSwarmValues(dm_swarm, DMSwarmPICField_u, tolerance, target_function_proj)); 2589dbcead6SJeremy L Thompson } 2599dbcead6SJeremy L Thompson 2609dbcead6SJeremy L Thompson // Interpolate from mesh to points via libCEED 2619dbcead6SJeremy L Thompson { 2629dbcead6SJeremy L Thompson PetscCall(DMSwarmInterpolateFromCellToSwarm_Ceed(dm_swarm, DMSwarmPICField_u, U_mesh)); 2639dbcead6SJeremy L Thompson if (view_ceed_swarm) PetscCall(DMSwarmViewXDMF(dm_swarm, "swarm_ceed.xmf")); 2649dbcead6SJeremy L Thompson PetscCall(DMSwarmCheckSwarmValues(dm_swarm, DMSwarmPICField_u, tolerance, target_function_proj)); 2659dbcead6SJeremy L Thompson } 2669dbcead6SJeremy L Thompson 2679dbcead6SJeremy L Thompson // Project from points to mesh via libCEED 2689dbcead6SJeremy L Thompson { 2699dbcead6SJeremy L Thompson Vec B_mesh, U_projected; 2709dbcead6SJeremy L Thompson Mat M; 2719dbcead6SJeremy L Thompson KSP ksp; 2729dbcead6SJeremy L Thompson 2739dbcead6SJeremy L Thompson PetscCall(VecDuplicate(U_mesh, &B_mesh)); 2749dbcead6SJeremy L Thompson PetscCall(VecDuplicate(U_mesh, &U_projected)); 2759dbcead6SJeremy L Thompson 2769dbcead6SJeremy L Thompson // -- Setup "mass matrix" 2779dbcead6SJeremy L Thompson { 2789dbcead6SJeremy L Thompson PetscInt l_size, g_size; 2799dbcead6SJeremy L Thompson 2809dbcead6SJeremy L Thompson PetscCall(VecGetLocalSize(U_mesh, &l_size)); 2819dbcead6SJeremy L Thompson PetscCall(VecGetSize(U_mesh, &g_size)); 2829dbcead6SJeremy L Thompson PetscCall(MatCreateShell(comm, l_size, l_size, g_size, g_size, swarm_ceed_context, &M)); 2839dbcead6SJeremy L Thompson PetscCall(MatSetDM(M, dm_mesh)); 2849dbcead6SJeremy L Thompson PetscCall(MatShellSetOperation(M, MATOP_MULT, (void (*)(void))MatMult_SwarmMass)); 2859dbcead6SJeremy L Thompson } 2869dbcead6SJeremy L Thompson 2879dbcead6SJeremy L Thompson // -- Setup KSP 2889dbcead6SJeremy L Thompson { 2899dbcead6SJeremy L Thompson PC pc; 2909dbcead6SJeremy L Thompson 2919dbcead6SJeremy L Thompson PetscCall(KSPCreate(comm, &ksp)); 2929dbcead6SJeremy L Thompson PetscCall(KSPGetPC(ksp, &pc)); 2939dbcead6SJeremy L Thompson PetscCall(PCSetType(pc, PCJACOBI)); 2949dbcead6SJeremy L Thompson PetscCall(PCJacobiSetType(pc, PC_JACOBI_ROWSUM)); 2959dbcead6SJeremy L Thompson PetscCall(KSPSetType(ksp, KSPCG)); 2969dbcead6SJeremy L Thompson PetscCall(KSPSetNormType(ksp, KSP_NORM_NATURAL)); 2979dbcead6SJeremy L Thompson PetscCall(KSPSetTolerances(ksp, 1e-10, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT)); 2989dbcead6SJeremy L Thompson PetscCall(KSPSetOperators(ksp, M, M)); 2999dbcead6SJeremy L Thompson PetscCall(KSPSetFromOptions(ksp)); 3009dbcead6SJeremy L Thompson PetscCall(PetscObjectSetName((PetscObject)ksp, "Swarm-to-Mesh Projection")); 3019dbcead6SJeremy L Thompson PetscCall(KSPViewFromOptions(ksp, NULL, "-ksp_projection_view")); 3029dbcead6SJeremy L Thompson } 3039dbcead6SJeremy L Thompson 3049dbcead6SJeremy L Thompson // -- Setup RHS 3059dbcead6SJeremy L Thompson PetscCall(DMSwarmCreateProjectionRHS(dm_swarm, DMSwarmPICField_u, B_mesh)); 3069dbcead6SJeremy L Thompson 3079dbcead6SJeremy L Thompson // -- Solve 3089dbcead6SJeremy L Thompson PetscCall(VecZeroEntries(U_projected)); 3099dbcead6SJeremy L Thompson PetscCall(KSPSolve(ksp, B_mesh, U_projected)); 3109dbcead6SJeremy L Thompson 3119dbcead6SJeremy L Thompson // -- KSP summary 3129dbcead6SJeremy L Thompson { 3139dbcead6SJeremy L Thompson KSPType ksp_type; 3149dbcead6SJeremy L Thompson KSPConvergedReason reason; 3159dbcead6SJeremy L Thompson PetscReal rnorm; 3169dbcead6SJeremy L Thompson PetscInt its; 3179dbcead6SJeremy L Thompson PetscCall(KSPGetType(ksp, &ksp_type)); 3189dbcead6SJeremy L Thompson PetscCall(KSPGetConvergedReason(ksp, &reason)); 3199dbcead6SJeremy L Thompson PetscCall(KSPGetIterationNumber(ksp, &its)); 3209dbcead6SJeremy L Thompson PetscCall(KSPGetResidualNorm(ksp, &rnorm)); 3219dbcead6SJeremy L Thompson 3229dbcead6SJeremy L Thompson if (!test_mode || reason < 0 || rnorm > 1e-8) { 3239dbcead6SJeremy L Thompson PetscCall(PetscPrintf(comm, 3249dbcead6SJeremy L Thompson "Swarm-to-Mesh Projection KSP Solve:\n" 3259dbcead6SJeremy L Thompson " KSP type: %s\n" 3269dbcead6SJeremy L Thompson " KSP convergence: %s\n" 3279dbcead6SJeremy L Thompson " Total KSP iterations: %" PetscInt_FMT "\n" 3289dbcead6SJeremy L Thompson " Final rnorm: %e\n", 3299dbcead6SJeremy L Thompson ksp_type, KSPConvergedReasons[reason], its, (double)rnorm)); 3309dbcead6SJeremy L Thompson } 3319dbcead6SJeremy L Thompson } 3329dbcead6SJeremy L Thompson 3339dbcead6SJeremy L Thompson // -- Check error 3349dbcead6SJeremy L Thompson PetscCall(KSPViewFromOptions(ksp, NULL, "-ksp_view")); 3359dbcead6SJeremy L Thompson PetscCall(PetscObjectSetName((PetscObject)U_mesh, "U projected to Background Mesh")); 3369dbcead6SJeremy L Thompson PetscCall(VecViewFromOptions(U_projected, NULL, "-u_projected_view")); 3379dbcead6SJeremy L Thompson PetscCall(VecAXPY(U_projected, -1.0, U_mesh)); 3389dbcead6SJeremy L Thompson PetscCall(PetscObjectSetName((PetscObject)U_projected, "U Projection Error")); 3399dbcead6SJeremy L Thompson PetscCall(VecViewFromOptions(U_projected, NULL, "-u_error_view")); 3409dbcead6SJeremy L Thompson { 3419dbcead6SJeremy L Thompson PetscScalar error, norm_u_mesh; 3429dbcead6SJeremy L Thompson 3439dbcead6SJeremy L Thompson PetscCall(VecNorm(U_projected, NORM_2, &error)); 3449dbcead6SJeremy L Thompson PetscCall(VecNorm(U_mesh, NORM_2, &norm_u_mesh)); 3459dbcead6SJeremy L Thompson PetscCheck(error / norm_u_mesh < tolerance, comm, PETSC_ERR_USER, "Projection error too high: %e\n", error / norm_u_mesh); 3469dbcead6SJeremy L Thompson if (!test_mode) PetscCall(PetscPrintf(comm, " Projection error: %e\n", error / norm_u_mesh)); 3479dbcead6SJeremy L Thompson } 3489dbcead6SJeremy L Thompson 3499dbcead6SJeremy L Thompson // -- Cleanup 3509dbcead6SJeremy L Thompson PetscCall(VecDestroy(&B_mesh)); 3519dbcead6SJeremy L Thompson PetscCall(VecDestroy(&U_projected)); 3529dbcead6SJeremy L Thompson PetscCall(MatDestroy(&M)); 3539dbcead6SJeremy L Thompson PetscCall(KSPDestroy(&ksp)); 3549dbcead6SJeremy L Thompson } 3559dbcead6SJeremy L Thompson 3569dbcead6SJeremy L Thompson // Cleanup 3579dbcead6SJeremy L Thompson PetscCall(DMSwarmCeedContextDestroy(&swarm_ceed_context)); 3589dbcead6SJeremy L Thompson PetscCall(DMDestroy(&dm_swarm)); 3599dbcead6SJeremy L Thompson PetscCall(DMDestroy(&dm_mesh)); 3609dbcead6SJeremy L Thompson PetscCall(VecDestroy(&U_mesh)); 3619dbcead6SJeremy L Thompson return PetscFinalize(); 3629dbcead6SJeremy L Thompson } 3639dbcead6SJeremy L Thompson 3649dbcead6SJeremy L Thompson // ------------------------------------------------------------------------------------------------ 3659dbcead6SJeremy L Thompson // Context utilities 3669dbcead6SJeremy L Thompson // ------------------------------------------------------------------------------------------------ 3679dbcead6SJeremy L Thompson PetscErrorCode DMSwarmCeedContextCreate(DM dm_swarm, const char *ceed_resource, DMSwarmCeedContext *ctx) { 3689dbcead6SJeremy L Thompson DM dm_mesh; 3699dbcead6SJeremy L Thompson 3709dbcead6SJeremy L Thompson PetscFunctionBeginUser; 3719dbcead6SJeremy L Thompson PetscCall(PetscNew(ctx)); 3729dbcead6SJeremy L Thompson PetscCall(DMSwarmGetCellDM(dm_swarm, &dm_mesh)); 3739dbcead6SJeremy L Thompson 3749dbcead6SJeremy L Thompson CeedInit(ceed_resource, &(*ctx)->ceed); 3759dbcead6SJeremy L Thompson // Background mesh objects 3769dbcead6SJeremy L Thompson { 3779dbcead6SJeremy L Thompson CeedInt elem_size, num_comp; 3789dbcead6SJeremy L Thompson BPData bp_data = {.q_mode = CEED_GAUSS}; 3799dbcead6SJeremy L Thompson 3809dbcead6SJeremy L Thompson PetscCall(CreateBasisFromPlex((*ctx)->ceed, dm_mesh, NULL, 0, 0, 0, bp_data, &(*ctx)->basis_u)); 3819dbcead6SJeremy L Thompson PetscCall(CreateRestrictionFromPlex((*ctx)->ceed, dm_mesh, 0, NULL, 0, &(*ctx)->restriction_u_mesh)); 3829dbcead6SJeremy L Thompson 3839dbcead6SJeremy L Thompson // -- U vector 3849dbcead6SJeremy L Thompson CeedElemRestrictionCreateVector((*ctx)->restriction_u_mesh, &(*ctx)->u_mesh_loc, NULL); 3859dbcead6SJeremy L Thompson CeedElemRestrictionCreateVector((*ctx)->restriction_u_mesh, &(*ctx)->v_mesh_loc, NULL); 3869dbcead6SJeremy L Thompson CeedElemRestrictionGetElementSize((*ctx)->restriction_u_mesh, &elem_size); 3879dbcead6SJeremy L Thompson CeedElemRestrictionGetNumComponents((*ctx)->restriction_u_mesh, &num_comp); 3889dbcead6SJeremy L Thompson CeedVectorCreate((*ctx)->ceed, elem_size * num_comp, &(*ctx)->u_mesh_elem); 3899dbcead6SJeremy L Thompson } 3909dbcead6SJeremy L Thompson // Swarm objects 3919dbcead6SJeremy L Thompson { 3929dbcead6SJeremy L Thompson PetscInt dim; 3939dbcead6SJeremy L Thompson const PetscInt *cell_points; 3949dbcead6SJeremy L Thompson IS is_points; 3959dbcead6SJeremy L Thompson Vec X_ref; 3969dbcead6SJeremy L Thompson CeedInt num_elem, num_comp, max_points_in_cell; 3979dbcead6SJeremy L Thompson 3989dbcead6SJeremy L Thompson PetscCall(DMSwarmCreateReferenceCoordinates(dm_swarm, &is_points, &X_ref)); 3999dbcead6SJeremy L Thompson PetscCall(DMGetDimension(dm_mesh, &dim)); 4009dbcead6SJeremy L Thompson CeedElemRestrictionGetNumElements((*ctx)->restriction_u_mesh, &num_elem); 4019dbcead6SJeremy L Thompson CeedElemRestrictionGetNumComponents((*ctx)->restriction_u_mesh, &num_comp); 4029dbcead6SJeremy L Thompson 4039dbcead6SJeremy L Thompson PetscCall(ISGetIndices(is_points, &cell_points)); 4049dbcead6SJeremy L Thompson PetscInt num_points = cell_points[num_elem + 1] - num_elem - 2; 4059dbcead6SJeremy L Thompson CeedInt offsets[num_elem + 1 + num_points]; 4069dbcead6SJeremy L Thompson 4079dbcead6SJeremy L Thompson for (PetscInt i = 0; i < num_elem + 1; i++) offsets[i] = cell_points[i + 1] - 1; 4089dbcead6SJeremy L Thompson for (PetscInt i = num_elem + 1; i < num_points + num_elem + 1; i++) offsets[i] = cell_points[i + 1]; 4099dbcead6SJeremy L Thompson PetscCall(ISRestoreIndices(is_points, &cell_points)); 4109dbcead6SJeremy L Thompson 4119dbcead6SJeremy L Thompson // -- Points restrictions 4129dbcead6SJeremy L Thompson CeedElemRestrictionCreateAtPoints((*ctx)->ceed, num_elem, num_points, num_comp, num_points * num_comp, CEED_MEM_HOST, CEED_COPY_VALUES, offsets, 4139dbcead6SJeremy L Thompson &(*ctx)->restriction_u_points); 4149dbcead6SJeremy L Thompson CeedElemRestrictionCreateAtPoints((*ctx)->ceed, num_elem, num_points, dim, num_points * dim, CEED_MEM_HOST, CEED_COPY_VALUES, offsets, 4159dbcead6SJeremy L Thompson &(*ctx)->restriction_x_points); 4169dbcead6SJeremy L Thompson 4179dbcead6SJeremy L Thompson // -- U vector 4189dbcead6SJeremy L Thompson CeedElemRestrictionGetMaxPointsInElement((*ctx)->restriction_u_points, &max_points_in_cell); 4199dbcead6SJeremy L Thompson CeedElemRestrictionCreateVector((*ctx)->restriction_u_points, &(*ctx)->u_points_loc, NULL); 4209dbcead6SJeremy L Thompson CeedVectorCreate((*ctx)->ceed, max_points_in_cell * num_comp, &(*ctx)->u_points_elem); 4219dbcead6SJeremy L Thompson 4229dbcead6SJeremy L Thompson // -- Ref coordinates 4239dbcead6SJeremy L Thompson { 4249dbcead6SJeremy L Thompson PetscMemType X_mem_type; 4259dbcead6SJeremy L Thompson const PetscScalar *x; 4269dbcead6SJeremy L Thompson 4279dbcead6SJeremy L Thompson CeedVectorCreate((*ctx)->ceed, num_points * dim, &(*ctx)->x_ref_points_loc); 4289dbcead6SJeremy L Thompson CeedVectorCreate((*ctx)->ceed, max_points_in_cell * dim, &(*ctx)->x_ref_points_elem); 4299dbcead6SJeremy L Thompson 4309dbcead6SJeremy L Thompson PetscCall(VecGetArrayReadAndMemType(X_ref, (const PetscScalar **)&x, &X_mem_type)); 4319dbcead6SJeremy L Thompson CeedVectorSetArray((*ctx)->x_ref_points_loc, MemTypeP2C(X_mem_type), CEED_COPY_VALUES, (CeedScalar *)x); 4329dbcead6SJeremy L Thompson PetscCall(VecRestoreArrayReadAndMemType(X_ref, (const PetscScalar **)&x)); 4339dbcead6SJeremy L Thompson } 4349dbcead6SJeremy L Thompson 4359dbcead6SJeremy L Thompson // -- Cleanup 4369dbcead6SJeremy L Thompson PetscCall(ISDestroy(&is_points)); 4379dbcead6SJeremy L Thompson PetscCall(VecDestroy(&X_ref)); 4389dbcead6SJeremy L Thompson } 4399dbcead6SJeremy L Thompson 4409dbcead6SJeremy L Thompson PetscCall(DMSetApplicationContext(dm_mesh, (void *)(*ctx))); 4419dbcead6SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 4429dbcead6SJeremy L Thompson } 4439dbcead6SJeremy L Thompson 4449dbcead6SJeremy L Thompson PetscErrorCode DMSwarmCeedContextDestroy(DMSwarmCeedContext *ctx) { 4459dbcead6SJeremy L Thompson PetscFunctionBeginUser; 4469dbcead6SJeremy L Thompson CeedDestroy(&(*ctx)->ceed); 4479dbcead6SJeremy L Thompson CeedVectorDestroy(&(*ctx)->u_mesh_loc); 4489dbcead6SJeremy L Thompson CeedVectorDestroy(&(*ctx)->v_mesh_loc); 4499dbcead6SJeremy L Thompson CeedVectorDestroy(&(*ctx)->u_mesh_elem); 4509dbcead6SJeremy L Thompson CeedVectorDestroy(&(*ctx)->u_points_loc); 4519dbcead6SJeremy L Thompson CeedVectorDestroy(&(*ctx)->u_points_elem); 4529dbcead6SJeremy L Thompson CeedVectorDestroy(&(*ctx)->x_ref_points_loc); 4539dbcead6SJeremy L Thompson CeedVectorDestroy(&(*ctx)->x_ref_points_elem); 4549dbcead6SJeremy L Thompson CeedElemRestrictionDestroy(&(*ctx)->restriction_u_mesh); 4559dbcead6SJeremy L Thompson CeedElemRestrictionDestroy(&(*ctx)->restriction_x_points); 4569dbcead6SJeremy L Thompson CeedElemRestrictionDestroy(&(*ctx)->restriction_u_points); 4579dbcead6SJeremy L Thompson CeedBasisDestroy(&(*ctx)->basis_u); 4589dbcead6SJeremy L Thompson PetscCall(PetscFree(*ctx)); 4599dbcead6SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 4609dbcead6SJeremy L Thompson } 4619dbcead6SJeremy L Thompson 4629dbcead6SJeremy L Thompson // ------------------------------------------------------------------------------------------------ 4639dbcead6SJeremy L Thompson // PETSc-libCEED memory space utilities 4649dbcead6SJeremy L Thompson // ------------------------------------------------------------------------------------------------ 4659dbcead6SJeremy L Thompson PetscErrorCode VecP2C(Vec X_petsc, PetscMemType *mem_type, CeedVector x_ceed) { 4669dbcead6SJeremy L Thompson PetscScalar *x; 4679dbcead6SJeremy L Thompson 4689dbcead6SJeremy L Thompson PetscFunctionBeginUser; 4699dbcead6SJeremy L Thompson PetscCall(VecGetArrayAndMemType(X_petsc, &x, mem_type)); 4709dbcead6SJeremy L Thompson CeedVectorSetArray(x_ceed, MemTypeP2C(*mem_type), CEED_USE_POINTER, x); 4719dbcead6SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 4729dbcead6SJeremy L Thompson } 4739dbcead6SJeremy L Thompson 4749dbcead6SJeremy L Thompson PetscErrorCode VecC2P(CeedVector x_ceed, PetscMemType mem_type, Vec X_petsc) { 4759dbcead6SJeremy L Thompson PetscScalar *x; 4769dbcead6SJeremy L Thompson 4779dbcead6SJeremy L Thompson PetscFunctionBeginUser; 4789dbcead6SJeremy L Thompson CeedVectorTakeArray(x_ceed, MemTypeP2C(mem_type), &x); 4799dbcead6SJeremy L Thompson PetscCall(VecRestoreArrayAndMemType(X_petsc, &x)); 4809dbcead6SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 4819dbcead6SJeremy L Thompson } 4829dbcead6SJeremy L Thompson 4839dbcead6SJeremy L Thompson PetscErrorCode VecReadP2C(Vec X_petsc, PetscMemType *mem_type, CeedVector x_ceed) { 4849dbcead6SJeremy L Thompson PetscScalar *x; 4859dbcead6SJeremy L Thompson 4869dbcead6SJeremy L Thompson PetscFunctionBeginUser; 4879dbcead6SJeremy L Thompson PetscCall(VecGetArrayReadAndMemType(X_petsc, (const PetscScalar **)&x, mem_type)); 4889dbcead6SJeremy L Thompson CeedVectorSetArray(x_ceed, MemTypeP2C(*mem_type), CEED_USE_POINTER, x); 4899dbcead6SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 4909dbcead6SJeremy L Thompson } 4919dbcead6SJeremy L Thompson 4929dbcead6SJeremy L Thompson PetscErrorCode VecReadC2P(CeedVector x_ceed, PetscMemType mem_type, Vec X_petsc) { 4939dbcead6SJeremy L Thompson PetscScalar *x; 4949dbcead6SJeremy L Thompson 4959dbcead6SJeremy L Thompson PetscFunctionBeginUser; 4969dbcead6SJeremy L Thompson CeedVectorTakeArray(x_ceed, MemTypeP2C(mem_type), &x); 4979dbcead6SJeremy L Thompson PetscCall(VecRestoreArrayReadAndMemType(X_petsc, (const PetscScalar **)&x)); 4989dbcead6SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 4999dbcead6SJeremy L Thompson } 5009dbcead6SJeremy L Thompson 5019dbcead6SJeremy L Thompson PetscErrorCode DMSwarmPICFieldP2C(DM dm_swarm, const char *field, CeedVector x_ceed) { 5029dbcead6SJeremy L Thompson PetscScalar *x; 5039dbcead6SJeremy L Thompson 5049dbcead6SJeremy L Thompson PetscFunctionBeginUser; 5059dbcead6SJeremy L Thompson PetscCall(DMSwarmGetField(dm_swarm, field, NULL, NULL, (void **)&x)); 5069dbcead6SJeremy L Thompson CeedVectorSetArray(x_ceed, CEED_MEM_HOST, CEED_USE_POINTER, (CeedScalar *)x); 5079dbcead6SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 5089dbcead6SJeremy L Thompson } 5099dbcead6SJeremy L Thompson 5109dbcead6SJeremy L Thompson PetscErrorCode DMSwarmPICFieldC2P(DM dm_swarm, const char *field, CeedVector x_ceed) { 5119dbcead6SJeremy L Thompson PetscScalar *x; 5129dbcead6SJeremy L Thompson 5139dbcead6SJeremy L Thompson PetscFunctionBeginUser; 5149dbcead6SJeremy L Thompson CeedVectorTakeArray(x_ceed, CEED_MEM_HOST, (CeedScalar **)&x); 5159dbcead6SJeremy L Thompson PetscCall(DMSwarmRestoreField(dm_swarm, field, NULL, NULL, (void **)&x)); 5169dbcead6SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 5179dbcead6SJeremy L Thompson } 5189dbcead6SJeremy L Thompson 5199dbcead6SJeremy L Thompson // ------------------------------------------------------------------------------------------------ 5209dbcead6SJeremy L Thompson // Solution functions 5219dbcead6SJeremy L Thompson // ------------------------------------------------------------------------------------------------ 5229dbcead6SJeremy L Thompson PetscScalar EvalU_Poly(PetscInt dim, const PetscScalar x[]) { 5239dbcead6SJeremy L Thompson PetscScalar result = 0.0; 5249dbcead6SJeremy L Thompson const PetscScalar p[5] = {3, 1, 4, 1, 5}; 5259dbcead6SJeremy L Thompson 5269dbcead6SJeremy L Thompson for (PetscInt d = 0; d < dim; d++) { 5279dbcead6SJeremy L Thompson PetscScalar result_1d = 1.0; 5289dbcead6SJeremy L Thompson 5299dbcead6SJeremy L Thompson for (PetscInt i = 4; i >= 0; i--) result_1d = result_1d * x[d] + p[i]; 5309dbcead6SJeremy L Thompson result += result_1d; 5319dbcead6SJeremy L Thompson } 5329dbcead6SJeremy L Thompson return result * 1E-3; 5339dbcead6SJeremy L Thompson } 5349dbcead6SJeremy L Thompson 5359dbcead6SJeremy L Thompson PetscScalar EvalU_Tanh(PetscInt dim, const PetscScalar x[]) { 5369dbcead6SJeremy L Thompson PetscScalar result = 1.0, center = 0.1; 5379dbcead6SJeremy L Thompson 5389dbcead6SJeremy L Thompson for (PetscInt d = 0; d < dim; d++) { 5399dbcead6SJeremy L Thompson result *= tanh(x[d] - center); 5409dbcead6SJeremy L Thompson center += 0.1; 5419dbcead6SJeremy L Thompson } 5429dbcead6SJeremy L Thompson return result; 5439dbcead6SJeremy L Thompson } 5449dbcead6SJeremy L Thompson 5459dbcead6SJeremy L Thompson PetscScalar EvalU_Sphere(PetscInt dim, const PetscScalar x[]) { 5469dbcead6SJeremy L Thompson PetscScalar distance = sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]); 5479dbcead6SJeremy L Thompson 5489dbcead6SJeremy L Thompson return distance < 1.0 ? 1.0 : 0.1; 5499dbcead6SJeremy L Thompson } 5509dbcead6SJeremy L Thompson 5519dbcead6SJeremy L Thompson PetscErrorCode EvalU_Poly_proj(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt num_comp, PetscScalar *u, void *ctx) { 5529dbcead6SJeremy L Thompson PetscFunctionBeginUser; 5539dbcead6SJeremy L Thompson 5549dbcead6SJeremy L Thompson const PetscScalar f_x = EvalU_Poly(dim, x); 5559dbcead6SJeremy L Thompson 5569dbcead6SJeremy L Thompson for (PetscInt c = 0; c < num_comp; c++) u[c] = (c + 1.0) * f_x; 5579dbcead6SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 5589dbcead6SJeremy L Thompson } 5599dbcead6SJeremy L Thompson 5609dbcead6SJeremy L Thompson PetscErrorCode EvalU_Tanh_proj(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt num_comp, PetscScalar *u, void *ctx) { 5619dbcead6SJeremy L Thompson PetscFunctionBeginUser; 5629dbcead6SJeremy L Thompson 5639dbcead6SJeremy L Thompson const PetscScalar f_x = EvalU_Tanh(dim, x); 5649dbcead6SJeremy L Thompson 5659dbcead6SJeremy L Thompson for (PetscInt c = 0; c < num_comp; c++) u[c] = (c + 1.0) * f_x; 5669dbcead6SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 5679dbcead6SJeremy L Thompson } 5689dbcead6SJeremy L Thompson 5699dbcead6SJeremy L Thompson PetscErrorCode EvalU_Sphere_proj(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt num_comp, PetscScalar *u, void *ctx) { 5709dbcead6SJeremy L Thompson PetscFunctionBeginUser; 5719dbcead6SJeremy L Thompson 5729dbcead6SJeremy L Thompson const PetscScalar f_x = EvalU_Sphere(dim, x); 5739dbcead6SJeremy L Thompson 5749dbcead6SJeremy L Thompson for (PetscInt c = 0; c < num_comp; c++) u[c] = (c + 1.0) * f_x; 5759dbcead6SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 5769dbcead6SJeremy L Thompson } 5779dbcead6SJeremy L Thompson 5789dbcead6SJeremy L Thompson // ------------------------------------------------------------------------------------------------ 5799dbcead6SJeremy L Thompson // Swarm point location utility 5809dbcead6SJeremy L Thompson // ------------------------------------------------------------------------------------------------ 5819dbcead6SJeremy L Thompson PetscErrorCode DMSwarmInitalizePointLocations(DM dm_swarm, PointSwarmType point_swarm_type, PetscInt num_points, PetscInt num_points_per_cell) { 5829dbcead6SJeremy L Thompson PetscFunctionBeginUser; 5839dbcead6SJeremy L Thompson 5849dbcead6SJeremy L Thompson switch (point_swarm_type) { 5859dbcead6SJeremy L Thompson case SWARM_GAUSS: 5869dbcead6SJeremy L Thompson case SWARM_UNIFORM: { 5879dbcead6SJeremy L Thompson // -- Set gauss or uniform point locations in each cell 5889dbcead6SJeremy L Thompson PetscInt num_points_per_cell_1d = round(cbrt(num_points_per_cell * 1.0)), dim = 3; 5899dbcead6SJeremy L Thompson PetscScalar point_coords[num_points_per_cell * 3]; 5909dbcead6SJeremy L Thompson CeedScalar points_1d[num_points_per_cell_1d], weights_1d[num_points_per_cell_1d]; 5919dbcead6SJeremy L Thompson 5929dbcead6SJeremy L Thompson if (point_swarm_type == SWARM_GAUSS) { 5939dbcead6SJeremy L Thompson PetscCall(CeedGaussQuadrature(num_points_per_cell_1d, points_1d, weights_1d)); 5949dbcead6SJeremy L Thompson } else { 5959dbcead6SJeremy L Thompson for (PetscInt i = 0; i < num_points_per_cell_1d; i++) points_1d[i] = 2.0 * (PetscReal)(i + 1) / (PetscReal)(num_points_per_cell_1d + 1) - 1; 5969dbcead6SJeremy L Thompson } 5979dbcead6SJeremy L Thompson for (PetscInt i = 0; i < num_points_per_cell_1d; i++) { 5989dbcead6SJeremy L Thompson for (PetscInt j = 0; j < num_points_per_cell_1d; j++) { 5999dbcead6SJeremy L Thompson for (PetscInt k = 0; k < num_points_per_cell_1d; k++) { 6009dbcead6SJeremy L Thompson PetscInt p = (i * num_points_per_cell_1d + j) * num_points_per_cell_1d + k; 6019dbcead6SJeremy L Thompson 6029dbcead6SJeremy L Thompson point_coords[p * dim + 0] = points_1d[i]; 6039dbcead6SJeremy L Thompson point_coords[p * dim + 1] = points_1d[j]; 6049dbcead6SJeremy L Thompson point_coords[p * dim + 2] = points_1d[k]; 6059dbcead6SJeremy L Thompson } 6069dbcead6SJeremy L Thompson } 6079dbcead6SJeremy L Thompson } 6089dbcead6SJeremy L Thompson PetscCall(DMSwarmSetPointCoordinatesCellwise(dm_swarm, num_points_per_cell_1d * num_points_per_cell_1d * num_points_per_cell_1d, point_coords)); 6099dbcead6SJeremy L Thompson } break; 6109dbcead6SJeremy L Thompson case SWARM_CELL_RANDOM: { 6119dbcead6SJeremy L Thompson // -- Set points randomly in each cell 6129dbcead6SJeremy L Thompson PetscInt dim = 3, num_cells_total = 1, num_cells[] = {1, 1, 1}; 6139dbcead6SJeremy L Thompson PetscScalar *point_coords; 6149dbcead6SJeremy L Thompson PetscRandom rng; 6159dbcead6SJeremy L Thompson 6169dbcead6SJeremy L Thompson PetscOptionsBegin(PetscObjectComm((PetscObject)dm_swarm), NULL, "libCEED example using PETSc with DMSwarm", NULL); 6179dbcead6SJeremy L Thompson 6189dbcead6SJeremy L Thompson PetscCall(PetscOptionsInt("-dm_plex_dim", "Background mesh dimension", NULL, dim, &dim, NULL)); 6199dbcead6SJeremy L Thompson PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of cells", NULL, num_cells, &dim, NULL)); 6209dbcead6SJeremy L Thompson 6219dbcead6SJeremy L Thompson PetscOptionsEnd(); 6229dbcead6SJeremy L Thompson 6239dbcead6SJeremy L Thompson PetscCall(PetscRandomCreate(PetscObjectComm((PetscObject)dm_swarm), &rng)); 6249dbcead6SJeremy L Thompson 6259dbcead6SJeremy L Thompson num_cells_total = num_cells[0] * num_cells[1] * num_cells[2]; 6269dbcead6SJeremy L Thompson PetscCall(DMSwarmGetField(dm_swarm, DMSwarmPICField_coor, NULL, NULL, (void **)&point_coords)); 6279dbcead6SJeremy L Thompson for (PetscInt c = 0; c < num_cells_total; c++) { 6289dbcead6SJeremy L Thompson PetscInt cell_index[3] = {c % num_cells[0], (c / num_cells[0]) % num_cells[1], (c / num_cells[0] / num_cells[1]) % num_cells[2]}; 6299dbcead6SJeremy L Thompson 6309dbcead6SJeremy L Thompson for (PetscInt p = 0; p < num_points_per_cell; p++) { 6319dbcead6SJeremy L Thompson PetscInt point_index = c * num_points_per_cell + p; 6329dbcead6SJeremy L Thompson PetscScalar random_value; 6339dbcead6SJeremy L Thompson 6349dbcead6SJeremy L Thompson for (PetscInt i = 0; i < dim; i++) { 6359dbcead6SJeremy L Thompson PetscCall(PetscRandomGetValue(rng, &random_value)); 6369dbcead6SJeremy L Thompson point_coords[point_index * dim + i] = -1.0 + cell_index[i] * 2.0 / (num_cells[i] + 1.0) + random_value; 6379dbcead6SJeremy L Thompson } 6389dbcead6SJeremy L Thompson } 6399dbcead6SJeremy L Thompson } 6409dbcead6SJeremy L Thompson PetscCall(DMSwarmRestoreField(dm_swarm, DMSwarmPICField_coor, NULL, NULL, (void **)&point_coords)); 6419dbcead6SJeremy L Thompson PetscCall(PetscRandomDestroy(&rng)); 6429dbcead6SJeremy L Thompson } break; 6439dbcead6SJeremy L Thompson case SWARM_SINUSOIDAL: { 6449dbcead6SJeremy L Thompson // -- Set points distributed per sinusoidal functions 6459dbcead6SJeremy L Thompson PetscInt dim = 3; 6469dbcead6SJeremy L Thompson PetscScalar *point_coords; 6479dbcead6SJeremy L Thompson DM dm_mesh; 6489dbcead6SJeremy L Thompson 6499dbcead6SJeremy L Thompson PetscCall(DMSwarmGetCellDM(dm_swarm, &dm_mesh)); 6509dbcead6SJeremy L Thompson PetscCall(DMGetDimension(dm_mesh, &dim)); 6519dbcead6SJeremy L Thompson 6529dbcead6SJeremy L Thompson PetscCall(DMSwarmGetField(dm_swarm, DMSwarmPICField_coor, NULL, NULL, (void **)&point_coords)); 6539dbcead6SJeremy L Thompson for (PetscInt p = 0; p < num_points; p++) { 6549dbcead6SJeremy L Thompson point_coords[p * dim + 0] = -PetscCosReal((PetscReal)(p + 1) / (PetscReal)(num_points + 1) * PETSC_PI); 6559dbcead6SJeremy L Thompson if (dim > 1) point_coords[p * dim + 1] = -PetscSinReal((PetscReal)(p + 1) / (PetscReal)(num_points + 1) * PETSC_PI); 6569dbcead6SJeremy L Thompson if (dim > 2) point_coords[p * dim + 2] = PetscSinReal((PetscReal)(p + 1) / (PetscReal)(num_points + 1) * PETSC_PI); 6579dbcead6SJeremy L Thompson } 6589dbcead6SJeremy L Thompson PetscCall(DMSwarmRestoreField(dm_swarm, DMSwarmPICField_coor, NULL, NULL, (void **)&point_coords)); 6599dbcead6SJeremy L Thompson } break; 6609dbcead6SJeremy L Thompson } 6619dbcead6SJeremy L Thompson PetscCall(DMSwarmMigrate(dm_swarm, PETSC_TRUE)); 6629dbcead6SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 6639dbcead6SJeremy L Thompson } 6649dbcead6SJeremy L Thompson 6659dbcead6SJeremy L Thompson /*@C 6669dbcead6SJeremy L Thompson DMSwarmCreateReferenceCoordinates - Compute the cell reference coordinates for local DMSwarm points. 6679dbcead6SJeremy L Thompson 6689dbcead6SJeremy L Thompson Collective 6699dbcead6SJeremy L Thompson 6709dbcead6SJeremy L Thompson Input Parameter: 6719dbcead6SJeremy L Thompson . dm_swarm - the `DMSwarm` 6729dbcead6SJeremy L Thompson 6739dbcead6SJeremy L Thompson Output Parameters: 6749dbcead6SJeremy L Thompson + is_points - The IS object for indexing into points per cell 6759dbcead6SJeremy L Thompson - X_points_ref - Vec holding the cell reference coordinates for local DMSwarm points 6769dbcead6SJeremy L Thompson 6779dbcead6SJeremy L Thompson The index set contains ranges of indices for each local cell. This range contains the indices of every point in the cell. 6789dbcead6SJeremy L Thompson 6799dbcead6SJeremy L Thompson ``` 6809dbcead6SJeremy L Thompson total_num_cells 6819dbcead6SJeremy L Thompson cell_0_start_index 6829dbcead6SJeremy L Thompson cell_1_start_index 6839dbcead6SJeremy L Thompson cell_2_start_index 6849dbcead6SJeremy L Thompson ... 6859dbcead6SJeremy L Thompson cell_n_start_index 6869dbcead6SJeremy L Thompson cell_n_stop_index 6879dbcead6SJeremy L Thompson cell_0_point_0 6889dbcead6SJeremy L Thompson cell_0_point_0 6899dbcead6SJeremy L Thompson ... 6909dbcead6SJeremy L Thompson cell_n_point_m 6919dbcead6SJeremy L Thompson ``` 6929dbcead6SJeremy L Thompson 6939dbcead6SJeremy L Thompson Level: beginner 6949dbcead6SJeremy L Thompson 6959dbcead6SJeremy L Thompson .seealso: `DMSwarm` 6969dbcead6SJeremy L Thompson @*/ 6979dbcead6SJeremy L Thompson PetscErrorCode DMSwarmCreateReferenceCoordinates(DM dm_swarm, IS *is_points, Vec *X_points_ref) { 6989dbcead6SJeremy L Thompson PetscInt cell_start, cell_end, num_cells_local, dim, num_points_local, *cell_points, points_offset; 6999dbcead6SJeremy L Thompson PetscScalar *coords_points_ref; 7009dbcead6SJeremy L Thompson const PetscScalar *coords_points_true; 7019dbcead6SJeremy L Thompson DM dm_mesh; 7029dbcead6SJeremy L Thompson 7039dbcead6SJeremy L Thompson PetscFunctionBeginUser; 7049dbcead6SJeremy L Thompson PetscCall(DMSwarmGetCellDM(dm_swarm, &dm_mesh)); 7059dbcead6SJeremy L Thompson 7069dbcead6SJeremy L Thompson // Create vector to hold reference coordinates 7079dbcead6SJeremy L Thompson { 7089dbcead6SJeremy L Thompson Vec X_points_true; 7099dbcead6SJeremy L Thompson 7109dbcead6SJeremy L Thompson PetscCall(DMSwarmCreateLocalVectorFromField(dm_swarm, DMSwarmPICField_coor, &X_points_true)); 7119dbcead6SJeremy L Thompson PetscCall(VecDuplicate(X_points_true, X_points_ref)); 7129dbcead6SJeremy L Thompson PetscCall(DMSwarmDestroyLocalVectorFromField(dm_swarm, DMSwarmPICField_coor, &X_points_true)); 7139dbcead6SJeremy L Thompson } 7149dbcead6SJeremy L Thompson 7159dbcead6SJeremy L Thompson // Allocate index set array 7169dbcead6SJeremy L Thompson PetscCall(DMPlexGetHeightStratum(dm_mesh, 0, &cell_start, &cell_end)); 7179dbcead6SJeremy L Thompson num_cells_local = cell_end - cell_start; 7189dbcead6SJeremy L Thompson points_offset = num_cells_local + 2; 7199dbcead6SJeremy L Thompson PetscCall(VecGetLocalSize(*X_points_ref, &num_points_local)); 7209dbcead6SJeremy L Thompson PetscCall(DMGetDimension(dm_mesh, &dim)); 7219dbcead6SJeremy L Thompson num_points_local /= dim; 7229dbcead6SJeremy L Thompson PetscCall(PetscMalloc1(num_points_local + num_cells_local + 2, &cell_points)); 7239dbcead6SJeremy L Thompson cell_points[0] = num_cells_local; 7249dbcead6SJeremy L Thompson 7259dbcead6SJeremy L Thompson // Get reference coordinates for each swarm point wrt the elements in the background mesh 7269dbcead6SJeremy L Thompson PetscCall(DMSwarmSortGetAccess(dm_swarm)); 7279dbcead6SJeremy L Thompson PetscCall(DMSwarmGetField(dm_swarm, DMSwarmPICField_coor, NULL, NULL, (void **)&coords_points_true)); 7289dbcead6SJeremy L Thompson PetscCall(VecGetArray(*X_points_ref, &coords_points_ref)); 7299dbcead6SJeremy L Thompson for (PetscInt cell = cell_start, num_points_processed = 0; cell < cell_end; cell++) { 7309dbcead6SJeremy L Thompson PetscInt *points_in_cell, num_points_in_cell, local_cell = cell - cell_start; 7319dbcead6SJeremy L Thompson PetscReal v[3], J[9], invJ[9], detJ, v0_ref[3] = {-1.0, -1.0, -1.0}; 7329dbcead6SJeremy L Thompson 7339dbcead6SJeremy L Thompson PetscCall(DMSwarmSortGetPointsPerCell(dm_swarm, cell, &num_points_in_cell, &points_in_cell)); 7349dbcead6SJeremy L Thompson // -- Reference coordinates for swarm points in background mesh element 7359dbcead6SJeremy L Thompson PetscCall(DMPlexComputeCellGeometryFEM(dm_mesh, cell, NULL, v, J, invJ, &detJ)); 7369dbcead6SJeremy L Thompson cell_points[local_cell + 1] = num_points_processed + points_offset; 7379dbcead6SJeremy L Thompson for (PetscInt p = 0; p < num_points_in_cell; p++) { 7389dbcead6SJeremy L Thompson const CeedInt point = points_in_cell[p]; 7399dbcead6SJeremy L Thompson 7409dbcead6SJeremy L Thompson cell_points[points_offset + (num_points_processed++)] = point; 7419dbcead6SJeremy L Thompson CoordinatesRealToRef(dim, dim, v0_ref, v, invJ, &coords_points_true[point * dim], &coords_points_ref[point * dim]); 7429dbcead6SJeremy L Thompson } 7439dbcead6SJeremy L Thompson 7449dbcead6SJeremy L Thompson // -- Cleanup 7459dbcead6SJeremy L Thompson PetscCall(PetscFree(points_in_cell)); 7469dbcead6SJeremy L Thompson } 7479dbcead6SJeremy L Thompson cell_points[points_offset - 1] = num_points_local + points_offset; 7489dbcead6SJeremy L Thompson 7499dbcead6SJeremy L Thompson // Cleanup 7509dbcead6SJeremy L Thompson PetscCall(DMSwarmRestoreField(dm_swarm, DMSwarmPICField_coor, NULL, NULL, (void **)&coords_points_true)); 7519dbcead6SJeremy L Thompson PetscCall(VecRestoreArray(*X_points_ref, &coords_points_ref)); 7529dbcead6SJeremy L Thompson PetscCall(DMSwarmSortRestoreAccess(dm_swarm)); 7539dbcead6SJeremy L Thompson 7549dbcead6SJeremy L Thompson // Create index set 7559dbcead6SJeremy L Thompson PetscCall(ISCreateGeneral(PETSC_COMM_SELF, num_points_local + points_offset, cell_points, PETSC_OWN_POINTER, is_points)); 7569dbcead6SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 7579dbcead6SJeremy L Thompson } 7589dbcead6SJeremy L Thompson 7599dbcead6SJeremy L Thompson // ------------------------------------------------------------------------------------------------ 7609dbcead6SJeremy L Thompson // Projection via PETSc 7619dbcead6SJeremy L Thompson // ------------------------------------------------------------------------------------------------ 7629dbcead6SJeremy L Thompson PetscErrorCode DMSwarmInterpolateFromCellToSwarm_Petsc(DM dm_swarm, const char *field, Vec U_mesh) { 7639dbcead6SJeremy L Thompson PetscInt dim, num_comp, cell_start, cell_end; 7649dbcead6SJeremy L Thompson PetscScalar *u_points; 7659dbcead6SJeremy L Thompson const PetscScalar *coords_points; 7669dbcead6SJeremy L Thompson const PetscReal v0_ref[3] = {-1.0, -1.0, -1.0}; 7679dbcead6SJeremy L Thompson DM dm_mesh; 7689dbcead6SJeremy L Thompson PetscSection section_u_mesh_loc; 7699dbcead6SJeremy L Thompson PetscDS ds; 7709dbcead6SJeremy L Thompson PetscFE fe; 7719dbcead6SJeremy L Thompson PetscFEGeom fe_geometry; 7729dbcead6SJeremy L Thompson PetscQuadrature quadrature; 7739dbcead6SJeremy L Thompson Vec U_loc; 7749dbcead6SJeremy L Thompson 7759dbcead6SJeremy L Thompson PetscFunctionBeginUser; 7769dbcead6SJeremy L Thompson // Get mesh DM 7779dbcead6SJeremy L Thompson PetscCall(DMSwarmGetCellDM(dm_swarm, &dm_mesh)); 7789dbcead6SJeremy L Thompson PetscCall(DMGetDimension(dm_mesh, &dim)); 7799dbcead6SJeremy L Thompson { 7809dbcead6SJeremy L Thompson PetscSection section_u_mesh_loc_closure_permutation; 7819dbcead6SJeremy L Thompson 7829dbcead6SJeremy L Thompson PetscCall(DMGetLocalSection(dm_mesh, §ion_u_mesh_loc_closure_permutation)); 7839dbcead6SJeremy L Thompson PetscCall(PetscSectionClone(section_u_mesh_loc_closure_permutation, §ion_u_mesh_loc)); 7849dbcead6SJeremy L Thompson PetscCall(PetscSectionResetClosurePermutation(section_u_mesh_loc)); 7859dbcead6SJeremy L Thompson } 7869dbcead6SJeremy L Thompson 7879dbcead6SJeremy L Thompson // Get local mesh values 7889dbcead6SJeremy L Thompson PetscCall(DMGetLocalVector(dm_mesh, &U_loc)); 7899dbcead6SJeremy L Thompson PetscCall(VecZeroEntries(U_loc)); 7909dbcead6SJeremy L Thompson PetscCall(DMGlobalToLocal(dm_mesh, U_mesh, INSERT_VALUES, U_loc)); 7919dbcead6SJeremy L Thompson 7929dbcead6SJeremy L Thompson // Get local swarm data 7939dbcead6SJeremy L Thompson PetscCall(DMSwarmSortGetAccess(dm_swarm)); 7949dbcead6SJeremy L Thompson PetscCall(DMPlexGetHeightStratum(dm_mesh, 0, &cell_start, &cell_end)); 7959dbcead6SJeremy L Thompson PetscCall(DMSwarmGetField(dm_swarm, DMSwarmPICField_coor, NULL, NULL, (void **)&coords_points)); 7969dbcead6SJeremy L Thompson PetscCall(DMSwarmGetField(dm_swarm, field, &num_comp, NULL, (void **)&u_points)); 7979dbcead6SJeremy L Thompson 7989dbcead6SJeremy L Thompson // Interpolate values to each swarm point, one element in the background mesh at a time 7999dbcead6SJeremy L Thompson PetscCall(DMGetDS(dm_mesh, &ds)); 8009dbcead6SJeremy L Thompson PetscCall(PetscDSGetDiscretization(ds, 0, (PetscObject *)&fe)); 8019dbcead6SJeremy L Thompson for (PetscInt cell = cell_start; cell < cell_end; cell++) { 8029dbcead6SJeremy L Thompson PetscTabulation tabulation; 8039dbcead6SJeremy L Thompson PetscScalar *u_cell = NULL, *coords_points_cell_true, *coords_points_cell_ref; 8049dbcead6SJeremy L Thompson PetscReal v[dim], J[dim * dim], invJ[dim * dim], detJ; 8059dbcead6SJeremy L Thompson PetscInt *points_cell; 8069dbcead6SJeremy L Thompson PetscInt num_points_in_cell; 8079dbcead6SJeremy L Thompson 8089dbcead6SJeremy L Thompson PetscCall(DMSwarmSortGetPointsPerCell(dm_swarm, cell, &num_points_in_cell, &points_cell)); 8099dbcead6SJeremy L Thompson PetscCall(DMGetWorkArray(dm_mesh, num_points_in_cell * dim, MPIU_REAL, &coords_points_cell_true)); 8109dbcead6SJeremy L Thompson PetscCall(DMGetWorkArray(dm_mesh, num_points_in_cell * dim, MPIU_REAL, &coords_points_cell_ref)); 8119dbcead6SJeremy L Thompson // -- Reference coordinates for swarm points in background mesh element 8129dbcead6SJeremy L Thompson for (PetscInt p = 0; p < num_points_in_cell; p++) { 8139dbcead6SJeremy L Thompson for (PetscInt d = 0; d < dim; d++) coords_points_cell_true[p * dim + d] = coords_points[points_cell[p] * dim + d]; 8149dbcead6SJeremy L Thompson } 8159dbcead6SJeremy L Thompson PetscCall(DMPlexComputeCellGeometryFEM(dm_mesh, cell, NULL, v, J, invJ, &detJ)); 8169dbcead6SJeremy L Thompson for (PetscInt p = 0; p < num_points_in_cell; p++) { 8179dbcead6SJeremy L Thompson CoordinatesRealToRef(dim, dim, v0_ref, v, invJ, &coords_points_cell_true[p * dim], &coords_points_cell_ref[p * dim]); 8189dbcead6SJeremy L Thompson } 8199dbcead6SJeremy L Thompson // -- Interpolate values from current element in background mesh to swarm points 8209dbcead6SJeremy L Thompson PetscCall(PetscFECreateTabulation(fe, 1, num_points_in_cell, coords_points_cell_ref, 1, &tabulation)); 8219dbcead6SJeremy L Thompson PetscCall(DMPlexVecGetClosure(dm_mesh, section_u_mesh_loc, U_loc, cell, NULL, &u_cell)); 8229dbcead6SJeremy L Thompson PetscCall(PetscFEGetQuadrature(fe, &quadrature)); 8239dbcead6SJeremy L Thompson PetscCall(PetscFECreateCellGeometry(fe, quadrature, &fe_geometry)); 8249dbcead6SJeremy L Thompson for (PetscInt p = 0; p < num_points_in_cell; p++) { 8259dbcead6SJeremy L Thompson PetscCall(PetscFEInterpolateAtPoints_Static(fe, tabulation, u_cell, &fe_geometry, p, &u_points[points_cell[p] * num_comp])); 8269dbcead6SJeremy L Thompson } 8279dbcead6SJeremy L Thompson 8289dbcead6SJeremy L Thompson // -- Cleanup 8299dbcead6SJeremy L Thompson PetscCall(PetscFEDestroyCellGeometry(fe, &fe_geometry)); 8309dbcead6SJeremy L Thompson PetscCall(DMPlexVecRestoreClosure(dm_mesh, section_u_mesh_loc, U_loc, cell, NULL, &u_cell)); 8319dbcead6SJeremy L Thompson PetscCall(DMRestoreWorkArray(dm_mesh, num_points_in_cell * dim, MPIU_REAL, &coords_points_cell_true)); 8329dbcead6SJeremy L Thompson PetscCall(DMRestoreWorkArray(dm_mesh, num_points_in_cell * dim, MPIU_REAL, &coords_points_cell_ref)); 8339dbcead6SJeremy L Thompson PetscCall(PetscTabulationDestroy(&tabulation)); 8349dbcead6SJeremy L Thompson PetscCall(PetscFree(points_cell)); 8359dbcead6SJeremy L Thompson } 8369dbcead6SJeremy L Thompson 8379dbcead6SJeremy L Thompson // Cleanup 8389dbcead6SJeremy L Thompson PetscCall(DMSwarmRestoreField(dm_swarm, DMSwarmPICField_coor, NULL, NULL, (void **)&coords_points)); 8399dbcead6SJeremy L Thompson PetscCall(DMSwarmRestoreField(dm_swarm, field, NULL, NULL, (void **)&u_points)); 8409dbcead6SJeremy L Thompson PetscCall(DMSwarmSortRestoreAccess(dm_swarm)); 8419dbcead6SJeremy L Thompson PetscCall(DMRestoreLocalVector(dm_mesh, &U_loc)); 8429dbcead6SJeremy L Thompson PetscCall(PetscSectionDestroy(§ion_u_mesh_loc)); 8439dbcead6SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 8449dbcead6SJeremy L Thompson } 8459dbcead6SJeremy L Thompson 8469dbcead6SJeremy L Thompson // ------------------------------------------------------------------------------------------------ 8479dbcead6SJeremy L Thompson // Projection via libCEED 8489dbcead6SJeremy L Thompson // ------------------------------------------------------------------------------------------------ 8499dbcead6SJeremy L Thompson PetscErrorCode DMSwarmInterpolateFromCellToSwarm_Ceed(DM dm_swarm, const char *field, Vec U_mesh) { 8509dbcead6SJeremy L Thompson PetscInt num_elem; 8519dbcead6SJeremy L Thompson PetscMemType U_mem_type; 8529dbcead6SJeremy L Thompson DM dm_mesh; 8539dbcead6SJeremy L Thompson Vec U_mesh_loc; 8549dbcead6SJeremy L Thompson DMSwarmCeedContext swarm_ceed_context; 8559dbcead6SJeremy L Thompson 8569dbcead6SJeremy L Thompson PetscFunctionBeginUser; 8579dbcead6SJeremy L Thompson // Get mesh DM 8589dbcead6SJeremy L Thompson PetscCall(DMSwarmGetCellDM(dm_swarm, &dm_mesh)); 8599dbcead6SJeremy L Thompson PetscCall(DMGetApplicationContext(dm_mesh, (void *)&swarm_ceed_context)); 8609dbcead6SJeremy L Thompson 8619dbcead6SJeremy L Thompson // Get mesh values 8629dbcead6SJeremy L Thompson PetscCall(DMGetLocalVector(dm_mesh, &U_mesh_loc)); 8639dbcead6SJeremy L Thompson PetscCall(VecZeroEntries(U_mesh_loc)); 8649dbcead6SJeremy L Thompson PetscCall(DMGlobalToLocal(dm_mesh, U_mesh, INSERT_VALUES, U_mesh_loc)); 8659dbcead6SJeremy L Thompson PetscCall(VecReadP2C(U_mesh_loc, &U_mem_type, swarm_ceed_context->u_mesh_loc)); 8669dbcead6SJeremy L Thompson 8679dbcead6SJeremy L Thompson // Get swarm access 8689dbcead6SJeremy L Thompson PetscCall(DMSwarmSortGetAccess(dm_swarm)); 8699dbcead6SJeremy L Thompson PetscCall(DMSwarmPICFieldP2C(dm_swarm, field, swarm_ceed_context->u_points_loc)); 8709dbcead6SJeremy L Thompson 8719dbcead6SJeremy L Thompson // Interpolate values to each swarm point, one element in the background mesh at a time 8729dbcead6SJeremy L Thompson CeedElemRestrictionGetNumElements(swarm_ceed_context->restriction_u_mesh, &num_elem); 8739dbcead6SJeremy L Thompson for (PetscInt e = 0; e < num_elem; e++) { 8749dbcead6SJeremy L Thompson PetscInt num_points_in_elem; 8759dbcead6SJeremy L Thompson 8769dbcead6SJeremy L Thompson CeedElemRestrictionGetNumPointsInElement(swarm_ceed_context->restriction_u_points, e, &num_points_in_elem); 8779dbcead6SJeremy L Thompson 8789dbcead6SJeremy L Thompson // -- Reference coordinates for swarm points in background mesh element 8799dbcead6SJeremy L Thompson CeedElemRestrictionApplyAtPointsInElement(swarm_ceed_context->restriction_x_points, e, CEED_NOTRANSPOSE, swarm_ceed_context->x_ref_points_loc, 8809dbcead6SJeremy L Thompson swarm_ceed_context->x_ref_points_elem, CEED_REQUEST_IMMEDIATE); 8819dbcead6SJeremy L Thompson 8829dbcead6SJeremy L Thompson // -- Interpolate values from current element in background mesh to swarm points 8839dbcead6SJeremy L Thompson // Note: This will only work for CPU backends at this time, as only CPU backends support ApplyBlock and ApplyAtPoints 8849dbcead6SJeremy L Thompson CeedElemRestrictionApplyBlock(swarm_ceed_context->restriction_u_mesh, e, CEED_NOTRANSPOSE, swarm_ceed_context->u_mesh_loc, 8859dbcead6SJeremy L Thompson swarm_ceed_context->u_mesh_elem, CEED_REQUEST_IMMEDIATE); 8869dbcead6SJeremy L Thompson CeedBasisApplyAtPoints(swarm_ceed_context->basis_u, num_points_in_elem, CEED_NOTRANSPOSE, CEED_EVAL_INTERP, swarm_ceed_context->x_ref_points_elem, 8879dbcead6SJeremy L Thompson swarm_ceed_context->u_mesh_elem, swarm_ceed_context->u_points_elem); 8889dbcead6SJeremy L Thompson 8899dbcead6SJeremy L Thompson // -- Insert result back into local vector 8909dbcead6SJeremy L Thompson CeedElemRestrictionApplyAtPointsInElement(swarm_ceed_context->restriction_u_points, e, CEED_TRANSPOSE, swarm_ceed_context->u_points_elem, 8919dbcead6SJeremy L Thompson swarm_ceed_context->u_points_loc, CEED_REQUEST_IMMEDIATE); 8929dbcead6SJeremy L Thompson } 8939dbcead6SJeremy L Thompson 8949dbcead6SJeremy L Thompson // Cleanup 8959dbcead6SJeremy L Thompson PetscCall(DMSwarmPICFieldC2P(dm_swarm, field, swarm_ceed_context->u_points_loc)); 8969dbcead6SJeremy L Thompson PetscCall(DMSwarmSortRestoreAccess(dm_swarm)); 8979dbcead6SJeremy L Thompson PetscCall(VecReadC2P(swarm_ceed_context->u_mesh_loc, U_mem_type, U_mesh_loc)); 8989dbcead6SJeremy L Thompson PetscCall(DMRestoreLocalVector(dm_mesh, &U_mesh_loc)); 8999dbcead6SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 9009dbcead6SJeremy L Thompson } 9019dbcead6SJeremy L Thompson 9029dbcead6SJeremy L Thompson // ------------------------------------------------------------------------------------------------ 9039dbcead6SJeremy L Thompson // Error checking utility 9049dbcead6SJeremy L Thompson // ------------------------------------------------------------------------------------------------ 9059dbcead6SJeremy L Thompson PetscErrorCode DMSwarmCheckSwarmValues(DM dm_swarm, const char *field, PetscScalar tolerance, TargetFuncProj TrueSolution) { 9069dbcead6SJeremy L Thompson PetscBool within_tolerance = PETSC_TRUE; 9079dbcead6SJeremy L Thompson PetscInt dim, num_comp, cell_start, cell_end; 9089dbcead6SJeremy L Thompson const PetscScalar *u_points, *coords_points; 9099dbcead6SJeremy L Thompson DM dm_mesh; 9109dbcead6SJeremy L Thompson 9119dbcead6SJeremy L Thompson PetscFunctionBeginUser; 9129dbcead6SJeremy L Thompson PetscCall(DMSwarmSortGetAccess(dm_swarm)); 9139dbcead6SJeremy L Thompson PetscCall(DMSwarmGetCellDM(dm_swarm, &dm_mesh)); 9149dbcead6SJeremy L Thompson PetscCall(DMGetDimension(dm_mesh, &dim)); 9159dbcead6SJeremy L Thompson PetscCall(DMPlexGetHeightStratum(dm_mesh, 0, &cell_start, &cell_end)); 9169dbcead6SJeremy L Thompson PetscCall(DMSwarmGetField(dm_swarm, DMSwarmPICField_coor, NULL, NULL, (void **)&coords_points)); 9179dbcead6SJeremy L Thompson PetscCall(DMSwarmGetField(dm_swarm, field, &num_comp, NULL, (void **)&u_points)); 9189dbcead6SJeremy L Thompson 9199dbcead6SJeremy L Thompson // Interpolate values to each swarm point, one element in the background mesh at a time 9209dbcead6SJeremy L Thompson for (PetscInt cell = cell_start; cell < cell_end; cell++) { 9219dbcead6SJeremy L Thompson PetscInt *points; 9229dbcead6SJeremy L Thompson PetscInt num_points_in_cell; 9239dbcead6SJeremy L Thompson 9249dbcead6SJeremy L Thompson PetscCall(DMSwarmSortGetPointsPerCell(dm_swarm, cell, &num_points_in_cell, &points)); 9259dbcead6SJeremy L Thompson // -- Reference coordinates for swarm points in background mesh element 9269dbcead6SJeremy L Thompson for (PetscInt p = 0; p < num_points_in_cell; p++) { 9279dbcead6SJeremy L Thompson PetscScalar x[dim], u_true[num_comp]; 9289dbcead6SJeremy L Thompson 9299dbcead6SJeremy L Thompson for (PetscInt d = 0; d < dim; d++) x[d] = coords_points[points[p] * dim + d]; 9309dbcead6SJeremy L Thompson PetscCall(TrueSolution(dim, 0.0, x, num_comp, u_true, NULL)); 9319dbcead6SJeremy L Thompson for (PetscInt i = 0; i < num_comp; i++) { 9329dbcead6SJeremy L Thompson if (PetscAbs(u_points[points[p] * num_comp + i] - u_true[i]) > tolerance) { 9339dbcead6SJeremy L Thompson within_tolerance = PETSC_FALSE; 9349dbcead6SJeremy L Thompson PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm_swarm), 9359dbcead6SJeremy L Thompson "Incorrect interpolated value, cell %" PetscInt_FMT " point %" PetscInt_FMT " component %" PetscInt_FMT 9369dbcead6SJeremy L Thompson ", found %f expected %f\n", 9379dbcead6SJeremy L Thompson cell, p, i, u_points[points[p] * num_comp + i], u_true[i])); 9389dbcead6SJeremy L Thompson } 9399dbcead6SJeremy L Thompson } 9409dbcead6SJeremy L Thompson } 9419dbcead6SJeremy L Thompson 9429dbcead6SJeremy L Thompson // -- Cleanup 9439dbcead6SJeremy L Thompson PetscCall(PetscFree(points)); 9449dbcead6SJeremy L Thompson } 9459dbcead6SJeremy L Thompson 9469dbcead6SJeremy L Thompson // Cleanup 9479dbcead6SJeremy L Thompson PetscCall(DMSwarmRestoreField(dm_swarm, DMSwarmPICField_coor, NULL, NULL, (void **)&coords_points)); 9489dbcead6SJeremy L Thompson PetscCall(DMSwarmRestoreField(dm_swarm, field, NULL, NULL, (void **)&u_points)); 9499dbcead6SJeremy L Thompson PetscCall(DMSwarmSortRestoreAccess(dm_swarm)); 9509dbcead6SJeremy L Thompson PetscCheck(within_tolerance, PetscObjectComm((PetscObject)dm_swarm), PETSC_ERR_USER, "Interpolation to swarm points not within tolerance"); 9519dbcead6SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 9529dbcead6SJeremy L Thompson } 9539dbcead6SJeremy L Thompson 9549dbcead6SJeremy L Thompson // ------------------------------------------------------------------------------------------------ 9559dbcead6SJeremy L Thompson // RHS for Swarm to Mesh projection 9569dbcead6SJeremy L Thompson // ------------------------------------------------------------------------------------------------ 9579dbcead6SJeremy L Thompson PetscErrorCode DMSwarmCreateProjectionRHS(DM dm_swarm, const char *field, Vec B_mesh) { 9589dbcead6SJeremy L Thompson PetscInt num_elem; 9599dbcead6SJeremy L Thompson PetscMemType B_mem_type; 9609dbcead6SJeremy L Thompson DM dm_mesh; 9619dbcead6SJeremy L Thompson Vec B_mesh_loc; 9629dbcead6SJeremy L Thompson DMSwarmCeedContext swarm_ceed_context; 9639dbcead6SJeremy L Thompson 9649dbcead6SJeremy L Thompson PetscFunctionBeginUser; 9659dbcead6SJeremy L Thompson // Get mesh DM 9669dbcead6SJeremy L Thompson PetscCall(DMSwarmGetCellDM(dm_swarm, &dm_mesh)); 9679dbcead6SJeremy L Thompson PetscCall(DMGetApplicationContext(dm_mesh, (void *)&swarm_ceed_context)); 9689dbcead6SJeremy L Thompson 9699dbcead6SJeremy L Thompson // Get mesh values 9709dbcead6SJeremy L Thompson PetscCall(DMGetLocalVector(dm_mesh, &B_mesh_loc)); 9719dbcead6SJeremy L Thompson PetscCall(VecZeroEntries(B_mesh_loc)); 9729dbcead6SJeremy L Thompson PetscCall(VecP2C(B_mesh_loc, &B_mem_type, swarm_ceed_context->v_mesh_loc)); 9739dbcead6SJeremy L Thompson 9749dbcead6SJeremy L Thompson // Get swarm access 9759dbcead6SJeremy L Thompson PetscCall(DMSwarmSortGetAccess(dm_swarm)); 9769dbcead6SJeremy L Thompson PetscCall(DMSwarmPICFieldP2C(dm_swarm, field, swarm_ceed_context->u_points_loc)); 9779dbcead6SJeremy L Thompson 9789dbcead6SJeremy L Thompson // Interpolate values to each swarm point, one element in the background mesh at a time 9799dbcead6SJeremy L Thompson CeedElemRestrictionGetNumElements(swarm_ceed_context->restriction_u_mesh, &num_elem); 9809dbcead6SJeremy L Thompson for (PetscInt e = 0; e < num_elem; e++) { 9819dbcead6SJeremy L Thompson PetscInt num_points_in_elem; 9829dbcead6SJeremy L Thompson 9839dbcead6SJeremy L Thompson CeedElemRestrictionGetNumPointsInElement(swarm_ceed_context->restriction_u_points, e, &num_points_in_elem); 9849dbcead6SJeremy L Thompson 9859dbcead6SJeremy L Thompson // -- Reference coordinates for swarm points in background mesh element 9869dbcead6SJeremy L Thompson CeedElemRestrictionApplyAtPointsInElement(swarm_ceed_context->restriction_x_points, e, CEED_NOTRANSPOSE, swarm_ceed_context->x_ref_points_loc, 9879dbcead6SJeremy L Thompson swarm_ceed_context->x_ref_points_elem, CEED_REQUEST_IMMEDIATE); 9889dbcead6SJeremy L Thompson 9899dbcead6SJeremy L Thompson // -- Interpolate values from current element in background mesh to swarm points 9909dbcead6SJeremy L Thompson // Note: This will only work for CPU backends at this time, as only CPU backends support ApplyBlock and ApplyAtPoints 9919dbcead6SJeremy L Thompson CeedElemRestrictionApplyAtPointsInElement(swarm_ceed_context->restriction_u_points, e, CEED_NOTRANSPOSE, swarm_ceed_context->u_points_loc, 9929dbcead6SJeremy L Thompson swarm_ceed_context->u_points_elem, CEED_REQUEST_IMMEDIATE); 9939dbcead6SJeremy L Thompson CeedBasisApplyAtPoints(swarm_ceed_context->basis_u, num_points_in_elem, CEED_TRANSPOSE, CEED_EVAL_INTERP, swarm_ceed_context->x_ref_points_elem, 9949dbcead6SJeremy L Thompson swarm_ceed_context->u_points_elem, swarm_ceed_context->u_mesh_elem); 9959dbcead6SJeremy L Thompson 9969dbcead6SJeremy L Thompson // -- Insert result back into local vector 9979dbcead6SJeremy L Thompson CeedElemRestrictionApplyBlock(swarm_ceed_context->restriction_u_mesh, e, CEED_TRANSPOSE, swarm_ceed_context->u_mesh_elem, 9989dbcead6SJeremy L Thompson swarm_ceed_context->v_mesh_loc, CEED_REQUEST_IMMEDIATE); 9999dbcead6SJeremy L Thompson } 10009dbcead6SJeremy L Thompson 10019dbcead6SJeremy L Thompson // Restore PETSc Vecs and Local to Global 10029dbcead6SJeremy L Thompson PetscCall(VecC2P(swarm_ceed_context->v_mesh_loc, B_mem_type, B_mesh_loc)); 10039dbcead6SJeremy L Thompson PetscCall(VecZeroEntries(B_mesh)); 10049dbcead6SJeremy L Thompson PetscCall(DMLocalToGlobal(dm_mesh, B_mesh_loc, ADD_VALUES, B_mesh)); 10059dbcead6SJeremy L Thompson 10069dbcead6SJeremy L Thompson // Cleanup 10079dbcead6SJeremy L Thompson PetscCall(DMSwarmPICFieldC2P(dm_swarm, field, swarm_ceed_context->u_points_loc)); 10089dbcead6SJeremy L Thompson PetscCall(DMSwarmSortRestoreAccess(dm_swarm)); 10099dbcead6SJeremy L Thompson PetscCall(DMRestoreLocalVector(dm_mesh, &B_mesh_loc)); 10109dbcead6SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 10119dbcead6SJeremy L Thompson } 10129dbcead6SJeremy L Thompson 10139dbcead6SJeremy L Thompson // ------------------------------------------------------------------------------------------------ 10149dbcead6SJeremy L Thompson // Swarm "mass matrix" 10159dbcead6SJeremy L Thompson // ------------------------------------------------------------------------------------------------ 10169dbcead6SJeremy L Thompson PetscErrorCode MatMult_SwarmMass(Mat A, Vec U_mesh, Vec V_mesh) { 10179dbcead6SJeremy L Thompson PetscInt num_elem; 10189dbcead6SJeremy L Thompson PetscMemType U_mem_type, V_mem_type; 10199dbcead6SJeremy L Thompson DM dm_mesh; 10209dbcead6SJeremy L Thompson Vec U_mesh_loc, V_mesh_loc; 10219dbcead6SJeremy L Thompson DMSwarmCeedContext swarm_ceed_context; 10229dbcead6SJeremy L Thompson 10239dbcead6SJeremy L Thompson PetscFunctionBeginUser; 10249dbcead6SJeremy L Thompson // Get mesh DM 10259dbcead6SJeremy L Thompson PetscCall(MatGetDM(A, &dm_mesh)); 10269dbcead6SJeremy L Thompson PetscCall(DMGetApplicationContext(dm_mesh, (void *)&swarm_ceed_context)); 10279dbcead6SJeremy L Thompson 10289dbcead6SJeremy L Thompson // Global to Local and get PETSc Vec access 10299dbcead6SJeremy L Thompson PetscCall(DMGetLocalVector(dm_mesh, &U_mesh_loc)); 10309dbcead6SJeremy L Thompson PetscCall(VecZeroEntries(U_mesh_loc)); 10319dbcead6SJeremy L Thompson PetscCall(DMGlobalToLocal(dm_mesh, U_mesh, INSERT_VALUES, U_mesh_loc)); 10329dbcead6SJeremy L Thompson PetscCall(VecReadP2C(U_mesh_loc, &U_mem_type, swarm_ceed_context->u_mesh_loc)); 10339dbcead6SJeremy L Thompson PetscCall(DMGetLocalVector(dm_mesh, &V_mesh_loc)); 10349dbcead6SJeremy L Thompson PetscCall(VecZeroEntries(V_mesh_loc)); 10359dbcead6SJeremy L Thompson PetscCall(VecP2C(V_mesh_loc, &V_mem_type, swarm_ceed_context->v_mesh_loc)); 10369dbcead6SJeremy L Thompson 10379dbcead6SJeremy L Thompson // Interpolate values to each swarm point, one element in the background mesh at a time 10389dbcead6SJeremy L Thompson CeedElemRestrictionGetNumElements(swarm_ceed_context->restriction_u_mesh, &num_elem); 10399dbcead6SJeremy L Thompson for (PetscInt e = 0; e < num_elem; e++) { 10409dbcead6SJeremy L Thompson PetscInt num_points_in_elem; 10419dbcead6SJeremy L Thompson 10429dbcead6SJeremy L Thompson CeedElemRestrictionGetNumPointsInElement(swarm_ceed_context->restriction_u_points, e, &num_points_in_elem); 10439dbcead6SJeremy L Thompson 10449dbcead6SJeremy L Thompson // -- Reference coordinates for swarm points in background mesh element 10459dbcead6SJeremy L Thompson CeedElemRestrictionApplyAtPointsInElement(swarm_ceed_context->restriction_x_points, e, CEED_NOTRANSPOSE, swarm_ceed_context->x_ref_points_loc, 10469dbcead6SJeremy L Thompson swarm_ceed_context->x_ref_points_elem, CEED_REQUEST_IMMEDIATE); 10479dbcead6SJeremy L Thompson 10489dbcead6SJeremy L Thompson // -- Interpolate values from current element in background mesh to swarm points 10499dbcead6SJeremy L Thompson // Note: This will only work for CPU backends at this time, as only CPU backends support ApplyBlock and ApplyAtPoints 10509dbcead6SJeremy L Thompson CeedElemRestrictionApplyBlock(swarm_ceed_context->restriction_u_mesh, e, CEED_NOTRANSPOSE, swarm_ceed_context->u_mesh_loc, 10519dbcead6SJeremy L Thompson swarm_ceed_context->u_mesh_elem, CEED_REQUEST_IMMEDIATE); 10529dbcead6SJeremy L Thompson CeedBasisApplyAtPoints(swarm_ceed_context->basis_u, num_points_in_elem, CEED_NOTRANSPOSE, CEED_EVAL_INTERP, swarm_ceed_context->x_ref_points_elem, 10539dbcead6SJeremy L Thompson swarm_ceed_context->u_mesh_elem, swarm_ceed_context->u_points_elem); 10549dbcead6SJeremy L Thompson 10559dbcead6SJeremy L Thompson // -- Interpolate transpose back from swarm points to mesh 10569dbcead6SJeremy L Thompson CeedBasisApplyAtPoints(swarm_ceed_context->basis_u, num_points_in_elem, CEED_TRANSPOSE, CEED_EVAL_INTERP, swarm_ceed_context->x_ref_points_elem, 10579dbcead6SJeremy L Thompson swarm_ceed_context->u_points_elem, swarm_ceed_context->u_mesh_elem); 10589dbcead6SJeremy L Thompson CeedElemRestrictionApplyBlock(swarm_ceed_context->restriction_u_mesh, e, CEED_TRANSPOSE, swarm_ceed_context->u_mesh_elem, 10599dbcead6SJeremy L Thompson swarm_ceed_context->v_mesh_loc, CEED_REQUEST_IMMEDIATE); 10609dbcead6SJeremy L Thompson } 10619dbcead6SJeremy L Thompson 10629dbcead6SJeremy L Thompson // Restore PETSc Vecs and Local to Global 10639dbcead6SJeremy L Thompson PetscCall(VecReadC2P(swarm_ceed_context->u_mesh_loc, U_mem_type, U_mesh_loc)); 10649dbcead6SJeremy L Thompson PetscCall(VecC2P(swarm_ceed_context->v_mesh_loc, V_mem_type, V_mesh_loc)); 10659dbcead6SJeremy L Thompson PetscCall(VecZeroEntries(V_mesh)); 10669dbcead6SJeremy L Thompson PetscCall(DMLocalToGlobal(dm_mesh, V_mesh_loc, ADD_VALUES, V_mesh)); 10679dbcead6SJeremy L Thompson 10689dbcead6SJeremy L Thompson // Cleanup 10699dbcead6SJeremy L Thompson PetscCall(DMRestoreLocalVector(dm_mesh, &U_mesh_loc)); 10709dbcead6SJeremy L Thompson PetscCall(DMRestoreLocalVector(dm_mesh, &V_mesh_loc)); 10719dbcead6SJeremy L Thompson PetscFunctionReturn(PETSC_SUCCESS); 10729dbcead6SJeremy L Thompson } 1073