|
5 | 5 |
|
6 | 6 | from pySDC.core.Errors import ParameterError, ProblemError |
7 | 7 | from pySDC.core.Problem import ptype |
8 | | -from pySDC.implementations.datatype_classes.mesh import mesh, rhs_imex_mesh |
| 8 | +from pySDC.implementations.datatype_classes.mesh import mesh, rhs_imex_mesh, rhs_comp2_mesh |
9 | 9 |
|
10 | 10 |
|
11 | 11 | class allencahn_front_fullyimplicit(ptype): |
@@ -580,7 +580,7 @@ def __init__(self, problem_params, dtype_u=mesh, dtype_f=rhs_imex_mesh): |
580 | 580 | # invoke super init, passing number of dofs, dtype_u and dtype_f |
581 | 581 | super(allencahn_periodic_semiimplicit, self).__init__(problem_params, dtype_u, dtype_f) |
582 | 582 |
|
583 | | - self.A -= sp.eye(self.init) * 2.0 / self.params.eps ** 2 |
| 583 | + self.A -= sp.eye(self.init) * 0.0 / self.params.eps ** 2 |
584 | 584 |
|
585 | 585 | def solve_system(self, rhs, factor, u0, t): |
586 | 586 | """ |
@@ -613,6 +613,139 @@ def eval_f(self, u, t): |
613 | 613 | """ |
614 | 614 | f = self.dtype_f(self.init) |
615 | 615 | f.impl.values = self.A.dot(u.values) |
616 | | - f.expl.values = -2.0 / self.params.eps ** 2 * u.values * (1.0 - u.values) * (1.0 - 2 * u.values) - \ |
617 | | - 6.0 * self.params.dw * u.values * (1.0 - u.values) + 2.0 / self.params.eps ** 2 * u.values |
| 616 | + f.expl.values = -2.0 / self.params.eps ** 2 * u.values * (1.0 - u.values) * (1.0 - 2.0 * u.values) - \ |
| 617 | + 6.0 * self.params.dw * u.values * (1.0 - u.values) + 0.0 / self.params.eps ** 2 * u.values |
618 | 618 | return f |
| 619 | + |
| 620 | + |
| 621 | +class allencahn_periodic_multiimplicit(allencahn_periodic_fullyimplicit): |
| 622 | + """ |
| 623 | + Example implementing the Allen-Cahn equation in 1D with finite differences and periodic BC, |
| 624 | + with driving force, 0-1 formulation (Bayreuth example) |
| 625 | + """ |
| 626 | + |
| 627 | + def __init__(self, problem_params, dtype_u=mesh, dtype_f=rhs_comp2_mesh): |
| 628 | + """ |
| 629 | + Initialization routine |
| 630 | +
|
| 631 | + Args: |
| 632 | + problem_params (dict): custom parameters for the example |
| 633 | + dtype_u: mesh data type (will be passed parent class) |
| 634 | + dtype_f: mesh data type (will be passed parent class) |
| 635 | + """ |
| 636 | + |
| 637 | + # these parameters will be used later, so assert their existence |
| 638 | + essential_keys = ['nvars', 'dw', 'eps', 'newton_maxiter', 'newton_tol', 'interval', 'radius'] |
| 639 | + for key in essential_keys: |
| 640 | + if key not in problem_params: |
| 641 | + msg = 'need %s to instantiate problem, only got %s' % (key, str(problem_params.keys())) |
| 642 | + raise ParameterError(msg) |
| 643 | + |
| 644 | + # we assert that nvars looks very particular here.. this will be necessary for coarsening in space later on |
| 645 | + if (problem_params['nvars']) % 2 != 0: |
| 646 | + raise ProblemError('setup requires nvars = 2^p') |
| 647 | + |
| 648 | + if 'stop_at_nan' not in problem_params: |
| 649 | + problem_params['stop_at_nan'] = True |
| 650 | + |
| 651 | + # invoke super init, passing number of dofs, dtype_u and dtype_f |
| 652 | + super(allencahn_periodic_multiimplicit, self).__init__(problem_params, dtype_u, dtype_f) |
| 653 | + |
| 654 | + self.A -= sp.eye(self.init) * 0.0 / self.params.eps ** 2 |
| 655 | + |
| 656 | + def solve_system_1(self, rhs, factor, u0, t): |
| 657 | + """ |
| 658 | + Simple linear solver for (I-factor*A)u = rhs |
| 659 | +
|
| 660 | + Args: |
| 661 | + rhs (dtype_f): right-hand side for the linear system |
| 662 | + factor (float): abbrev. for the local stepsize (or any other factor required) |
| 663 | + u0 (dtype_u): initial guess for the iterative solver |
| 664 | + t (float): current time (e.g. for time-dependent BCs) |
| 665 | +
|
| 666 | + Returns: |
| 667 | + dtype_u: solution as mesh |
| 668 | + """ |
| 669 | + |
| 670 | + me = self.dtype_u(u0) |
| 671 | + me.values = spsolve(sp.eye(self.params.nvars, format='csc') - factor * self.A, rhs.values) |
| 672 | + return me |
| 673 | + |
| 674 | + def eval_f(self, u, t): |
| 675 | + """ |
| 676 | + Routine to evaluate the RHS |
| 677 | +
|
| 678 | + Args: |
| 679 | + u (dtype_u): current values |
| 680 | + t (float): current time |
| 681 | +
|
| 682 | + Returns: |
| 683 | + dtype_f: the RHS |
| 684 | + """ |
| 685 | + f = self.dtype_f(self.init) |
| 686 | + f.comp1.values = self.A.dot(u.values) |
| 687 | + f.comp2.values = -2.0 / self.params.eps ** 2 * u.values * (1.0 - u.values) * (1.0 - 2.0 * u.values) - \ |
| 688 | + 6.0 * self.params.dw * u.values * (1.0 - u.values) + 0.0 / self.params.eps ** 2 * u.values |
| 689 | + return f |
| 690 | + |
| 691 | + def solve_system_2(self, rhs, factor, u0, t): |
| 692 | + """ |
| 693 | + Simple linear solver for (I-factor*A)u = rhs |
| 694 | +
|
| 695 | + Args: |
| 696 | + rhs (dtype_f): right-hand side for the linear system |
| 697 | + factor (float): abbrev. for the local stepsize (or any other factor required) |
| 698 | + u0 (dtype_u): initial guess for the iterative solver |
| 699 | + t (float): current time (e.g. for time-dependent BCs) |
| 700 | +
|
| 701 | + Returns: |
| 702 | + dtype_u: solution as mesh |
| 703 | + """ |
| 704 | + |
| 705 | + u = self.dtype_u(u0).values |
| 706 | + eps2 = self.params.eps ** 2 |
| 707 | + dw = self.params.dw |
| 708 | + |
| 709 | + Id = sp.eye(self.params.nvars) |
| 710 | + |
| 711 | + # start newton iteration |
| 712 | + n = 0 |
| 713 | + res = 99 |
| 714 | + while n < self.params.newton_maxiter: |
| 715 | + # print(n) |
| 716 | + # form the function g with g(u) = 0 |
| 717 | + g = u - rhs.values - factor * (- 2.0 / eps2 * u * (1.0 - u) * (1.0 - 2.0 * u) - |
| 718 | + 6.0 * dw * u * (1.0 - u) + 0.0 / self.params.eps ** 2 * u) |
| 719 | + |
| 720 | + # if g is close to 0, then we are done |
| 721 | + res = np.linalg.norm(g, np.inf) |
| 722 | + |
| 723 | + if res < self.params.newton_tol: |
| 724 | + break |
| 725 | + |
| 726 | + # assemble dg |
| 727 | + dg = Id - factor * (- 2.0 / eps2 * sp.diags( |
| 728 | + (1.0 - u) * (1.0 - 2.0 * u) - u * ((1.0 - 2.0 * u) + 2.0 * (1.0 - u)), offsets=0) - 6.0 * dw * sp.diags( |
| 729 | + (1.0 - u) - u, offsets=0) + 0.0 / self.params.eps ** 2 * Id) |
| 730 | + |
| 731 | + # newton update: u1 = u0 - g/dg |
| 732 | + u -= spsolve(dg, g) |
| 733 | + # u -= gmres(dg, g, x0=z, tol=self.params.lin_tol)[0] |
| 734 | + # increase iteration count |
| 735 | + n += 1 |
| 736 | + |
| 737 | + if np.isnan(res) and self.params.stop_at_nan: |
| 738 | + raise ProblemError('Newton got nan after %i iterations, aborting...' % n) |
| 739 | + elif np.isnan(res): |
| 740 | + self.logger.warning('Newton got nan after %i iterations...' % n) |
| 741 | + |
| 742 | + if n == self.params.newton_maxiter: |
| 743 | + self.logger.warning('Newton did not converge after %i iterations, error is %s' % (n, res)) |
| 744 | + |
| 745 | + self.newton_ncalls += 1 |
| 746 | + self.newton_itercount += n |
| 747 | + |
| 748 | + me = self.dtype_u(self.init) |
| 749 | + me.values = u |
| 750 | + |
| 751 | + return me |
0 commit comments