Compare commits

...

7 Commits

Author SHA1 Message Date
Jan Petykiewicz 4b798893bc Use python3 for setup 6 years ago
Jan Petykiewicz 3cd26265bd Use readme as long_description 6 years ago
Jan Petykiewicz 8360f98395 Move version string into module 6 years ago
Jan Petykiewicz b62cd6e867 move code to new location 6 years ago
jan c96d367502 fixup package info 7 years ago
Jan Petykiewicz 1d5e7ff3bb minor cleanup of generated source 7 years ago
Jan Petykiewicz 4ffa5e4a66 use logging package for output, and remove 'verbose' options 7 years ago

@ -38,12 +38,12 @@ generalization to multiple GPUs should be pretty straightforward
* numpy
* pyopencl
* jinja2
* [fdfd_tools](https://mpxd.net/gogs/jan/fdfd_tools) (>=0.2)
* [fdfd_tools](https://mpxd.net/code/jan/fdfd_tools) (>=0.2)
Install with pip, via git:
```bash
pip install git+https://mpxd.net/gogs/jan/opencl_fdfd.git@release
pip install git+https://mpxd.net/code/jan/opencl_fdfd.git@release
```

@ -31,7 +31,7 @@
Dependencies:
- fdfd_tools ( https://mpxd.net/gogs/jan/fdfd_tools )
- fdfd_tools ( https://mpxd.net/code/jan/fdfd_tools )
- numpy
- pyopencl
- jinja2
@ -41,3 +41,4 @@ from .main import cg_solver
__author__ = 'Jan Petykiewicz'
version = '0.3'

@ -16,6 +16,7 @@ satisfy the constraints for the 'conjugate gradient' algorithm
from typing import Dict, Any
import time
import logging
import numpy
from numpy.linalg import norm
@ -27,6 +28,11 @@ import fdfd_tools.solvers
from . import ops
__author__ = 'Jan Petykiewicz'
logger = logging.getLogger(__name__)
class CSRMatrix(object):
"""
Matrix stored in Compressed Sparse Row format, in GPU RAM.
@ -49,7 +55,6 @@ def cg(A: 'scipy.sparse.csr_matrix',
err_threshold: float = 1e-6,
context: pyopencl.Context = None,
queue: pyopencl.CommandQueue = None,
verbose: bool = False,
) -> numpy.ndarray:
"""
General conjugate-gradient solver for sparse matrices, where A @ x = b.
@ -60,7 +65,6 @@ def cg(A: 'scipy.sparse.csr_matrix',
:param err_threshold: Error threshold for successful solve, relative to norm(b)
:param context: PyOpenCL context. Will be created if not given.
:param queue: PyOpenCL command queue. Will be created if not given.
:param verbose: Whether to print statistics to screen.
:return: Solution vector x; returned even if solve doesn't converge.
"""
@ -102,13 +106,11 @@ def cg(A: 'scipy.sparse.csr_matrix',
_, err2 = rhoerr_step(r, [])
b_norm = numpy.sqrt(err2)
if verbose:
print('b_norm check: ', b_norm)
logging.debug('b_norm check: ', b_norm)
success = False
for k in range(max_iters):
if verbose:
print('[{:06d}] rho {:.4} alpha {:4.4}'.format(k, rho, alpha), end=' ')
logging.debug('[{:06d}] rho {:.4} alpha {:4.4}'.format(k, rho, alpha))
rho_prev = rho
e = xr_step(x, p, r, v, alpha, [])
@ -116,8 +118,7 @@ def cg(A: 'scipy.sparse.csr_matrix',
errs += [numpy.sqrt(err2) / b_norm]
if verbose:
print('err', errs[-1])
logging.debug('err {}'.format(errs[-1]))
if errs[-1] < err_threshold:
success = True
@ -128,7 +129,7 @@ def cg(A: 'scipy.sparse.csr_matrix',
alpha = rho / dot(p, v, e)
if verbose and k % 1000 == 0:
print(k)
logging.info('iteration {}'.format(k))
'''
Done solving
@ -137,17 +138,16 @@ def cg(A: 'scipy.sparse.csr_matrix',
x = x.get()
if verbose:
if success:
print('Success', end='')
else:
print('Failure', end=', ')
print(', {} iterations in {} sec: {} iterations/sec \
'.format(k, time_elapsed, k / time_elapsed))
print('final error', errs[-1])
print('overhead {} sec'.format(start_time2 - start_time))
if success:
logging.info('Solve success')
else:
logging.warning('Solve failure')
logging.info('{} iterations in {} sec: {} iterations/sec \
'.format(k, time_elapsed, k / time_elapsed))
logging.debug('final error {}'.format(errs[-1]))
logging.debug('overhead {} sec'.format(start_time2 - start_time))
print('Final residual:', norm(A @ x - b) / norm(b))
logging.info('Final residual: {}'.format(norm(A @ x - b) / norm(b)))
return x

@ -31,7 +31,7 @@ __global char *pmc_z = pmc + ZZ;
//Update H components; set them to 0 if PMC is enabled at that location.
//Mu division and PMC conditional are only included if {{mu}} and {{pmc}} are true
//Mu division and PMC conditional are only included if {mu} and {pmc} are true
{% if pmc -%}
if (pmc_x[i] != 0) {
Hx[i] = zero;
@ -42,9 +42,9 @@ if (pmc_x[i] != 0) {
ctype Dyz = mul(sub(Ey[i + pz], Ey[i]), inv_dez[z]);
ctype x_curl = sub(Dzy, Dyz);
{%- if mu -%}
{%- if mu %}
Hx[i] = mul(inv_mu_x[i], x_curl);
{%- else -%}
{%- else %}
Hx[i] = x_curl;
{%- endif %}
}
@ -59,9 +59,9 @@ if (pmc_y[i] != 0) {
ctype Dzx = mul(sub(Ez[i + px], Ez[i]), inv_dex[x]);
ctype y_curl = sub(Dxz, Dzx);
{%- if mu -%}
{%- if mu %}
Hy[i] = mul(inv_mu_y[i], y_curl);
{%- else -%}
{%- else %}
Hy[i] = y_curl;
{%- endif %}
}
@ -76,9 +76,9 @@ if (pmc_z[i] != 0) {
ctype Dxy = mul(sub(Ex[i + py], Ex[i]), inv_dey[y]);
ctype z_curl = sub(Dyx, Dxy);
{%- if mu -%}
{%- if mu %}
Hz[i] = mul(inv_mu_z[i], z_curl);
{%- else -%}
{%- else %}
Hz[i] = z_curl;
{%- endif %}
}

@ -8,6 +8,7 @@ a matrix).
from typing import List
import time
import logging
import numpy
from numpy.linalg import norm
@ -18,8 +19,11 @@ import fdfd_tools.operators
from . import ops
__author__ = 'Jan Petykiewicz'
logger = logging.getLogger(__name__)
def cg_solver(omega: complex,
dxes: List[List[numpy.ndarray]],
@ -32,7 +36,6 @@ def cg_solver(omega: complex,
max_iters: int = 40000,
err_threshold: float = 1e-6,
context: pyopencl.Context = None,
verbose: bool = False,
) -> numpy.ndarray:
"""
OpenCL FDFD solver using the iterative conjugate gradient (cg) method
@ -57,7 +60,6 @@ def cg_solver(omega: complex,
:param err_threshold: If (r @ r.conj()) / norm(1j * omega * J) < err_threshold, success.
Default 1e-6.
:param context: PyOpenCL context to run in. If not given, construct a new context.
:param verbose: If True, print progress to stdout. Default False.
:return: E-field which solves the system. Returned even if we did not converge.
"""
@ -171,12 +173,13 @@ def cg_solver(omega: complex,
_, err2 = rhoerr_step(r, [])
b_norm = numpy.sqrt(err2)
print('b_norm check: ', b_norm)
logging.debug('b_norm check: {}'.format(b_norm))
success = False
for k in range(max_iters):
if verbose:
print('[{:06d}] rho {:.4} alpha {:4.4}'.format(k, rho, alpha), end=' ')
do_print = (k % 100 == 0)
if do_print:
logger.debug('[{:06d}] rho {:.4} alpha {:4.4}'.format(k, rho, alpha))
rho_prev = rho
e = xr_step(x, p, r, v, alpha, [])
@ -184,8 +187,8 @@ def cg_solver(omega: complex,
errs += [numpy.sqrt(err2) / b_norm]
if verbose:
print('err', errs[-1])
if do_print:
logger.debug('err {}'.format(errs[-1]))
if errs[-1] < err_threshold:
success = True
@ -196,7 +199,7 @@ def cg_solver(omega: complex,
alpha = rho / dot(p, v, e)
if k % 1000 == 0:
print(k)
logger.info('iteration {}'.format(k))
'''
Done solving
@ -210,18 +213,18 @@ def cg_solver(omega: complex,
x = (Pr * x).get()
if success:
print('Success', end='')
logger.info('Solve success')
else:
print('Failure', end=', ')
print(', {} iterations in {} sec: {} iterations/sec \
logger.warning('Solve failure')
logger.info('{} iterations in {} sec: {} iterations/sec \
'.format(k, time_elapsed, k / time_elapsed))
print('final error', errs[-1])
print('overhead {} sec'.format(start_time2 - start_time))
logger.debug('final error {}'.format(errs[-1]))
logger.debug('overhead {} sec'.format(start_time2 - start_time))
A0 = fdfd_tools.operators.e_full(omega, dxes, epsilon, mu).tocsr()
if adjoint:
# Remember we conjugated all the contents of A earlier
A0 = A0.T
print('Post-everything residual:', norm(A0 @ x - b) / norm(b))
logger.info('Post-everything residual: {}'.format(norm(A0 @ x - b) / norm(b)))
return x

@ -8,6 +8,7 @@ See kernels/ for any of the .cl files loaded in this file.
"""
from typing import List, Callable
import logging
import numpy
import jinja2
@ -18,6 +19,8 @@ from pyopencl.elementwise import ElementwiseKernel
from pyopencl.reduction import ReductionKernel
logger = logging.getLogger(__name__)
# Create jinja2 env on module load
jinja_env = jinja2.Environment(loader=jinja2.PackageLoader(__name__, 'kernels'))
@ -145,6 +148,11 @@ def create_a(context: pyopencl.Context,
e2 = H2E_kernel(E, H, oeps, Pl, pec, *idxes[1], wait_for=[e2])
return [e2]
logger.debug('Preamble: \n{}'.format(preamble))
logger.debug('p2e: \n{}'.format(p2e_source))
logger.debug('e2h: \n{}'.format(e2h_source))
logger.debug('h2e: \n{}'.format(h2e_source))
return spmv

@ -1,14 +1,23 @@
#!/usr/bin/env python
#!/usr/bin/env python3
from setuptools import setup, find_packages
import opencl_fdfd
with open('README.md', 'r') as f:
long_description = f.read()
setup(name='opencl_fdfd',
version='0.3',
description='Opencl FDFD solver',
version=opencl_fdfd.version,
description='OpenCL FDFD solver',
long_description=long_description,
long_description_content_type='text/markdown',
author='Jan Petykiewicz',
author_email='anewusername@gmail.com',
url='https://mpxd.net/gogs/jan/opencl_fdfd',
url='https://mpxd.net/code/jan/opencl_fdfd',
packages=find_packages(),
package_data={
'opencl_fdfd': ['kernels/*']
},
install_requires=[
'numpy',
'pyopencl',

Loading…
Cancel
Save