|
| 1 | +#!/usr/bin/env python3 |
| 2 | +################################################################################### |
| 3 | +# Copyright 2021 National Technology & Engineering Solutions of Sandia, # |
| 4 | +# LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the # |
| 5 | +# U.S. Government retains certain rights in this software. # |
| 6 | +# If you want to use this code, please refer to the README.rst and LICENSE files. # |
| 7 | +################################################################################### |
| 8 | + |
| 9 | +from PyNucleus.packageTools.sphinxTools import codeRegionManager |
| 10 | + |
| 11 | +mgr = codeRegionManager() |
| 12 | + |
| 13 | +with mgr.add('preamble'): |
| 14 | + ###################################################################### |
| 15 | + # preamble |
| 16 | + import logging |
| 17 | + from PyNucleus_base.utilsFem import TimerManager |
| 18 | + from PyNucleus import meshFactory, dofmapFactory, kernelFactory, functionFactory, solverFactory |
| 19 | + from PyNucleus_nl.operatorInterpolation import admissibleSet |
| 20 | + import h5py |
| 21 | + from PyNucleus_base.linear_operators import LinearOperator |
| 22 | + from PyNucleus_fem.DoFMaps import DoFMap |
| 23 | + |
| 24 | + fmt = '{message}' |
| 25 | + logging.basicConfig(level=logging.INFO, |
| 26 | + format=fmt, |
| 27 | + style='{', |
| 28 | + datefmt="%Y-%m-%d %H:%M:%S") |
| 29 | + logger = logging.getLogger('__main__') |
| 30 | + timer = TimerManager(logger) |
| 31 | + |
| 32 | +with mgr.add('setup'): |
| 33 | + # Set up a mesh and a dofmap on it. |
| 34 | + mesh = meshFactory('interval', hTarget=2e-3, a=-1, b=1) |
| 35 | + dm = dofmapFactory('P1', mesh) |
| 36 | + |
| 37 | + # Construct a RHS vector and a vector for the solution. |
| 38 | + f = functionFactory('constant', 1.) |
| 39 | + b = dm.assembleRHS(f) |
| 40 | + u = dm.zeros() |
| 41 | + |
| 42 | + # construct a fractional kernel with fractional order in S = [0.05, 0.95] |
| 43 | + s = admissibleSet([0.05, 0.95]) |
| 44 | + kernel = kernelFactory('fractional', s=s, dim=mesh.dim) |
| 45 | + |
| 46 | +with mgr.add('operator'): |
| 47 | + ###################################################################### |
| 48 | + # The operator is set up to be constructed on-demand. |
| 49 | + # We partition the interval S into several sub-interval and construct a Chebyshev interpolant on each sub-interval. |
| 50 | + # Therefore this operation is fast. |
| 51 | + with timer('operator creation'): |
| 52 | + A = dm.assembleNonlocal(kernel, matrixFormat='H2') |
| 53 | + |
| 54 | +with mgr.add('firstSolve'): |
| 55 | + ###################################################################### |
| 56 | + # Set s = 0.75. |
| 57 | + A.set(0.75) |
| 58 | + |
| 59 | + # Let's solve a system. |
| 60 | + # This triggers the assembly of the operators for the matrices at the interpolation nodes of the interval that contains s. |
| 61 | + # The required matrices are constructed on-demand and then stay in memory. |
| 62 | + with timer('solve 1 (slow)'): |
| 63 | + solver = solverFactory('cg-jacobi', A=A, setup=True) |
| 64 | + solver.maxIter = 1000 |
| 65 | + numIter = solver(b, u) |
| 66 | + logger.info('Solved problem for s={} in {} iterations (residual norm {})'.format(A.get(), numIter, solver.residuals[-1])) |
| 67 | + |
| 68 | +with mgr.add('secondSolve'): |
| 69 | + ###################################################################### |
| 70 | + # Let's solve a second sytem for a closeby value of s. |
| 71 | + # This should be faster since we no longer need to assemble any matrices. |
| 72 | + with timer('solve 2 (fast)'): |
| 73 | + A.set(0.76) |
| 74 | + solver = solverFactory('cg-jacobi', A=A, setup=True) |
| 75 | + solver.maxIter = 1000 |
| 76 | + numIter = solver(b, u) |
| 77 | + logger.info('Solved problem for s={} in {} iterations (residual norm {})'.format(A.get(), numIter, solver.residuals[-1])) |
| 78 | + |
| 79 | +with mgr.add('saveToFile'): |
| 80 | + ###################################################################### |
| 81 | + # We can save the operator and the DoFMap to a file. |
| 82 | + # This will trigger the assembly of all matrices. |
| 83 | + with timer('save operator'): |
| 84 | + h5_file = h5py.File('test.hdf5', 'w') |
| 85 | + A.HDF5write(h5_file.create_group('A')) |
| 86 | + dm.HDF5write(h5_file.create_group('dm')) |
| 87 | + h5_file.close() |
| 88 | + |
| 89 | +with mgr.add('readFromFile'): |
| 90 | + ###################################################################### |
| 91 | + # Now we can read them back in. |
| 92 | + with timer('load operator'): |
| 93 | + h5_file = h5py.File('test.hdf5', 'r') |
| 94 | + A_2 = LinearOperator.HDF5read(h5_file['A']) |
| 95 | + dm_2 = DoFMap.HDF5read(h5_file['dm']) |
| 96 | + h5_file.close() |
| 97 | + |
| 98 | +with mgr.add('thirdSolve'): |
| 99 | + # Set up and solve a system with the operator we loaded. |
| 100 | + f_2 = functionFactory('constant', 2.) |
| 101 | + b_2 = dm_2.assembleRHS(f_2) |
| 102 | + u_2 = dm_2.zeros() |
| 103 | + with timer('solve 3 (fast)'): |
| 104 | + A_2.set(0.8) |
| 105 | + solver = solverFactory('cg-jacobi', A=A_2, setup=True) |
| 106 | + solver.maxIter = 1000 |
| 107 | + numIter = solver(b_2, u_2) |
| 108 | + logger.info('Solved problem for s={} in {} iterations (residual norm {})'.format(A_2.get(), numIter, solver.residuals[-1])) |
| 109 | + ###################################################################### |
0 commit comments