diff --git a/Examples/Modules/embedded_boundary_python_API/PICMI_inputs_EB_API.py b/Examples/Modules/embedded_boundary_python_API/PICMI_inputs_EB_API.py new file mode 100644 index 00000000000..daabfece554 --- /dev/null +++ b/Examples/Modules/embedded_boundary_python_API/PICMI_inputs_EB_API.py @@ -0,0 +1,252 @@ +from pywarpx import picmi, _libwarpx, fields +import numpy as np + +max_steps = 1 +unit = 1e-3 + +################################## +# Define the mesh +################################## +# mesh cells per direction +nx = 64 +ny = 64 +nz = 64 + +# mesh bounds for domain +xmin = -32*unit +xmax = 32*unit +ymin = -32*unit +ymax = 32*unit +zmin = -32*unit +zmax = 32*unit + +########################## +# numerics components +########################## +lower_boundary_conditions = ['open', 'dirichlet', 'periodic'] +upper_boundary_conditions = ['open', 'dirichlet', 'periodic'] + +grid = picmi.Cartesian3DGrid( + number_of_cells = [nx, ny, nz], + lower_bound = [xmin, ymin, zmin], + upper_bound = [xmax, ymax, zmax], + lower_boundary_conditions = lower_boundary_conditions, + upper_boundary_conditions = upper_boundary_conditions, + lower_boundary_conditions_particles = ['absorbing', 'absorbing', 'periodic'], + upper_boundary_conditions_particles = ['absorbing', 'absorbing', 'periodic'], + moving_window_velocity = None, + warpx_max_grid_size = 64 +) + + +flag_correct_div = False + +solver = picmi.ElectromagneticSolver(grid=grid, method='Yee', cfl=1.) + +n_cavity=30 +L_cavity = n_cavity*unit + +embedded_boundary = picmi.EmbeddedBoundary( + implicit_function="max(max(max(x-L_cavity/2,-L_cavity/2-x),max(y-L_cavity/2,-L_cavity/2-y)),max(z-L_cavity/2,-L_cavity/2-z))", + L_cavity=L_cavity +) + + +########################## +# diagnostics +########################## + +field_diag = picmi.FieldDiagnostic( + name = 'diag1', + grid = grid, + period = 1, + data_list = ['Ex'], + write_dir = '.', + warpx_file_prefix = "embedded_boundary_python_API_plt" +) + +########################## +# simulation setup +########################## + +sim = picmi.Simulation( + solver = solver, + max_steps = max_steps, + warpx_embedded_boundary=embedded_boundary, + verbose = 1 +) + +sim.add_diagnostic(field_diag) + +sim.initialize_inputs() + +sim.step(1) + +print("======== Testing _libwarpx.get_mesh_edge_lengths =========") + +ly_slice_x = np.array(_libwarpx.get_mesh_edge_lengths(0,1,include_ghosts=False)[0])[int(nx/2),:,:] +lz_slice_x = np.array(_libwarpx.get_mesh_edge_lengths(0,2,include_ghosts=False)[0])[int(nx/2),:,:] + +n_edge_y_lo = int((ny - 30)/2) +n_edge_y_hi = int(ny - (ny - 30)/2) +n_edge_z_lo = int((nz - 30)/2) +n_edge_z_hi = int(nz - (nz - 30)/2) + +perimeter_slice_x = (np.sum(ly_slice_x[n_edge_y_lo:n_edge_y_hi, n_edge_z_lo+1]) + + np.sum(ly_slice_x[n_edge_y_lo:n_edge_y_hi, n_edge_z_hi-1]) + + np.sum(lz_slice_x[n_edge_y_lo+1, n_edge_z_lo:n_edge_z_hi]) + + np.sum(lz_slice_x[n_edge_y_hi-1, n_edge_z_lo:n_edge_z_hi])) + +perimeter_slice_x_true = L_cavity*4 + +print("Perimeter of the middle x-slice:", perimeter_slice_x) +assert np.isclose(perimeter_slice_x, perimeter_slice_x_true, rtol=1e-05, atol=1e-08) + + +lx_slice_y = np.array(_libwarpx.get_mesh_edge_lengths(0,0,include_ghosts=False)[0])[:,int(ny/2),:] +lz_slice_y = np.array(_libwarpx.get_mesh_edge_lengths(0,2,include_ghosts=False)[0])[:,int(ny/2),:] + +n_edge_x_lo = int((nx - 30)/2) +n_edge_x_hi = int(nx - (nx - 30)/2) +n_edge_z_lo = int((nz - 30)/2) +n_edge_z_hi = int(nz - (nz - 30)/2) + +perimeter_slice_y = (np.sum(lx_slice_y[n_edge_x_lo:n_edge_x_hi, n_edge_z_lo+1]) + + np.sum(lx_slice_y[n_edge_x_lo:n_edge_x_hi, n_edge_z_hi-1]) + + np.sum(lz_slice_y[n_edge_x_lo+1, n_edge_z_lo:n_edge_z_hi]) + + np.sum(lz_slice_y[n_edge_x_hi-1, n_edge_z_lo:n_edge_z_hi])) + +perimeter_slice_y_true = L_cavity*4 + + +print("Perimeter of the middle y-slice:", perimeter_slice_y) +assert np.isclose(perimeter_slice_y, perimeter_slice_y_true, rtol=1e-05, atol=1e-08) + + +lx_slice_z = np.array(_libwarpx.get_mesh_edge_lengths(0,0,include_ghosts=False)[0])[:,:,int(nz/2)] +ly_slice_z = np.array(_libwarpx.get_mesh_edge_lengths(0,1,include_ghosts=False)[0])[:,:,int(nz/2)] + +n_edge_x_lo = int((nx - 30)/2) +n_edge_x_hi = int(nx - (nx - 30)/2) +n_edge_y_lo = int((ny - 30)/2) +n_edge_y_hi = int(ny - (ny - 30)/2) + +perimeter_slice_z = (np.sum(lx_slice_z[n_edge_x_lo:n_edge_x_hi, n_edge_y_lo+1]) + + np.sum(lx_slice_z[n_edge_x_lo:n_edge_x_hi, n_edge_y_hi-1]) + + np.sum(ly_slice_z[n_edge_x_lo+1, n_edge_y_lo:n_edge_y_hi]) + + np.sum(ly_slice_z[n_edge_x_hi-1, n_edge_y_lo:n_edge_y_hi])) + +perimeter_slice_z_true = L_cavity*4 + +print("Perimeter of the middle z-slice:", perimeter_slice_z) +assert np.isclose(perimeter_slice_z, perimeter_slice_z_true, rtol=1e-05, atol=1e-08) + +print("======== Testing _libwarpx.get_mesh_face_areas =========") + +Sx_slice = np.sum(np.array(_libwarpx.get_mesh_face_areas(0,0,include_ghosts=False)[0])[int(nx/2),:,:]) +dx = (xmax-xmin)/nx +Ax = dx*dx +Sx_slice_true = L_cavity*L_cavity - 2*Ax +print("Area of the middle x-slice:", Sx_slice) +assert np.isclose(Sx_slice, Sx_slice_true, rtol=1e-05, atol=1e-08) + + +Sy_slice = np.sum(np.array(_libwarpx.get_mesh_face_areas(0,1,include_ghosts=False)[0])[:,int(ny/2),:]) +dy = (ymax-ymin)/ny +Ay = dy*dy +Sy_slice_true = L_cavity*L_cavity - 2*Ay +print("Area of the middle y-slice:", Sx_slice) +assert np.isclose(Sy_slice, Sy_slice_true, rtol=1e-05, atol=1e-08) + + +Sz_slice = np.sum(np.array(_libwarpx.get_mesh_face_areas(0,2,include_ghosts=False)[0])[:,:,int(nz/2)]) +dz = (zmax-zmin)/nz +Az = dz*dz +Sz_slice_true = L_cavity*L_cavity - 2*Az +print("Area of the middle z-slice:", Sz_slice) +assert np.isclose(Sz_slice, Sz_slice_true, rtol=1e-05, atol=1e-08) + +print("======== Testing the wrappers of m_edge_lengths =========") + +ly_slice_x = np.array(fields.EdgeLengthsyWrapper().get_fabs(0,1,include_ghosts=False)[0])[int(nx/2),:,:] +lz_slice_x = np.array(fields.EdgeLengthszWrapper().get_fabs(0,2,include_ghosts=False)[0])[int(nx/2),:,:] + +n_edge_y_lo = int((ny - 30)/2) +n_edge_y_hi = int(ny - (ny - 30)/2) +n_edge_z_lo = int((nz - 30)/2) +n_edge_z_hi = int(nz - (nz - 30)/2) + +perimeter_slice_x = (np.sum(ly_slice_x[n_edge_y_lo:n_edge_y_hi, n_edge_z_lo+1]) + + np.sum(ly_slice_x[n_edge_y_lo:n_edge_y_hi, n_edge_z_hi-1]) + + np.sum(lz_slice_x[n_edge_y_lo+1, n_edge_z_lo:n_edge_z_hi]) + + np.sum(lz_slice_x[n_edge_y_hi-1, n_edge_z_lo:n_edge_z_hi])) + +perimeter_slice_x_true = L_cavity*4 + +print("Perimeter of the middle x-slice:", perimeter_slice_x) +assert np.isclose(perimeter_slice_x, perimeter_slice_x_true, rtol=1e-05, atol=1e-08) + + +lx_slice_y = np.array(fields.EdgeLengthsxWrapper().get_fabs(0,0,include_ghosts=False)[0])[:,int(ny/2),:] +lz_slice_y = np.array(fields.EdgeLengthszWrapper().get_fabs(0,2,include_ghosts=False)[0])[:,int(ny/2),:] + +n_edge_x_lo = int((nx - 30)/2) +n_edge_x_hi = int(nx - (nx - 30)/2) +n_edge_z_lo = int((nz - 30)/2) +n_edge_z_hi = int(nz - (nz - 30)/2) + +perimeter_slice_y = (np.sum(lx_slice_y[n_edge_x_lo:n_edge_x_hi, n_edge_z_lo+1]) + + np.sum(lx_slice_y[n_edge_x_lo:n_edge_x_hi, n_edge_z_hi-1]) + + np.sum(lz_slice_y[n_edge_x_lo+1, n_edge_z_lo:n_edge_z_hi]) + + np.sum(lz_slice_y[n_edge_x_hi-1, n_edge_z_lo:n_edge_z_hi])) + +perimeter_slice_y_true = L_cavity*4 + + +print("Perimeter of the middle y-slice:", perimeter_slice_y) +assert np.isclose(perimeter_slice_y, perimeter_slice_y_true, rtol=1e-05, atol=1e-08) + + +lx_slice_z = np.array(fields.EdgeLengthsxWrapper().get_fabs(0,0,include_ghosts=False)[0])[:,:,int(nz/2)] +ly_slice_z = np.array(fields.EdgeLengthsyWrapper().get_fabs(0,1,include_ghosts=False)[0])[:,:,int(nz/2)] + +n_edge_x_lo = int((nx - 30)/2) +n_edge_x_hi = int(nx - (nx - 30)/2) +n_edge_y_lo = int((ny - 30)/2) +n_edge_y_hi = int(ny - (ny - 30)/2) + +perimeter_slice_z = (np.sum(lx_slice_z[n_edge_x_lo:n_edge_x_hi, n_edge_y_lo+1]) + + np.sum(lx_slice_z[n_edge_x_lo:n_edge_x_hi, n_edge_y_hi-1]) + + np.sum(ly_slice_z[n_edge_x_lo+1, n_edge_y_lo:n_edge_y_hi]) + + np.sum(ly_slice_z[n_edge_x_hi-1, n_edge_y_lo:n_edge_y_hi])) + +perimeter_slice_z_true = L_cavity*4 + +print("Perimeter of the middle z-slice:", perimeter_slice_z) +assert np.isclose(perimeter_slice_z, perimeter_slice_z_true, rtol=1e-05, atol=1e-08) + +print("======== Testing the wrappers of m_face_areas =========") + +Sx_slice = np.sum(np.array(fields.FaceAreasxWrapper().get_fabs(0,0,include_ghosts=False)[0])[int(nx/2),:,:]) +dx = (xmax-xmin)/nx +Ax = dx*dx +Sx_slice_true = L_cavity*L_cavity - 2*Ax +print("Area of the middle x-slice:", Sx_slice) +assert np.isclose(Sx_slice, Sx_slice_true, rtol=1e-05, atol=1e-08) + +Sy_slice = np.sum(np.array(fields.FaceAreasyWrapper().get_fabs(0,1,include_ghosts=False)[0])[:,int(ny/2),:]) +dy = (ymax-ymin)/ny +Ay = dy*dy +Sy_slice_true = L_cavity*L_cavity - 2*Ay +print("Area of the middle y-slice:", Sx_slice) +assert np.isclose(Sy_slice, Sy_slice_true, rtol=1e-05, atol=1e-08) + +Sz_slice = np.sum(np.array(fields.FaceAreaszWrapper().get_fabs(0,2,include_ghosts=False)[0])[:,:,int(nz/2)]) +dz = (zmax-zmin)/nz +Az = dz*dz +Sz_slice_true = L_cavity*L_cavity - 2*Az +print("Area of the middle z-slice:", Sz_slice) +assert np.isclose(Sz_slice, Sz_slice_true, rtol=1e-05, atol=1e-08) + +sim.step(1) + diff --git a/Examples/Modules/embedded_boundary_python_API/analysis.py b/Examples/Modules/embedded_boundary_python_API/analysis.py new file mode 100644 index 00000000000..b6b2955cf0f --- /dev/null +++ b/Examples/Modules/embedded_boundary_python_API/analysis.py @@ -0,0 +1,10 @@ +#! /usr/bin/env python + +# This script just checks that the PICMI file executed successfully. +# If it did there will be a plotfile for the final step. + +import sys + +step = int(sys.argv[1][-5:]) + +assert step == 2 diff --git a/Python/pywarpx/_libwarpx.py b/Python/pywarpx/_libwarpx.py index e32dc239d27..6850e1b28ac 100755 --- a/Python/pywarpx/_libwarpx.py +++ b/Python/pywarpx/_libwarpx.py @@ -214,6 +214,10 @@ def _array1d_from_pointer(pointer, dtype, size): libwarpx.warpx_getGfieldCPLoVects_PML.restype = _LP_c_int libwarpx.warpx_getGfieldFP_PML.restype = _LP_LP_c_real libwarpx.warpx_getGfieldFPLoVects_PML.restype = _LP_c_int +libwarpx.warpx_getEdgeLengths.restype = _LP_LP_c_real +libwarpx.warpx_getEdgeLengthsLoVects.restype = _LP_c_int +libwarpx.warpx_getFaceAreas.restype = _LP_LP_c_real +libwarpx.warpx_getFaceAreasLoVects.restype = _LP_c_int libwarpx.warpx_getParticleBoundaryBufferSize.restype = ctypes.c_int libwarpx.warpx_getParticleBoundaryBufferStructs.restype = _LP_LP_c_particlereal libwarpx.warpx_getParticleBoundaryBuffer.restype = _LP_LP_c_particlereal @@ -234,6 +238,12 @@ def _array1d_from_pointer(pointer, dtype, size): libwarpx.warpx_getG_nodal_flag.restype = _LP_c_int libwarpx.warpx_getF_pml_nodal_flag.restype = _LP_c_int libwarpx.warpx_getG_pml_nodal_flag.restype = _LP_c_int +libwarpx.warpx_get_edge_lengths_x_nodal_flag.restype = _LP_c_int +libwarpx.warpx_get_edge_lengths_y_nodal_flag.restype = _LP_c_int +libwarpx.warpx_get_edge_lengths_z_nodal_flag.restype = _LP_c_int +libwarpx.warpx_get_face_areas_x_nodal_flag.restype = _LP_c_int +libwarpx.warpx_get_face_areas_y_nodal_flag.restype = _LP_c_int +libwarpx.warpx_get_face_areas_z_nodal_flag.restype = _LP_c_int #libwarpx.warpx_getPMLSigma.restype = _LP_c_real #libwarpx.warpx_getPMLSigmaStar.restype = _LP_c_real @@ -1753,6 +1763,60 @@ def get_mesh_G_fp_pml(level, include_ghosts=True): raise Exception('PML not initialized') +def get_mesh_edge_lengths(level, direction, include_ghosts=True): + ''' + + This returns a list of numpy arrays containing the mesh edge lengths + data on each grid for this process. This version returns the density on + the fine patch for the given level. + + The data for the numpy arrays are not copied, but share the underlying + memory buffer with WarpX. The numpy arrays are fully writeable. + + Parameters + ---------- + + level : the AMR level to get the data for + direction : the component of the data you want + include_ghosts : whether to include ghost zones or not + + Returns + ------- + + A List of numpy arrays. + + ''' + + return _get_mesh_field_list(libwarpx.warpx_getEdgeLengths, level, direction, include_ghosts) + + +def get_mesh_face_areas(level, direction, include_ghosts=True): + ''' + + This returns a list of numpy arrays containing the mesh face areas + data on each grid for this process. This version returns the density on + the fine patch for the given level. + + The data for the numpy arrays are not copied, but share the underlying + memory buffer with WarpX. The numpy arrays are fully writeable. + + Parameters + ---------- + + level : the AMR level to get the data for + direction : the component of the data you want + include_ghosts : whether to include ghost zones or not + + Returns + ------- + + A List of numpy arrays. + + ''' + + return _get_mesh_field_list(libwarpx.warpx_getFaceAreas, level, direction, include_ghosts) + + def _get_mesh_array_lovects(level, direction, include_ghosts=True, getlovectsfunc=None): assert(0 <= level and level <= libwarpx.warpx_finestLevel()) @@ -2378,6 +2442,51 @@ def get_mesh_G_fp_lovects_pml(level, include_ghosts=True): except ValueError: raise Exception('PML not initialized') + +def get_mesh_edge_lengths_lovects(level, direction, include_ghosts=True): + ''' + + This returns a list of the lo vectors of the arrays containing the mesh edge lengths + data on each grid for this process. + + Parameters + ---------- + + level : the AMR level to get the data for + direction : the component of the data you want + include_ghosts : whether to include ghost zones or not + + Returns + ------- + + A 2d numpy array of the lo vector for each grid with the shape (dims, number of grids) + + ''' + return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.warpx_getEdgeLengthsLoVects) + + +def get_mesh_face_areas_lovects(level, direction, include_ghosts=True): + ''' + + This returns a list of the lo vectors of the arrays containing the mesh face areas + data on each grid for this process. + + Parameters + ---------- + + level : the AMR level to get the data for + direction : the component of the data you want + include_ghosts : whether to include ghost zones or not + + Returns + ------- + + A 2d numpy array of the lo vector for each grid with the shape (dims, number of grids) + + ''' + return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.warpx_getFaceAreasLoVects) + + def _get_nodal_flag(getdatafunc): data = getdatafunc() if not data: @@ -2480,6 +2589,42 @@ def get_G_nodal_flag(): ''' return _get_nodal_flag(libwarpx.warpx_getG_nodal_flag) +def get_edge_lengths_x_nodal_flag(): + ''' + This returns a 1d array of the nodal flags for the x edge lengths along each direction. A 1 means node centered, and 0 cell centered. + ''' + return _get_nodal_flag(libwarpx.warpx_get_edge_lengths_x_nodal_flag) + +def get_edge_lengths_y_nodal_flag(): + ''' + This returns a 1d array of the nodal flags for the y edge lengths along each direction. A 1 means node centered, and 0 cell centered. + ''' + return _get_nodal_flag(libwarpx.warpx_get_edge_lengths_y_nodal_flag) + +def get_edge_lengths_z_nodal_flag(): + ''' + This returns a 1d array of the nodal flags for the z edge lengths along each direction. A 1 means node centered, and 0 cell centered. + ''' + return _get_nodal_flag(libwarpx.warpx_get_edge_lengths_z_nodal_flag) + +def get_face_areas_x_nodal_flag(): + ''' + This returns a 1d array of the nodal flags for the x face areas along each direction. A 1 means node centered, and 0 cell centered. + ''' + return _get_nodal_flag(libwarpx.warpx_get_face_areas_x_nodal_flag) + +def get_face_areas_y_nodal_flag(): + ''' + This returns a 1d array of the nodal flags for the y face areas along each direction. A 1 means node centered, and 0 cell centered. + ''' + return _get_nodal_flag(libwarpx.warpx_get_face_areas_y_nodal_flag) + +def get_face_areas_z_nodal_flag(): + ''' + This returns a 1d array of the nodal flags for the z face areas along each direction. A 1 means node centered, and 0 cell centered. + ''' + return _get_nodal_flag(libwarpx.warpx_get_face_areas_z_nodal_flag) + def get_F_pml_nodal_flag(): ''' This returns a 1d array of the nodal flags for F in the PML along each direction. A 1 means node centered, and 0 cell centered. diff --git a/Python/pywarpx/fields.py b/Python/pywarpx/fields.py index 612ea32c0e0..cb63a8af4e0 100644 --- a/Python/pywarpx/fields.py +++ b/Python/pywarpx/fields.py @@ -682,6 +682,48 @@ def GFPWrapper(level=0, include_ghosts=False): get_nodal_flag=_libwarpx.get_G_nodal_flag, level=level, include_ghosts=include_ghosts) +def EdgeLengthsxWrapper(level=0, include_ghosts=False): + return _MultiFABWrapper(direction=0, + get_lovects=_libwarpx.get_mesh_edge_lengths_lovects, + get_fabs=_libwarpx.get_mesh_edge_lengths, + get_nodal_flag=_libwarpx.get_edge_lengths_x_nodal_flag, + level=level, include_ghosts=include_ghosts) + +def EdgeLengthsyWrapper(level=0, include_ghosts=False): + return _MultiFABWrapper(direction=1, + get_lovects=_libwarpx.get_mesh_edge_lengths_lovects, + get_fabs=_libwarpx.get_mesh_edge_lengths, + get_nodal_flag=_libwarpx.get_edge_lengths_y_nodal_flag, + level=level, include_ghosts=include_ghosts) + +def EdgeLengthszWrapper(level=0, include_ghosts=False): + return _MultiFABWrapper(direction=2, + get_lovects=_libwarpx.get_mesh_edge_lengths_lovects, + get_fabs=_libwarpx.get_mesh_edge_lengths, + get_nodal_flag=_libwarpx.get_edge_lengths_z_nodal_flag, + level=level, include_ghosts=include_ghosts) + +def FaceAreasxWrapper(level=0, include_ghosts=False): + return _MultiFABWrapper(direction=0, + get_lovects=_libwarpx.get_mesh_face_areas_lovects, + get_fabs=_libwarpx.get_mesh_face_areas, + get_nodal_flag=_libwarpx.get_face_areas_x_nodal_flag, + level=level, include_ghosts=include_ghosts) + +def FaceAreasyWrapper(level=0, include_ghosts=False): + return _MultiFABWrapper(direction=1, + get_lovects=_libwarpx.get_mesh_face_areas_lovects, + get_fabs=_libwarpx.get_mesh_face_areas, + get_nodal_flag=_libwarpx.get_face_areas_y_nodal_flag, + level=level, include_ghosts=include_ghosts) + +def FaceAreaszWrapper(level=0, include_ghosts=False): + return _MultiFABWrapper(direction=2, + get_lovects=_libwarpx.get_mesh_face_areas_lovects, + get_fabs=_libwarpx.get_mesh_face_areas, + get_nodal_flag=_libwarpx.get_face_areas_z_nodal_flag, + level=level, include_ghosts=include_ghosts) + def ExCPPMLWrapper(level=1, include_ghosts=False): assert level>0, Exception('Coarse patch only available on levels > 0') return _MultiFABWrapper(direction=0, diff --git a/Regression/WarpX-tests.ini b/Regression/WarpX-tests.ini index 0d4d1e99736..44eac6ab75c 100644 --- a/Regression/WarpX-tests.ini +++ b/Regression/WarpX-tests.ini @@ -2887,3 +2887,20 @@ compileTest = 0 doVis = 0 compareParticles = 0 analysisRoutine = Examples/analysis_default_regression.py + +[embedded_boundary_python_API] +buildDir = . +inputFile = Examples/Modules/embedded_boundary_python_API/PICMI_inputs_EB_API.py +runtime_params = +customRunCmd = python PICMI_inputs_EB_API.py +dim = 3 +addToCompileString = USE_EB=TRUE +restartTest = 0 +useMPI = 1 +numprocs = 1 +useOMP = 1 +numthreads = 1 +compileTest = 0 +doVis = 0 +compareParticles = 0 +analysisRoutine = Examples/Modules/embedded_boundary_python_API/analysis.py \ No newline at end of file diff --git a/Source/Python/WarpXWrappers.H b/Source/Python/WarpXWrappers.H index 6897ae212f6..42066b6729d 100644 --- a/Source/Python/WarpXWrappers.H +++ b/Source/Python/WarpXWrappers.H @@ -172,6 +172,12 @@ extern "C" { int* warpx_getCurrentDensityCPLoVects (int lev, int direction, int *return_size, int **ngrowvect); int* warpx_getCurrentDensityFPLoVects (int lev, int direction, int *return_size, int **ngrowvect); + amrex::Real** warpx_getEdgeLengths (int lev, int direction, int *return_size, int *ncomps, int **ngrowvect, int **shapes); + int* warpx_getEdgeLengthsLoVects (int lev, int direction, int *return_size, int **ngrowvect); + + amrex::Real** warpx_getFaceAreas (int lev, int direction, int *return_size, int *ncomps, int **ngrowvect, int **shapes); + int* warpx_getFaceAreasLoVects (int lev, int direction, int *return_size, int **ngrowvect); + int* warpx_getEx_nodal_flag (); int* warpx_getEy_nodal_flag (); int* warpx_getEz_nodal_flag (); @@ -185,6 +191,12 @@ extern "C" { int* warpx_getPhi_nodal_flag (); int* warpx_getF_nodal_flag (); int* warpx_getG_nodal_flag (); + int* warpx_get_edge_lengths_x_nodal_flag (); + int* warpx_get_edge_lengths_y_nodal_flag (); + int* warpx_get_edge_lengths_z_nodal_flag (); + int* warpx_get_face_areas_x_nodal_flag (); + int* warpx_get_face_areas_y_nodal_flag (); + int* warpx_get_face_areas_z_nodal_flag (); amrex::Real** warpx_getChargeDensityCP (int lev, int *return_size, int *ncomps, int **ngrowvect, int **shapes); amrex::Real** warpx_getChargeDensityFP (int lev, int *return_size, int *ncomps, int **ngrowvect, int **shapes); diff --git a/Source/Python/WarpXWrappers.cpp b/Source/Python/WarpXWrappers.cpp index ba78d22333b..a2b8dc354df 100644 --- a/Source/Python/WarpXWrappers.cpp +++ b/Source/Python/WarpXWrappers.cpp @@ -323,6 +323,9 @@ namespace WARPX_GET_FIELD(warpx_getBfieldCP, WarpX::GetInstance().get_pointer_Bfield_cp) WARPX_GET_FIELD(warpx_getBfieldFP, WarpX::GetInstance().get_pointer_Bfield_fp) + WARPX_GET_FIELD(warpx_getEdgeLengths, WarpX::GetInstance().get_pointer_edge_lengths) + WARPX_GET_FIELD(warpx_getFaceAreas, WarpX::GetInstance().get_pointer_face_areas) + WARPX_GET_FIELD(warpx_getCurrentDensity, WarpX::GetInstance().get_pointer_current_fp) WARPX_GET_FIELD(warpx_getCurrentDensityCP, WarpX::GetInstance().get_pointer_current_cp) WARPX_GET_FIELD(warpx_getCurrentDensityFP, WarpX::GetInstance().get_pointer_current_fp) @@ -339,6 +342,9 @@ namespace WARPX_GET_LOVECTS(warpx_getCurrentDensityCPLoVects, WarpX::GetInstance().get_pointer_current_cp) WARPX_GET_LOVECTS(warpx_getCurrentDensityFPLoVects, WarpX::GetInstance().get_pointer_current_fp) + WARPX_GET_LOVECTS(warpx_getEdgeLengthsLoVects, WarpX::GetInstance().get_pointer_edge_lengths) + WARPX_GET_LOVECTS(warpx_getFaceAreasLoVects, WarpX::GetInstance().get_pointer_face_areas) + int* warpx_getEx_nodal_flag() {return getFieldNodalFlagData( WarpX::GetInstance().get_pointer_Efield_aux(0,0) );} int* warpx_getEy_nodal_flag() {return getFieldNodalFlagData( WarpX::GetInstance().get_pointer_Efield_aux(0,1) );} int* warpx_getEz_nodal_flag() {return getFieldNodalFlagData( WarpX::GetInstance().get_pointer_Efield_aux(0,2) );} @@ -352,6 +358,12 @@ namespace int* warpx_getPhi_nodal_flag() {return getFieldNodalFlagData( WarpX::GetInstance().get_pointer_phi_fp(0) );} int* warpx_getF_nodal_flag() {return getFieldNodalFlagData( WarpX::GetInstance().get_pointer_F_fp(0) );} int* warpx_getG_nodal_flag() {return getFieldNodalFlagData( WarpX::GetInstance().get_pointer_G_fp(0) );} + int* warpx_get_edge_lengths_x_nodal_flag() {return getFieldNodalFlagData( WarpX::GetInstance().get_pointer_edge_lengths(0, 0) );} + int* warpx_get_edge_lengths_y_nodal_flag() {return getFieldNodalFlagData( WarpX::GetInstance().get_pointer_edge_lengths(0, 1) );} + int* warpx_get_edge_lengths_z_nodal_flag() {return getFieldNodalFlagData( WarpX::GetInstance().get_pointer_edge_lengths(0, 2) );} + int* warpx_get_face_areas_x_nodal_flag() {return getFieldNodalFlagData( WarpX::GetInstance().get_pointer_face_areas(0, 0) );} + int* warpx_get_face_areas_y_nodal_flag() {return getFieldNodalFlagData( WarpX::GetInstance().get_pointer_face_areas(0, 1) );} + int* warpx_get_face_areas_z_nodal_flag() {return getFieldNodalFlagData( WarpX::GetInstance().get_pointer_face_areas(0, 2) );} #define WARPX_GET_SCALAR(SCALAR, GETTER) \ amrex::Real** SCALAR(int lev, \ diff --git a/Source/WarpX.H b/Source/WarpX.H index 31e66e48e65..dd10d34f61d 100644 --- a/Source/WarpX.H +++ b/Source/WarpX.H @@ -321,6 +321,9 @@ public: amrex::MultiFab * get_pointer_F_cp (int lev) const { return F_cp[lev].get(); } amrex::MultiFab * get_pointer_G_cp (int lev) const { return G_cp[lev].get(); } + amrex::MultiFab * get_pointer_edge_lengths (int lev, int direction) const { return m_edge_lengths[lev][direction].get(); } + amrex::MultiFab * get_pointer_face_areas (int lev, int direction) const { return m_face_areas[lev][direction].get(); } + const amrex::MultiFab& getcurrent (int lev, int direction) {return *current_fp[lev][direction];} const amrex::MultiFab& getEfield (int lev, int direction) {return *Efield_aux[lev][direction];} const amrex::MultiFab& getBfield (int lev, int direction) {return *Bfield_aux[lev][direction];}