|
12 | 12 | # copyright notice, and modified files need to carry a notice indicating |
13 | 13 | # that they have been altered from the originals. |
14 | 14 |
|
15 | | -from typing import List, Union |
| 15 | +from typing import List, Tuple, Union |
16 | 16 |
|
17 | 17 | import pandas as pd |
18 | 18 | from collections import defaultdict |
@@ -443,6 +443,158 @@ def lumped_oscillator_vs_passes(self, *args, **kwargs): |
443 | 443 | 'This method is deprecated. Change your scripts to use' |
444 | 444 | 'analysis.quantitative.capacitance_lom.run_lom()') |
445 | 445 |
|
| 446 | + def get_convergence(self) -> bool: |
| 447 | + """Extracts convergence from Ansys simulation result |
| 448 | + """ |
| 449 | + # If 'LastAdaptive' is used, then the pass_number won't affect anything. |
| 450 | + # If 'AdaptivePass' is used, then the pass_number is used. |
| 451 | + convergence_df, convergence_txt = self._pinfo.setup.get_convergence() |
| 452 | + target, current, pass_min = self._parse_text_from_q3d_convergence( |
| 453 | + convergence_txt) |
| 454 | + is_converged = self._test_if_q3d_analysis_converged( |
| 455 | + target, current, pass_min) |
| 456 | + |
| 457 | + return is_converged |
| 458 | + |
| 459 | + def _test_if_q3d_analysis_converged(cls, target: float, current: float, |
| 460 | + passes_min: int) -> Union[bool, None]: |
| 461 | + """Use solution-data from Ansys-Q3d to determine if converged. |
| 462 | +
|
| 463 | + Args: |
| 464 | + target (float): Delta percentage for target. Default is None. |
| 465 | + current (float): Delta percentage for current. Default is None. |
| 466 | + passes_min (int): Regarding convergence, minimum number of passes. |
| 467 | + Default is None. |
| 468 | +
|
| 469 | + Returns: |
| 470 | + Union[bool, None]: Had solution data converged. Default is None. |
| 471 | + """ |
| 472 | + |
| 473 | + if None not in (target, current, passes_min): |
| 474 | + # Confirm that all three numbers have an value. |
| 475 | + if current <= target and passes_min > 1: |
| 476 | + is_converged = True |
| 477 | + return is_converged |
| 478 | + is_converged = False |
| 479 | + return is_converged |
| 480 | + |
| 481 | + is_converged = None |
| 482 | + return is_converged |
| 483 | + |
| 484 | + def _parse_text_from_q3d_convergence( |
| 485 | + self, |
| 486 | + gui_text: str) -> Tuple[Union[None, float], Union[None, float]]: |
| 487 | + """Parse gui_text using a priori known formatting. Ansys-Q3D |
| 488 | + solution-data provides gui_text. |
| 489 | +
|
| 490 | + Args: |
| 491 | + gui_text (str): From Ansys-GUI-SolutionData. |
| 492 | +
|
| 493 | + Returns: |
| 494 | + 1st Union[None, float]: Delta percentage for target. Default is None. |
| 495 | + 2nd Union[None, float]: Delta percentage for current. Default is None. |
| 496 | + """ |
| 497 | + |
| 498 | + text_list = gui_text.splitlines() |
| 499 | + |
| 500 | + # Find Target information in text. |
| 501 | + target_all = [string for string in text_list if 'Target' in string] |
| 502 | + |
| 503 | + # Find Current information in text. |
| 504 | + current_all = [string for string in text_list if 'Current' in string] |
| 505 | + |
| 506 | + # Find Minimum number of passes from solution-data. |
| 507 | + min_passes_all = [string for string in text_list if 'Minimum' in string] |
| 508 | + |
| 509 | + target = self._extract_target_delta(target_all) |
| 510 | + current = self._extract_current_delta(current_all) |
| 511 | + min_passes = self._extract_min_passes(min_passes_all) |
| 512 | + |
| 513 | + return target, current, min_passes |
| 514 | + |
| 515 | + def _extract_min_passes(self, min_passes_all: list) -> Union[None, float]: |
| 516 | + """Given a pre-formatted list, search and return the "Minimum Number |
| 517 | + Of Passes." |
| 518 | +
|
| 519 | + Args: |
| 520 | + min_passes_all (list): Result of search through string returned from Ansys-Q3D. |
| 521 | +
|
| 522 | + Returns: |
| 523 | + Union[None, float]: Regarding convergence, minimum number of passes. |
| 524 | + Default is None. |
| 525 | + """ |
| 526 | + |
| 527 | + min_num_of_passes = None |
| 528 | + if len(min_passes_all) == 1: |
| 529 | + if min_passes_all[0]: |
| 530 | + _, _, min_passes_str = min_passes_all[0].partition(':') |
| 531 | + try: |
| 532 | + min_num_of_passes = int(min_passes_str) |
| 533 | + except ValueError: |
| 534 | + self.design.logger.warning( |
| 535 | + f'Target={min_passes_str} in GUI is not an int.' |
| 536 | + 'Force Minimum Number Of Passes to be None.') |
| 537 | + else: |
| 538 | + self.design.logger.warning( |
| 539 | + 'Either could not find Minimum Number of Passes ' |
| 540 | + 'information or too many entries in text. ' |
| 541 | + 'Force Minimum Number of Passes to be None.') |
| 542 | + return min_num_of_passes |
| 543 | + |
| 544 | + def _extract_target_delta(self, target_all: list) -> Union[None, float]: |
| 545 | + """Given a pre-formatted list, search and return the target-delta |
| 546 | + percentage for convergence. |
| 547 | +
|
| 548 | + Args: |
| 549 | + target_all (list): Result of search through string returned from Ansys-Q3D. |
| 550 | +
|
| 551 | + Returns: |
| 552 | + Union[None, float]: Delta percentage for target. Default is None. |
| 553 | + """ |
| 554 | + |
| 555 | + target = None |
| 556 | + if len(target_all) == 1: |
| 557 | + if target_all[0]: |
| 558 | + _, _, target_str = target_all[0].partition(':') |
| 559 | + try: |
| 560 | + target = float(target_str) |
| 561 | + except ValueError: |
| 562 | + self.design.logger.warning( |
| 563 | + f'Target={target_str} in GUI is not a float.' |
| 564 | + 'Force Target Delta to be None.') |
| 565 | + else: |
| 566 | + self.design.logger.warning( |
| 567 | + 'Either could not find Target Delta information or too many ' |
| 568 | + 'entries in text. Force Target Delta to be None.') |
| 569 | + return target |
| 570 | + |
| 571 | + def _extract_current_delta(self, current_all: list) -> Union[None, float]: |
| 572 | + """Given a pre-formatted list, search and return the current-delta |
| 573 | + percentage for convergence. |
| 574 | +
|
| 575 | + Args: |
| 576 | + current_all (list): Result of search through string returned from Ansys-Q3D. |
| 577 | +
|
| 578 | + Returns: |
| 579 | + Union[None, float]: Delta percentage for current. Default is None. |
| 580 | + """ |
| 581 | + |
| 582 | + current = None |
| 583 | + if len(current_all) == 1: |
| 584 | + if current_all[0]: |
| 585 | + _, _, current_str = current_all[0].partition(':') |
| 586 | + try: |
| 587 | + current = float(current_str) |
| 588 | + except ValueError: |
| 589 | + self.design.logger.warning( |
| 590 | + f'Target={current_str} in GUI is not a float.' |
| 591 | + 'Force Current Delta to be None.') |
| 592 | + else: |
| 593 | + self.design.logger.warning( |
| 594 | + 'Either could not find Current Delta information or too many ' |
| 595 | + 'entries in text. Force Current Delta to be None.') |
| 596 | + return current |
| 597 | + |
446 | 598 | def plot_convergence_main(self, RES: pd.DataFrame): |
447 | 599 | """Plot alpha and frequency versus pass number, as well as convergence |
448 | 600 | of delta (in %). |
|
0 commit comments