(self, problem, ncc_cutoff=1e-6, max_ncc_terms=None, entry_cutoff=1e-12, matrix_coupling=None, matsolver=None,
bc_top=None, tau_left=None, interleave_components=None, store_expanded_matrices=None)
| 57 | """ |
| 58 | |
| 59 | def __init__(self, problem, ncc_cutoff=1e-6, max_ncc_terms=None, entry_cutoff=1e-12, matrix_coupling=None, matsolver=None, |
| 60 | bc_top=None, tau_left=None, interleave_components=None, store_expanded_matrices=None): |
| 61 | # Take attributes from problem |
| 62 | self.problem = problem |
| 63 | self.dist = problem.dist |
| 64 | self.dtype = problem.dtype |
| 65 | self.state = problem.variables |
| 66 | # Process options |
| 67 | self.ncc_cutoff = ncc_cutoff |
| 68 | self.max_ncc_terms = max_ncc_terms |
| 69 | self.entry_cutoff = entry_cutoff |
| 70 | if matrix_coupling is None: |
| 71 | matrix_coupling = np.array(problem.matrix_coupling) |
| 72 | # Couple fully separable problems along last axis by default for efficiency |
| 73 | if not np.any(matrix_coupling): |
| 74 | matrix_coupling[-1] = True |
| 75 | else: |
| 76 | # Check specified coupling for compatibility |
| 77 | problem_coupling = np.array(problem.matrix_coupling) |
| 78 | matrix_coupling = np.array(matrix_coupling) |
| 79 | if np.any(~matrix_coupling & problem_coupling): |
| 80 | raise ValueError(f"Specified solver coupling is incompatible with problem coupling: {problem_coupling}") |
| 81 | # Check that coupled dimensions are local |
| 82 | coeff_layout = self.dist.coeff_layout |
| 83 | coupled_nonlocal = matrix_coupling & ~coeff_layout.local |
| 84 | if np.any(coupled_nonlocal): |
| 85 | raise ValueError(f"Problem is coupled along distributed dimensions: {tuple(np.where(coupled_nonlocal)[0])}") |
| 86 | self.matrix_coupling = matrix_coupling |
| 87 | # Determine matrix dependence based on specified coupling |
| 88 | self.matrix_dependence = np.array(problem.matrix_dependence) |
| 89 | for eq in problem.eqs: |
| 90 | for basis in eq['domain'].bases: |
| 91 | first_axis = self.dist.get_basis_axis(basis) |
| 92 | slices = slice(first_axis, first_axis+basis.dim) |
| 93 | self.matrix_dependence[slices] = self.matrix_dependence[slices] | basis.matrix_dependence(matrix_coupling[slices]) |
| 94 | # Process config options |
| 95 | if matsolver is None: |
| 96 | matsolver = config['linear algebra'][self.matsolver_default] |
| 97 | if isinstance(matsolver, str): |
| 98 | matsolver = matsolvers[matsolver.lower()] |
| 99 | self.matsolver = matsolver |
| 100 | if bc_top is None: |
| 101 | bc_top = config['matrix construction'].getboolean('BC_TOP') |
| 102 | self.bc_top = bc_top |
| 103 | if tau_left is None: |
| 104 | tau_left = config['matrix construction'].getboolean('TAU_LEFT') |
| 105 | self.tau_left = tau_left |
| 106 | if interleave_components is None: |
| 107 | interleave_components = config['matrix construction'].getboolean('INTERLEAVE_COMPONENTS') |
| 108 | self.interleave_components = interleave_components |
| 109 | if store_expanded_matrices is None: |
| 110 | store_expanded_matrices = config['matrix construction'].getboolean('STORE_EXPANDED_MATRICES') |
| 111 | self.store_expanded_matrices = store_expanded_matrices |
| 112 | # Process option overrides from matsolver |
| 113 | for key, value in matsolver.config.items(): |
| 114 | if getattr(self, key, None) is not value: |
| 115 | logger.info("matsolver overriding solver option '%i' with '%s'" %(key, value)) |
| 116 | setattr(self, key, value) |
no test coverage detected