|
22 | 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
23 | 23 | # SOFTWARE. |
24 | 24 |
|
25 | | -import os |
26 | | - |
27 | 25 | from ansys.aedt.core import constants |
28 | | -from ansys.aedt.core import pyaedt_path |
29 | 26 | from ansys.aedt.core.generic.file_utils import generate_unique_name |
30 | 27 | from ansys.aedt.core.generic.general_methods import pyaedt_function_handler |
31 | 28 | from ansys.aedt.core.modules.material_lib import Material |
@@ -691,78 +688,6 @@ def add_patch( |
691 | 688 | created_patch.aedt_object.group_name = f"Layer_{self._name}" |
692 | 689 | return created_patch |
693 | 690 |
|
694 | | - @pyaedt_function_handler() |
695 | | - def ml_patch( |
696 | | - self, |
697 | | - frequency, |
698 | | - patch_width, |
699 | | - patch_position_x=0, |
700 | | - patch_position_y=0, |
701 | | - patch_name=None, |
702 | | - axis="X", |
703 | | - ): |
704 | | - """Create a new parametric patch using machine learning algorithm rather than analytic formulas. |
705 | | -
|
706 | | - Parameters |
707 | | - ---------- |
708 | | - frequency : float, None |
709 | | - Frequency value for patch calculation in Hz. |
710 | | - patch_width : float |
711 | | - Patch width. |
712 | | - patch_position_x : float, optional |
713 | | - Patch start x position. |
714 | | - patch_position_y : float, optional |
715 | | - Patch start y position. |
716 | | - patch_name : str, optional |
717 | | - Patch name. |
718 | | - axis : str, optional |
719 | | - Line orientation axis. |
720 | | -
|
721 | | - Returns |
722 | | - ------- |
723 | | - :class:`ansys.aedt.core.modeler.advanced_cad.stackup_3d.MachineLearningPatch` |
724 | | -
|
725 | | - Examples |
726 | | - -------- |
727 | | -
|
728 | | - >>> from ansys.aedt.core import Hfss |
729 | | - >>> from ansys.aedt.core.modeler.advanced_cad.stackup_3d import Stackup3D |
730 | | - >>> hfss = Hfss() |
731 | | - >>> my_stackup = Stackup3D(hfss, 2.5e9) |
732 | | - >>> gnd = my_stackup.add_ground_layer("gnd") |
733 | | - >>> my_stackup.add_dielectric_layer("diel1", thickness=1.5, material="Duroid (tm)") |
734 | | - >>> top = my_stackup.add_signal_layer("top") |
735 | | - >>> my_patch = top.ml_patch(frequency=None, patch_width=51, patch_name="MLPatch") |
736 | | - >>> my_stackup.resize_around_element(my_patch) |
737 | | -
|
738 | | - """ |
739 | | - if not patch_name: |
740 | | - patch_name = generate_unique_name(f"{self._name}_patch", n=3) |
741 | | - lst = self._stackup._layer_name |
742 | | - for i in range(len(lst)): |
743 | | - if lst[i] == self._name: |
744 | | - if self._stackup.stackup_layers[lst[i - 1]].type == "dielectric": |
745 | | - below_layer = self._stackup.stackup_layers[lst[i - 1]] |
746 | | - break |
747 | | - else: |
748 | | - self._app.logger.error("The layer below the selected one must be of dielectric type") |
749 | | - return False |
750 | | - created_patch = MachineLearningPatch( |
751 | | - self._app, |
752 | | - frequency, |
753 | | - patch_width, |
754 | | - signal_layer=self, |
755 | | - dielectric_layer=below_layer, |
756 | | - patch_position_x=patch_position_x, |
757 | | - patch_position_y=patch_position_y, |
758 | | - patch_name=patch_name, |
759 | | - axis=axis, |
760 | | - ) |
761 | | - self._obj_3d.append(created_patch.aedt_object) |
762 | | - self._stackup._object_list.append(created_patch) |
763 | | - created_patch.aedt_object.group_name = f"Layer_{self._name}" |
764 | | - return created_patch |
765 | | - |
766 | 691 | @pyaedt_function_handler() |
767 | 692 | def add_trace( |
768 | 693 | self, |
@@ -3378,119 +3303,3 @@ def points_on_layer(self): |
3378 | 3303 | """ |
3379 | 3304 | bb = self._aedt_object.bounding_box |
3380 | 3305 | return [[bb[0], bb[1]], [bb[0], bb[4]], [bb[3], bb[4]], [bb[3], bb[1]]] |
3381 | | - |
3382 | | - |
3383 | | -class MachineLearningPatch(Patch, object): |
3384 | | - """MachineLearningPatch Class in Stackup3D. Create an antenna whose length is predicted by a |
3385 | | - machine learning algorithm. |
3386 | | -
|
3387 | | - The machine learning algorithm determines the length according to resonant frequency, |
3388 | | - patch width, substrat thickness and relative permittivity. The other parameter have no or only a minor influence. |
3389 | | - We can consider that the patch thickness has no influence as long as it is lower than 50 um, |
3390 | | - for machine learning training is set to 35 um. The patch conductivity and other dielectric properties are |
3391 | | - respectively those of copper and duroid (tm) for the machine learning training, but predictions work |
3392 | | - regardless of the dielectric or the conductor. The predictions are, in the most of cases, better than the |
3393 | | - predictions with formula used in the class Patch. The machine learning model used, is Support Vector Regression, |
3394 | | - it is a classic model in the non-linear prediction, it can be used for other non-linear application. |
3395 | | - Two models were created, one from 0.1 GHz to 1 GHz and another from 1 GHz to 10 GHz. The example of the creation of |
3396 | | - these models is available in a PyAEDT example named Machine_learning_applied_to_Patch. The two databases and models |
3397 | | - are available in PyAEDT in misc. |
3398 | | -
|
3399 | | - It is preferable to use the ml_patch method in the class Layer3D than directly the class constructor. |
3400 | | -
|
3401 | | - Parameters |
3402 | | - ---------- |
3403 | | - application : :class:`ansys.aedt.core.hfss.Hfss` |
3404 | | - HFSS design or project where the variable is to be created. |
3405 | | - frequency : float, None |
3406 | | - The patch frequency, it is used in prediction formulas. If it is None, the patch frequency will be that of the |
3407 | | - layer or of the stackup. From 0.1 to 10 GHz. |
3408 | | - dx : float |
3409 | | - The patch width. From O.5 to 1.5 of the optimal width value : c0 * 1000/(2 * f * sqrt((er + 1)/2)) |
3410 | | - signal_layer : :class:`ansys.aedt.core.modeler.advanced_cad.stackup_3d.Layer3D` |
3411 | | - The signal layer where the patch will be drawn. |
3412 | | - dielectric_layer : :class:`ansys.aedt.core.modeler.advanced_cad.stackup_3d.Layer3D` |
3413 | | - The dielectric layer between the patch and the ground layer. Its permittivity and thickness are used in |
3414 | | - prediction formulas. Thickness must be from 0.003 to 0.05 of the wavelength in vacuum and relative permittivity |
3415 | | - from 1 to 12. |
3416 | | - patch_position_x : float, optional |
3417 | | - Patch x position, by default it is 0. |
3418 | | - patch_position_y : float, optional |
3419 | | - Patch y position, by default it is 0. |
3420 | | - patch_name : str, optional |
3421 | | - Patch name, by default "patch". |
3422 | | - reference_system : str, None, optional |
3423 | | - Coordinate system of the patch. By default, None. |
3424 | | - axis : str, optional |
3425 | | - Patch length axis, by default ``"X"``. |
3426 | | -
|
3427 | | - Examples |
3428 | | - -------- |
3429 | | -
|
3430 | | - >>> from ansys.aedt.core import Hfss |
3431 | | - >>> from ansys.aedt.core.modeler.advanced_cad.stackup_3d import Stackup3D |
3432 | | - >>> hfss = Hfss() |
3433 | | - >>> my_stackup = Stackup3D(hfss, 2.5e9) |
3434 | | - >>> gnd = my_stackup.add_ground_layer("gnd") |
3435 | | - >>> my_stackup.add_dielectric_layer("diel1", thickness=1.5, material="Duroid (tm)") |
3436 | | - >>> top = my_stackup.add_signal_layer("top") |
3437 | | - >>> my_patch = top.ml_patch(frequency=None, patch_width=51, patch_name="MLPatch") |
3438 | | - >>> my_stackup.resize_around_element(my_patch) |
3439 | | -
|
3440 | | - """ |
3441 | | - |
3442 | | - def __init__( |
3443 | | - self, |
3444 | | - application, |
3445 | | - frequency, |
3446 | | - dx, |
3447 | | - signal_layer, |
3448 | | - dielectric_layer, |
3449 | | - patch_position_x=0, |
3450 | | - patch_position_y=0, |
3451 | | - patch_name="patch", |
3452 | | - reference_system=None, |
3453 | | - axis="X", |
3454 | | - ): |
3455 | | - Patch.__init__( |
3456 | | - self, |
3457 | | - application, |
3458 | | - frequency, |
3459 | | - dx, |
3460 | | - signal_layer, |
3461 | | - dielectric_layer, |
3462 | | - dy=None, |
3463 | | - patch_position_x=patch_position_x, |
3464 | | - patch_position_y=patch_position_y, |
3465 | | - patch_name=patch_name, |
3466 | | - reference_system=reference_system, |
3467 | | - axis=axis, |
3468 | | - ) |
3469 | | - self.predict_length() |
3470 | | - |
3471 | | - def predict_length(self): |
3472 | | - try: |
3473 | | - import joblib |
3474 | | - import numpy as np |
3475 | | - except ImportError: # pragma: no cover |
3476 | | - raise ImportError("Package Joblib and Numpy are required to run ML.") |
3477 | | - training_file = None |
3478 | | - if 1e9 >= self.frequency.numeric_value >= 1e8: |
3479 | | - training_file = os.path.join(pyaedt_path, "misc", "patch_svr_model_100MHz_1GHz.joblib") |
3480 | | - elif 1e10 >= self.frequency.numeric_value > 1e9: |
3481 | | - training_file = os.path.join(pyaedt_path, "misc", "patch_svr_model_1GHz_10GHz.joblib") |
3482 | | - else: # pragma: no cover |
3483 | | - self.application.logger.error("This ML algorithm can only predict patch antennas from 100 MHz to 10 GHz.") |
3484 | | - if training_file: |
3485 | | - model = joblib.load(training_file) |
3486 | | - list_for_array = [ |
3487 | | - [ |
3488 | | - self.frequency.numeric_value, |
3489 | | - self.width.numeric_value, |
3490 | | - self._permittivity.numeric_value, |
3491 | | - self.dielectric_layer.thickness.numeric_value, |
3492 | | - ] |
3493 | | - ] |
3494 | | - array_for_prediction = np.array(list_for_array, dtype=np.float32) |
3495 | | - length = model.predict(array_for_prediction)[0] |
3496 | | - self.length.expression = self.application.value_with_units(length) |
0 commit comments