aboutsummaryrefslogtreecommitdiff
path: root/Source/Utils/check_interp_points_and_weights.py
diff options
context:
space:
mode:
authorGravatar Edoardo Zoni <59625522+EZoni@users.noreply.github.com> 2020-05-11 08:01:49 -0700
committerGravatar GitHub <noreply@github.com> 2020-05-11 08:01:49 -0700
commite2eb322f5856994102237c8903781a5b3f77dd58 (patch)
tree2744f0ae6735ce2c427f344f72a90724c4f7f8af /Source/Utils/check_interp_points_and_weights.py
parentec3c2aab43130d96c599e38474e3467b47a4bfcd (diff)
downloadWarpX-e2eb322f5856994102237c8903781a5b3f77dd58.tar.gz
WarpX-e2eb322f5856994102237c8903781a5b3f77dd58.tar.zst
WarpX-e2eb322f5856994102237c8903781a5b3f77dd58.zip
Generalize coarsening for MR (#945)
* Move interpolation functions for MR to new folder * Preparatory clean-up of old namespace Average for future MR functions * Add interpolation for MR in new namespace Coarsen * Change file names Average.H/.cpp to Coarsen.H/.cpp * Remove Source/Parallelization/WarpXComm.H (not necessary anymore) * Coarsening for IO and MR in separate files * Clean up IO and MR Coarsen namespaces * Remove old interpolation functions (charge and current) * Void commit: trigger Travis CI build * Fix GPU build * Void commit: trigger Travis CI build * Add Python script to test interpolation points/weights in 1D * Move using-directives inside namespaces * Add Doxygen documentation and comments * Minor style changes * Improve new Python script
Diffstat (limited to 'Source/Utils/check_interp_points_and_weights.py')
-rw-r--r--Source/Utils/check_interp_points_and_weights.py187
1 files changed, 187 insertions, 0 deletions
diff --git a/Source/Utils/check_interp_points_and_weights.py b/Source/Utils/check_interp_points_and_weights.py
new file mode 100644
index 000000000..13b429050
--- /dev/null
+++ b/Source/Utils/check_interp_points_and_weights.py
@@ -0,0 +1,187 @@
+# Copyright 2020 Edoardo Zoni
+#
+# This file is part of WarpX
+#
+# License: BSD-3-Clause-LBNL
+
+#-------------------------------------------------------------------------------
+# Compute interpolation points and weights for coarsening and refinement in IO
+# and MR applications in 1D (extensions to 2D and 3D are trivial). Weights are
+# computed in order to guarantee total charge conservation for both cell-centered
+# data (equal weights) and nodal data (weights depend on distance between points
+# on fine and coarse grids).
+#
+# Notation:
+# - index i refers to points on coarse grid
+# - index ii refers to points on fine grid
+# - sc denotes the staggering of the coarse data
+# - sf denotes the staggering of the fine data
+# - cr denotes the coarsening ratio (must be cr=1,2,4 only)
+#
+# For MR applications only the cases sc=sf=0 and sc=sf=1 are considered. Terms
+# multiplied by (1-sf)*(1-sc) are ON for cell-centered data and OFF for nodal data,
+# while terms multiplied by sf*sc are ON for nodal data and OFF for cell-centered
+# data. C++ implementation in Source/Utils/CoarsenMR.H/.cpp and Source/Utils/CoarsenIO.H/.cpp
+#-------------------------------------------------------------------------------
+
+import numpy as np
+import sys
+
+# Fine grid limits (without ghost cells)
+def fine_grid_limits( sf ):
+ if ( sf == 0 ): # cell-centered
+ iimin = 0
+ iimax = 7
+ elif ( sf == 1 ): # nodal
+ iimin = 0
+ iimax = 8
+ return [ iimin, iimax ]
+
+# Coarse grid limits (without ghost cells)
+def coarse_grid_limits( sc, sf, iimin, iimax ):
+ imin = int( iimin/cr )
+ imax = int( iimax/cr )-(1-sc)*sf+(1-sf)*sc
+ return [ imin, imax ]
+
+# Coarsening for MR: interpolation points and weights
+def coarsening_points_and_weights( i, sc, sf, cr ):
+ if ( cr==1 ):
+ numpts = 1
+ idxmin = i
+ elif ( cr>=2 ):
+ numpts = cr*(1-sf)*(1-sc)+(2*(cr-1)+1)*sf*sc
+ idxmin = i*cr*(1-sf)*(1-sc)+(i*cr-cr+1)*sf*sc
+ weights = np.zeros( numpts )
+ for ir in range( numpts ):
+ ii = idxmin+ir
+ weights[ir] = (1/cr)*(1-sf)*(1-sc)+((abs(cr-abs(ii-i*cr)))/(cr*cr))*sf*sc
+ return [ numpts, idxmin, weights ]
+
+# Refinement for MR: interpolation points and weights
+def refinement_points_and_weights( ii, sc, sf, cr ):
+ if ( cr==1 ):
+ numpts = 1
+ idxmin = ii
+ elif ( cr>=2 ):
+ if ( ii%cr==0 ):
+ numpts = (1-sf)*(1-sc)+sf*sc
+ elif ( ii%cr!=0 ):
+ numpts = (1-sf)*(1-sc)+2*sf*sc
+ idxmin = (ii//cr)*(1-sf)*(1-sc)+(ii//cr)*sf*sc
+ weights = np.zeros( numpts )
+ for ir in range( numpts ):
+ i = idxmin+ir
+ if ( ii==iimin or ii==iimax ):
+ weights[ir] = (1-sf)*(1-sc)+((abs(cr-abs(ii-i*cr)))/(cr)+(cr/2-0.5))*sf*sc
+ else:
+ weights[ir] = (1-sf)*(1-sc)+((abs(cr-abs(ii-i*cr)))/(cr))*sf*sc
+ return [ numpts, idxmin, weights ]
+
+## TODO Coarsening for IO: interpolation points and weights
+#def coarsening_points_and_weights_for_IO( i, sf, sc, cr ):
+# if ( cr==1 ):
+# numpts = 1+abs(sf-sc)
+# idxmin = i-sc*(1-sf)
+# elif ( cr>=2 ):
+# numpts = 2-sf
+# idxmin = i*cr+cr//2*(1-sc)-(1-sf)
+# weights = np.zeros( numpts )
+# for ir in range( numpts ):
+# weights[ir] = (1/numpts)*(1-sf)*(1-sc)+(1/numpts)*sf*sc
+# return [ numpts, idxmin, weights ]
+
+#-------------------------------------------------------------------------------
+# Main
+#-------------------------------------------------------------------------------
+
+# Input coarsening ratio
+cr = int( input( "\n Select coarsening ratio (cr=1,2,4): cr=" ) )
+if ( cr!=1 and cr!=2 and cr!=4 ):
+ print()
+ sys.exit( 'coarsening ratio cr={} is not valid'.format( cr ) )
+
+# Loop over possible staggering of coarse and fine grid (cell-centered or nodal)
+for sc in [0,1]:
+ for sf in [0,1]:
+
+ print( '\n **************************************************' )
+ print( ' * Staggering of coarse grid: sc={}'.format( sc ), end='' )
+ if ( sc == 0 ):
+ print( ' cell-centered *' )
+ elif ( sc == 1 ):
+ print( ' nodal *' )
+ print( ' * Staggering of fine grid: sf={}'.format( sf ), end='' )
+ if ( sf == 0 ):
+ print( ' cell-centered *' )
+ elif ( sf == 1 ):
+ print( ' nodal *' )
+ print( ' **************************************************' )
+
+ iimin,iimax = fine_grid_limits( sf )
+ imin ,imax = coarse_grid_limits( sc, sf, iimin, iimax )
+
+ print( '\n Min and max index on coarse grid: imin={} imax={}'.format( imin, imax ) )
+ print( ' Min and max index on fine grid: iimin={} iimax={}'.format( iimin, iimax ) )
+
+ # Number of grid points
+ nc = imax-imin+1
+ nf = iimax-iimin+1
+
+ print( '\n Number of points on coarse grid: nc={}'.format( nc ) )
+ print( ' Number of points on fine grid: nf={}'.format( nf ) )
+
+ if ( sf!=sc ):
+ print( '\n WARNING: sc={} not equal to sf={}, not implemented for MR, continue ...'.format( sc, sf ) )
+ continue
+
+ print( '\n Coarsening for MR: check interpolation points and weights' )
+ print( ' ---------------------------------------------------------' )
+
+ # Coarsening for MR: interpolation points and weights
+ for i in range ( nc ): # index on coarse grid
+ numpts,idxmin,weights = coarsening_points_and_weights( i, sc, sf, cr )
+ print( '\n Find value at i={} by interpolating over the following points and weights:'.format( i ) )
+ for ir in range( numpts ): # interpolation points and weights
+ ii = idxmin+ir
+ print( ' ({},{})'.format( ii, weights[ir] ), end='' )
+ if not ( ir == numpts-1 ):
+ print( ' ', end='' )
+ print()
+
+ # Coarsening for MR: check conservation properties
+ for ii in range( nf ): # index on fine grid
+ ws = 0.0
+ for i in range( nc ): # index on coarse grid
+ numpts,idxmin,weights = coarsening_points_and_weights( i, sc, sf, cr )
+ for ir in range( numpts ): # interpolation points and weights
+ jj = idxmin+ir
+ if ( jj==ii ): # interpolation point matches point on fine grid
+ ws += weights[ir]
+ if ( ws!=1.0/cr ):
+ print( '\n ERROR: sum of weights ws={} should be 1/cr'.format( ws ) )
+
+ print( '\n Refinement for MR: check interpolation points and weights' )
+ print( ' ---------------------------------------------------------' )
+
+ # Refinement for MR: interpolation points and weights
+ for ii in range ( nf ): # index on fine grid
+ numpts,idxmin,weights = refinement_points_and_weights( ii, sc, sf, cr )
+ print( '\n Find value at ii={} by interpolating over the following points and weights:'.format( ii ) )
+ for ir in range( numpts ): # interpolation points and weights
+ i = idxmin+ir
+ print( ' ({},{})'.format( i, weights[ir] ), end='' )
+ if not ( ir == numpts-1 ):
+ print( ' ', end='' )
+ print()
+
+ # Refinement for MR: check conservation properties
+ for i in range( nc ): # index on coarse grid
+ ws = 0.0
+ for ii in range( nf ): # index on fine grid
+ numpts,idxmin,weights = refinement_points_and_weights( ii, sc, sf, cr )
+ for ir in range( numpts ): # interpolation points and weights
+ jj = idxmin+ir
+ if ( jj==i ): # interpolation point matches point on coarse grid
+ ws += weights[ir]
+ if ( ws!=cr ):
+ print( '\n ERROR: sum of weights ws={} should be cr'.format( ws ) )