pyedb 0.6.0__py3-none-any.whl → 0.7.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyedb might be problematic. Click here for more details.
- pyedb/__init__.py +1 -1
- pyedb/dotnet/clr_module.py +1 -1
- pyedb/dotnet/edb.py +15 -16
- pyedb/dotnet/edb_core/cell/hierarchy/model.py +17 -0
- pyedb/dotnet/edb_core/components.py +11 -11
- pyedb/dotnet/edb_core/configuration.py +346 -77
- pyedb/dotnet/edb_core/definition/component_def.py +9 -0
- pyedb/dotnet/edb_core/definition/package_def.py +27 -0
- pyedb/dotnet/edb_core/edb_data/components_data.py +8 -3
- pyedb/dotnet/edb_core/edb_data/hfss_extent_info.py +14 -13
- pyedb/dotnet/edb_core/edb_data/hfss_simulation_setup_data.py +2 -2
- pyedb/dotnet/edb_core/edb_data/layer_data.py +8 -3
- pyedb/dotnet/edb_core/edb_data/padstacks_data.py +26 -5
- pyedb/dotnet/edb_core/edb_data/primitives_data.py +12 -11
- pyedb/dotnet/edb_core/edb_data/siwave_simulation_setup_data.py +1 -1
- pyedb/dotnet/edb_core/edb_data/sources.py +10 -0
- pyedb/dotnet/edb_core/hfss.py +1 -1
- pyedb/dotnet/edb_core/layout.py +94 -31
- pyedb/dotnet/edb_core/materials.py +637 -541
- pyedb/dotnet/edb_core/nets.py +5 -5
- pyedb/dotnet/edb_core/padstack.py +57 -6
- pyedb/dotnet/edb_core/siwave.py +9 -2
- pyedb/dotnet/edb_core/stackup.py +108 -94
- pyedb/dotnet/edb_core/utilities/__init__.py +3 -0
- pyedb/dotnet/edb_core/utilities/heatsink.py +69 -0
- pyedb/exceptions.py +6 -0
- pyedb/generic/filesystem.py +7 -3
- pyedb/generic/general_methods.py +4 -0
- pyedb/generic/process.py +4 -1
- pyedb/generic/settings.py +10 -0
- {pyedb-0.6.0.dist-info → pyedb-0.7.1.dist-info}/METADATA +31 -53
- {pyedb-0.6.0.dist-info → pyedb-0.7.1.dist-info}/RECORD +35 -32
- /pyedb/dotnet/edb_core/{edb_data → utilities}/simulation_setup.py +0 -0
- {pyedb-0.6.0.dist-info → pyedb-0.7.1.dist-info}/LICENSE +0 -0
- {pyedb-0.6.0.dist-info → pyedb-0.7.1.dist-info}/WHEEL +0 -0
|
@@ -26,450 +26,523 @@ import difflib
|
|
|
26
26
|
import logging
|
|
27
27
|
import os
|
|
28
28
|
import re
|
|
29
|
+
from typing import Optional, Union
|
|
29
30
|
import warnings
|
|
30
31
|
|
|
32
|
+
from pydantic import BaseModel, confloat
|
|
33
|
+
|
|
34
|
+
from pyedb import Edb
|
|
31
35
|
from pyedb.dotnet.clr_module import _clr
|
|
32
36
|
from pyedb.dotnet.edb_core.general import convert_py_list_to_net_list
|
|
37
|
+
from pyedb.exceptions import MaterialModelException
|
|
33
38
|
from pyedb.generic.general_methods import is_ironpython, pyedb_function_handler
|
|
34
39
|
|
|
35
40
|
logger = logging.getLogger(__name__)
|
|
36
41
|
|
|
42
|
+
# TODO: Once we are Python3.9+ change PositiveInt implementation like
|
|
43
|
+
# from annotated_types import Gt
|
|
44
|
+
# from typing_extensions import Annotated
|
|
45
|
+
# PositiveFloat = Annotated[float, Gt(0)]
|
|
46
|
+
try:
|
|
47
|
+
from annotated_types import Gt
|
|
48
|
+
from typing_extensions import Annotated
|
|
49
|
+
|
|
50
|
+
PositiveFloat = Annotated[float, Gt(0)]
|
|
51
|
+
except:
|
|
52
|
+
PositiveFloat = confloat(gt=0)
|
|
53
|
+
|
|
54
|
+
ATTRIBUTES = [
|
|
55
|
+
"conductivity",
|
|
56
|
+
"dielectric_loss_tangent",
|
|
57
|
+
"magnetic_loss_tangent",
|
|
58
|
+
"mass_density",
|
|
59
|
+
"permittivity",
|
|
60
|
+
"permeability",
|
|
61
|
+
"poisson_ratio",
|
|
62
|
+
"specific_heat",
|
|
63
|
+
"thermal_conductivity",
|
|
64
|
+
"youngs_modulus",
|
|
65
|
+
"thermal_expansion_coefficient",
|
|
66
|
+
]
|
|
67
|
+
DC_ATTRIBUTES = [
|
|
68
|
+
"dielectric_model_frequency",
|
|
69
|
+
"loss_tangent_at_frequency",
|
|
70
|
+
"permittivity_at_frequency",
|
|
71
|
+
"dc_conductivity",
|
|
72
|
+
"dc_permittivity",
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class MaterialProperties(BaseModel):
|
|
77
|
+
"""Store material properties."""
|
|
78
|
+
|
|
79
|
+
conductivity: Optional[PositiveFloat] = None
|
|
80
|
+
dielectric_loss_tangent: Optional[PositiveFloat] = None
|
|
81
|
+
magnetic_loss_tangent: Optional[PositiveFloat] = None
|
|
82
|
+
mass_density: Optional[PositiveFloat] = None
|
|
83
|
+
permittivity: Optional[PositiveFloat] = None
|
|
84
|
+
permeability: Optional[PositiveFloat] = None
|
|
85
|
+
poisson_ratio: Optional[PositiveFloat] = None
|
|
86
|
+
specific_heat: Optional[PositiveFloat] = None
|
|
87
|
+
thermal_conductivity: Optional[PositiveFloat] = None
|
|
88
|
+
youngs_modulus: Optional[PositiveFloat] = None
|
|
89
|
+
thermal_expansion_coefficient: Optional[PositiveFloat] = None
|
|
90
|
+
dc_conductivity: Optional[PositiveFloat] = None
|
|
91
|
+
dc_permittivity: Optional[PositiveFloat] = None
|
|
92
|
+
dielectric_model_frequency: Optional[PositiveFloat] = None
|
|
93
|
+
loss_tangent_at_frequency: Optional[PositiveFloat] = None
|
|
94
|
+
permittivity_at_frequency: Optional[PositiveFloat] = None
|
|
95
|
+
|
|
37
96
|
|
|
38
97
|
class Material(object):
|
|
39
|
-
"""
|
|
40
|
-
|
|
41
|
-
def __init__(self, pclass, edb_material_def):
|
|
42
|
-
self._pclass = pclass
|
|
43
|
-
self._name = edb_material_def.GetName()
|
|
44
|
-
self._edb_material_def = edb_material_def
|
|
45
|
-
self._conductivity = 0.0
|
|
46
|
-
self._loss_tangent = 0.0
|
|
47
|
-
self._magnetic_loss_tangent = 0.0
|
|
48
|
-
self._mass_density = 0.0
|
|
49
|
-
self._permittivity = 0.0
|
|
50
|
-
self._permeability = 0.0
|
|
51
|
-
self._poisson_ratio = 0.0
|
|
52
|
-
self._specific_heat = 0.0
|
|
53
|
-
self._thermal_conductivity = 0.0
|
|
54
|
-
self._youngs_modulus = 0.0
|
|
55
|
-
self._thermal_expansion_coefficient = 0.0
|
|
56
|
-
self._dc_conductivity = 0.0
|
|
57
|
-
self._dc_permittivity = 0.0
|
|
58
|
-
self._dielectric_model_frequency = 0.0
|
|
59
|
-
self._loss_tangent_at_frequency = 0.0
|
|
60
|
-
self._permittivity_at_frequency = 0.0
|
|
61
|
-
|
|
62
|
-
def _edb_value(self, value):
|
|
63
|
-
return self._pclass._edb_value(value)
|
|
98
|
+
"""Manage EDB methods for material property management."""
|
|
64
99
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
100
|
+
def __init__(self, edb: Edb, material_def):
|
|
101
|
+
self.__edb: Edb = edb
|
|
102
|
+
self.__edb_definition = edb.edb_api.definition
|
|
103
|
+
self.__name: str = material_def.GetName()
|
|
104
|
+
self.__material_def = material_def
|
|
105
|
+
self.__dc_model = material_def.GetDielectricMaterialModel()
|
|
106
|
+
self.__properties: MaterialProperties = MaterialProperties()
|
|
69
107
|
|
|
70
108
|
@property
|
|
71
|
-
def
|
|
72
|
-
|
|
109
|
+
def name(self):
|
|
110
|
+
"""Material name."""
|
|
111
|
+
return self.__name
|
|
73
112
|
|
|
74
113
|
@property
|
|
75
|
-
def
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
@pyedb_function_handler()
|
|
79
|
-
def _get_property(self, property_name):
|
|
80
|
-
if is_ironpython: # pragma: no cover
|
|
81
|
-
property_box = _clr.StrongBox[float]()
|
|
82
|
-
self._edb_material_def.GetProperty(property_name, property_box)
|
|
83
|
-
return float(property_box)
|
|
84
|
-
else:
|
|
85
|
-
_, property_box = self._edb_material_def.GetProperty(property_name)
|
|
86
|
-
if isinstance(property_box, float):
|
|
87
|
-
return property_box
|
|
88
|
-
else:
|
|
89
|
-
return property_box.ToDouble()
|
|
114
|
+
def dc_model(self):
|
|
115
|
+
"""Material dielectric model."""
|
|
116
|
+
return self.__dc_model
|
|
90
117
|
|
|
91
118
|
@property
|
|
92
119
|
def conductivity(self):
|
|
93
|
-
|
|
94
|
-
self.
|
|
95
|
-
|
|
120
|
+
"""Get material conductivity."""
|
|
121
|
+
if self.__properties.conductivity is None:
|
|
122
|
+
material_property_id = self.__edb_definition.MaterialPropertyId.Conductivity
|
|
123
|
+
self.__properties.conductivity = self.__property_value(material_property_id)
|
|
124
|
+
return self.__properties.conductivity
|
|
96
125
|
|
|
97
126
|
@conductivity.setter
|
|
98
127
|
def conductivity(self, value):
|
|
99
|
-
"""
|
|
100
|
-
|
|
101
|
-
self.
|
|
102
|
-
self.
|
|
128
|
+
"""Set material conductivity."""
|
|
129
|
+
edb_value = self.__edb_value(value)
|
|
130
|
+
material_property_id = self.__edb_definition.MaterialPropertyId.Conductivity
|
|
131
|
+
self.__material_def.SetProperty(material_property_id, self.__edb_value(value))
|
|
132
|
+
self.__properties.conductivity = edb_value.ToDouble()
|
|
103
133
|
|
|
104
134
|
@property
|
|
105
135
|
def permittivity(self):
|
|
106
|
-
"""
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
136
|
+
"""Get material permittivity."""
|
|
137
|
+
if self.__properties.permittivity is None:
|
|
138
|
+
material_property_id = self.__edb_definition.MaterialPropertyId.Permittivity
|
|
139
|
+
self.__properties.permittivity = self.__property_value(material_property_id)
|
|
140
|
+
return self.__properties.permittivity
|
|
110
141
|
|
|
111
142
|
@permittivity.setter
|
|
112
143
|
def permittivity(self, value):
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
144
|
+
"""Set material permittivity."""
|
|
145
|
+
edb_value = self.__edb_value(value)
|
|
146
|
+
material_property_id = self.__edb_definition.MaterialPropertyId.Permittivity
|
|
147
|
+
self.__material_def.SetProperty(material_property_id, edb_value)
|
|
148
|
+
self.__properties.permittivity = edb_value.ToDouble()
|
|
116
149
|
|
|
117
150
|
@property
|
|
118
151
|
def permeability(self):
|
|
119
|
-
"""
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
152
|
+
"""Get material permeability."""
|
|
153
|
+
if self.__properties.permeability is None:
|
|
154
|
+
material_property_id = self.__edb_definition.MaterialPropertyId.Permeability
|
|
155
|
+
self.__properties.permeability = self.__property_value(material_property_id)
|
|
156
|
+
return self.__properties.permeability
|
|
123
157
|
|
|
124
158
|
@permeability.setter
|
|
125
159
|
def permeability(self, value):
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
160
|
+
"""Set material permeability."""
|
|
161
|
+
edb_value = self.__edb_value(value)
|
|
162
|
+
material_property_id = self.__edb_definition.MaterialPropertyId.Permeability
|
|
163
|
+
self.__material_def.SetProperty(material_property_id, edb_value)
|
|
164
|
+
self.__properties.permeability = edb_value.ToDouble()
|
|
129
165
|
|
|
130
166
|
@property
|
|
131
167
|
def loss_tangent(self):
|
|
132
|
-
"""
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
168
|
+
"""Get material loss tangent."""
|
|
169
|
+
warnings.warn(
|
|
170
|
+
"This method is deprecated in versions >0.7.0 and will soon be removed. "
|
|
171
|
+
"Use property dielectric_loss_tangent instead.",
|
|
172
|
+
DeprecationWarning,
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
return self.dielectric_loss_tangent
|
|
176
|
+
|
|
177
|
+
@property
|
|
178
|
+
def dielectric_loss_tangent(self):
|
|
179
|
+
"""Get material loss tangent."""
|
|
180
|
+
if self.__properties.dielectric_loss_tangent is None:
|
|
181
|
+
material_property_id = self.__edb_definition.MaterialPropertyId.DielectricLossTangent
|
|
182
|
+
self.__properties.dielectric_loss_tangent = self.__property_value(material_property_id)
|
|
183
|
+
return self.__properties.dielectric_loss_tangent
|
|
136
184
|
|
|
137
185
|
@loss_tangent.setter
|
|
138
186
|
def loss_tangent(self, value):
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
187
|
+
"""Set material loss tangent."""
|
|
188
|
+
warnings.warn(
|
|
189
|
+
"This method is deprecated in versions >0.7.0 and will soon be removed. "
|
|
190
|
+
"Use property dielectric_loss_tangent instead.",
|
|
191
|
+
DeprecationWarning,
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
return self.dielectric_loss_tangent(value)
|
|
195
|
+
|
|
196
|
+
@dielectric_loss_tangent.setter
|
|
197
|
+
def dielectric_loss_tangent(self, value):
|
|
198
|
+
"""Set material loss tangent."""
|
|
199
|
+
edb_value = self.__edb_value(value)
|
|
200
|
+
material_property_id = self.__edb_definition.MaterialPropertyId.DielectricLossTangent
|
|
201
|
+
self.__material_def.SetProperty(material_property_id, edb_value)
|
|
202
|
+
self.__properties.dielectric_loss_tangent = edb_value.ToDouble()
|
|
142
203
|
|
|
143
204
|
@property
|
|
144
205
|
def dc_conductivity(self):
|
|
145
|
-
""""""
|
|
146
|
-
if self.
|
|
147
|
-
|
|
206
|
+
"""Get material dielectric conductivity."""
|
|
207
|
+
if self.__dc_model and self.__properties.dc_conductivity is None:
|
|
208
|
+
self.__properties.dc_conductivity = self.__dc_model.GetDCConductivity()
|
|
209
|
+
return self.__properties.dc_conductivity
|
|
148
210
|
|
|
149
211
|
@dc_conductivity.setter
|
|
150
|
-
def dc_conductivity(self, value):
|
|
151
|
-
|
|
152
|
-
|
|
212
|
+
def dc_conductivity(self, value: Union[int, float]):
|
|
213
|
+
"""Set material dielectric conductivity."""
|
|
214
|
+
if self.__dc_model:
|
|
215
|
+
self.__dc_model.SetDCConductivity(value)
|
|
216
|
+
self.__properties.dc_conductivity = value
|
|
153
217
|
|
|
154
218
|
@property
|
|
155
219
|
def dc_permittivity(self):
|
|
156
|
-
""""""
|
|
157
|
-
if self.
|
|
158
|
-
|
|
220
|
+
"""Get material dielectric relative permittivity"""
|
|
221
|
+
if self.__dc_model and self.__properties.dc_permittivity is None:
|
|
222
|
+
self.__properties.dc_permittivity = self.__dc_model.GetDCRelativePermitivity()
|
|
223
|
+
return self.__properties.dc_permittivity
|
|
159
224
|
|
|
160
225
|
@dc_permittivity.setter
|
|
161
|
-
def dc_permittivity(self, value):
|
|
162
|
-
|
|
163
|
-
|
|
226
|
+
def dc_permittivity(self, value: Union[int, float]):
|
|
227
|
+
"""Set material dielectric relative permittivity"""
|
|
228
|
+
if self.__dc_model:
|
|
229
|
+
self.__dc_model.SetDCRelativePermitivity(value)
|
|
230
|
+
self.__properties.dc_permittivity = value
|
|
164
231
|
|
|
165
232
|
@property
|
|
166
233
|
def dielectric_model_frequency(self):
|
|
167
|
-
"""
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
Frequency in GHz
|
|
172
|
-
"""
|
|
173
|
-
if self._edb_material_def.GetDielectricMaterialModel():
|
|
174
|
-
return self._edb_material_def.GetDielectricMaterialModel().GetFrequency()
|
|
234
|
+
"""Get material frequency in GHz."""
|
|
235
|
+
if self.__dc_model and self.__properties.dielectric_model_frequency is None:
|
|
236
|
+
self.__properties.dielectric_model_frequency = self.__dc_model.GetFrequency()
|
|
237
|
+
return self.__properties.dielectric_model_frequency
|
|
175
238
|
|
|
176
239
|
@dielectric_model_frequency.setter
|
|
177
|
-
def dielectric_model_frequency(self, value):
|
|
178
|
-
|
|
179
|
-
|
|
240
|
+
def dielectric_model_frequency(self, value: Union[int, float]):
|
|
241
|
+
"""Get material frequency in GHz."""
|
|
242
|
+
if self.__dc_model:
|
|
243
|
+
self.__dc_model.SetFrequency(value)
|
|
244
|
+
self.__properties.dielectric_model_frequency = value
|
|
180
245
|
|
|
181
246
|
@property
|
|
182
247
|
def loss_tangent_at_frequency(self):
|
|
183
|
-
|
|
184
|
-
|
|
248
|
+
"""Get material loss tangeat at frequency."""
|
|
249
|
+
if self.__dc_model and self.__properties.loss_tangent_at_frequency is None:
|
|
250
|
+
self.__properties.loss_tangent_at_frequency = self.__dc_model.GetLossTangentAtFrequency()
|
|
251
|
+
return self.__properties.loss_tangent_at_frequency
|
|
185
252
|
|
|
186
253
|
@loss_tangent_at_frequency.setter
|
|
187
254
|
def loss_tangent_at_frequency(self, value):
|
|
188
|
-
|
|
189
|
-
|
|
255
|
+
"""Set material loss tangeat at frequency."""
|
|
256
|
+
if self.__dc_model:
|
|
257
|
+
edb_value = self.__edb_value(value)
|
|
258
|
+
self.__dc_model.SetLossTangentAtFrequency(edb_value)
|
|
259
|
+
self.__properties.dielectric_model_frequency = edb_value.ToDouble()
|
|
190
260
|
|
|
191
261
|
@property
|
|
192
262
|
def permittivity_at_frequency(self):
|
|
193
|
-
|
|
194
|
-
|
|
263
|
+
"""Get material relative permittivity at frequency."""
|
|
264
|
+
if self.__dc_model and self.__properties.permittivity_at_frequency is None:
|
|
265
|
+
self.__properties.permittivity_at_frequency = self.__dc_model.GetRelativePermitivityAtFrequency()
|
|
266
|
+
return self.__properties.permittivity_at_frequency
|
|
195
267
|
|
|
196
268
|
@permittivity_at_frequency.setter
|
|
197
|
-
def permittivity_at_frequency(self, value):
|
|
198
|
-
|
|
199
|
-
|
|
269
|
+
def permittivity_at_frequency(self, value: Union[int, float]):
|
|
270
|
+
"""Set material relative permittivity at frequency."""
|
|
271
|
+
if self.__dc_model:
|
|
272
|
+
self.__dc_model.SetRelativePermitivityAtFrequency(value)
|
|
273
|
+
self.__properties.permittivity_at_frequency = value
|
|
200
274
|
|
|
201
275
|
@property
|
|
202
276
|
def magnetic_loss_tangent(self):
|
|
203
|
-
"""
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
277
|
+
"""Get material magnetic loss tangent."""
|
|
278
|
+
if self.__properties.magnetic_loss_tangent is None:
|
|
279
|
+
material_property_id = self.__edb_definition.MaterialPropertyId.MagneticLossTangent
|
|
280
|
+
self.__properties.magnetic_loss_tangent = self.__property_value(material_property_id)
|
|
281
|
+
return self.__properties.magnetic_loss_tangent
|
|
207
282
|
|
|
208
283
|
@magnetic_loss_tangent.setter
|
|
209
284
|
def magnetic_loss_tangent(self, value):
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
285
|
+
"""Set material magnetic loss tangent."""
|
|
286
|
+
edb_value = self.__edb_value(value)
|
|
287
|
+
material_property_id = self.__edb_definition.MaterialPropertyId.MagneticLossTangent
|
|
288
|
+
self.__material_def.SetProperty(material_property_id, edb_value)
|
|
289
|
+
self.__properties.magnetic_loss_tangent = edb_value.ToDouble()
|
|
213
290
|
|
|
214
291
|
@property
|
|
215
292
|
def thermal_conductivity(self):
|
|
216
|
-
"""
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
293
|
+
"""Get material thermal conductivity."""
|
|
294
|
+
if self.__properties.thermal_conductivity is None:
|
|
295
|
+
material_property_id = self.__edb_definition.MaterialPropertyId.ThermalConductivity
|
|
296
|
+
self.__properties.thermal_conductivity = self.__property_value(material_property_id)
|
|
297
|
+
return self.__properties.thermal_conductivity
|
|
220
298
|
|
|
221
299
|
@thermal_conductivity.setter
|
|
222
300
|
def thermal_conductivity(self, value):
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
301
|
+
"""Set material thermal conductivity."""
|
|
302
|
+
edb_value = self.__edb_value(value)
|
|
303
|
+
material_property_id = self.__edb_definition.MaterialPropertyId.ThermalConductivity
|
|
304
|
+
self.__material_def.SetProperty(material_property_id, edb_value)
|
|
305
|
+
self.__properties.thermal_conductivity = edb_value.ToDouble()
|
|
226
306
|
|
|
227
307
|
@property
|
|
228
308
|
def mass_density(self):
|
|
229
|
-
"""
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
309
|
+
"""Get material mass density."""
|
|
310
|
+
if self.__properties.thermal_conductivity is None:
|
|
311
|
+
material_property_id = self.__edb_definition.MaterialPropertyId.MassDensity
|
|
312
|
+
self.__properties.mass_density = self.__property_value(material_property_id)
|
|
313
|
+
return self.__properties.mass_density
|
|
233
314
|
|
|
234
315
|
@mass_density.setter
|
|
235
316
|
def mass_density(self, value):
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
317
|
+
"""Set material mass density."""
|
|
318
|
+
edb_value = self.__edb_value(value)
|
|
319
|
+
material_property_id = self.__edb_definition.MaterialPropertyId.MassDensity
|
|
320
|
+
self.__material_def.SetProperty(material_property_id, edb_value)
|
|
321
|
+
self.__properties.mass_density = edb_value.ToDouble()
|
|
239
322
|
|
|
240
323
|
@property
|
|
241
324
|
def youngs_modulus(self):
|
|
242
|
-
"""
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
325
|
+
"""Get material youngs modulus."""
|
|
326
|
+
if self.__properties.youngs_modulus is None:
|
|
327
|
+
material_property_id = self.__edb_definition.MaterialPropertyId.YoungsModulus
|
|
328
|
+
self.__properties.youngs_modulus = self.__property_value(material_property_id)
|
|
329
|
+
return self.__properties.youngs_modulus
|
|
246
330
|
|
|
247
331
|
@youngs_modulus.setter
|
|
248
332
|
def youngs_modulus(self, value):
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
333
|
+
"""Set material youngs modulus."""
|
|
334
|
+
edb_value = self.__edb_value(value)
|
|
335
|
+
material_property_id = self.__edb_definition.MaterialPropertyId.YoungsModulus
|
|
336
|
+
self.__material_def.SetProperty(material_property_id, edb_value)
|
|
337
|
+
self.__properties.youngs_modulus = edb_value.ToDouble()
|
|
252
338
|
|
|
253
339
|
@property
|
|
254
340
|
def specific_heat(self):
|
|
255
|
-
"""
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
341
|
+
"""Get material specific heat."""
|
|
342
|
+
if self.__properties.specific_heat is None:
|
|
343
|
+
material_property_id = self.__edb_definition.MaterialPropertyId.SpecificHeat
|
|
344
|
+
self.__properties.specific_heat = self.__property_value(material_property_id)
|
|
345
|
+
return self.__properties.specific_heat
|
|
259
346
|
|
|
260
347
|
@specific_heat.setter
|
|
261
348
|
def specific_heat(self, value):
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
349
|
+
"""Set material specific heat."""
|
|
350
|
+
edb_value = self.__edb_value(value)
|
|
351
|
+
material_property_id = self.__edb_definition.MaterialPropertyId.SpecificHeat
|
|
352
|
+
self.__material_def.SetProperty(material_property_id, edb_value)
|
|
353
|
+
self.__properties.specific_heat = edb_value.ToDouble()
|
|
265
354
|
|
|
266
355
|
@property
|
|
267
356
|
def poisson_ratio(self):
|
|
268
|
-
"""
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
357
|
+
"""Get material poisson ratio."""
|
|
358
|
+
if self.__properties.specific_heat is None:
|
|
359
|
+
material_property_id = self.__edb_definition.MaterialPropertyId.PoissonsRatio
|
|
360
|
+
self.__properties.poisson_ratio = self.__property_value(material_property_id)
|
|
361
|
+
return self.__properties.poisson_ratio
|
|
272
362
|
|
|
273
363
|
@poisson_ratio.setter
|
|
274
364
|
def poisson_ratio(self, value):
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
365
|
+
"""Set material poisson ratio."""
|
|
366
|
+
edb_value = self.__edb_value(value)
|
|
367
|
+
material_property_id = self.__edb_definition.MaterialPropertyId.PoissonsRatio
|
|
368
|
+
self.__material_def.SetProperty(material_property_id, edb_value)
|
|
369
|
+
self.__properties.poisson_ratio = edb_value.ToDouble()
|
|
278
370
|
|
|
279
371
|
@property
|
|
280
372
|
def thermal_expansion_coefficient(self):
|
|
281
|
-
"""
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
373
|
+
"""Get material thermal coefficient."""
|
|
374
|
+
if self.__properties.thermal_expansion_coefficient is None:
|
|
375
|
+
material_property_id = self.__edb_definition.MaterialPropertyId.ThermalExpansionCoefficient
|
|
376
|
+
self.__properties.thermal_expansion_coefficient = self.__property_value(material_property_id)
|
|
377
|
+
return self.__properties.thermal_expansion_coefficient
|
|
285
378
|
|
|
286
379
|
@thermal_expansion_coefficient.setter
|
|
287
380
|
def thermal_expansion_coefficient(self, value):
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
381
|
+
"""Set material thermal coefficient."""
|
|
382
|
+
edb_value = self.__edb_value(value)
|
|
383
|
+
material_property_id = self.__edb_definition.MaterialPropertyId.ThermalExpansionCoefficient
|
|
384
|
+
self.__material_def.SetProperty(material_property_id, self.__edb_value(value))
|
|
385
|
+
self.__properties.thermal_expansion_coefficient = edb_value.ToDouble()
|
|
291
386
|
|
|
292
387
|
@pyedb_function_handler()
|
|
293
|
-
def
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
self._conductivity = self.conductivity
|
|
301
|
-
self._loss_tangent = self.loss_tangent
|
|
302
|
-
self._magnetic_loss_tangent = self.magnetic_loss_tangent
|
|
303
|
-
self._mass_density = self.mass_density
|
|
304
|
-
self._permittivity = self.permittivity
|
|
305
|
-
self._permeability = self.permeability
|
|
306
|
-
self._poisson_ratio = self.poisson_ratio
|
|
307
|
-
self._specific_heat = self.specific_heat
|
|
308
|
-
self._thermal_conductivity = self.thermal_conductivity
|
|
309
|
-
self._youngs_modulus = self.youngs_modulus
|
|
310
|
-
self._thermal_expansion_coefficient = self.thermal_expansion_coefficient
|
|
311
|
-
self._dc_conductivity = self.dc_conductivity
|
|
312
|
-
self._dc_permittivity = self.dc_permittivity
|
|
313
|
-
self._dielectric_model_frequency = self.dielectric_model_frequency
|
|
314
|
-
self._loss_tangent_at_frequency = self.loss_tangent_at_frequency
|
|
315
|
-
self._permittivity_at_frequency = self.permittivity_at_frequency
|
|
316
|
-
for k, v in self.__dict__.items():
|
|
317
|
-
if not k == "_pclass" and not k == "_edb_material_def":
|
|
318
|
-
out_dict[k[1:]] = v
|
|
319
|
-
return out_dict
|
|
388
|
+
def to_dict(self):
|
|
389
|
+
"""Convert material into dictionary."""
|
|
390
|
+
self.__load_all_properties()
|
|
391
|
+
|
|
392
|
+
res = {"name": self.name}
|
|
393
|
+
res.update(self.__properties.model_dump())
|
|
394
|
+
return res
|
|
320
395
|
|
|
321
396
|
@pyedb_function_handler()
|
|
322
|
-
def
|
|
323
|
-
default_material = {
|
|
324
|
-
"name": "default",
|
|
325
|
-
"conductivity": 0,
|
|
326
|
-
"loss_tangent": 0,
|
|
327
|
-
"magnetic_loss_tangent": 0,
|
|
328
|
-
"mass_density": 0,
|
|
329
|
-
"permittivity": 1,
|
|
330
|
-
"permeability": 1,
|
|
331
|
-
"poisson_ratio": 0,
|
|
332
|
-
"specific_heat": 0,
|
|
333
|
-
"thermal_conductivity": 0,
|
|
334
|
-
"youngs_modulus": 0,
|
|
335
|
-
"thermal_expansion_coefficient": 0,
|
|
336
|
-
"dielectric_model_frequency": None,
|
|
337
|
-
"dc_permittivity": None,
|
|
338
|
-
}
|
|
397
|
+
def update(self, input_dict: dict):
|
|
339
398
|
if input_dict:
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
399
|
+
# Update attributes
|
|
400
|
+
for attribute in ATTRIBUTES:
|
|
401
|
+
if attribute in input_dict:
|
|
402
|
+
setattr(self, attribute, input_dict[attribute])
|
|
403
|
+
if "loss_tangent" in input_dict:
|
|
404
|
+
setattr(self, "loss_tangent", input_dict["loss_tangent"])
|
|
405
|
+
|
|
406
|
+
# Update DS model
|
|
407
|
+
# NOTE: Contrary to before we don't test 'dielectric_model_frequency' only
|
|
408
|
+
if any(map(lambda attribute: input_dict.get(attribute, None) is not None, DC_ATTRIBUTES)):
|
|
409
|
+
if not self.__dc_model:
|
|
410
|
+
self.__dc_model = self.__edb_definition.DjordjecvicSarkarModel()
|
|
411
|
+
for attribute in DC_ATTRIBUTES:
|
|
412
|
+
if attribute in input_dict:
|
|
413
|
+
if attribute == "dc_permittivity" and input_dict[attribute] is not None:
|
|
414
|
+
self.__dc_model.SetUseDCRelativePermitivity(True)
|
|
415
|
+
setattr(self, attribute, input_dict[attribute])
|
|
416
|
+
self.__material_def.SetDielectricMaterialModel(self.__dc_model)
|
|
417
|
+
# Unset DS model if it is already assigned to the material in the database
|
|
418
|
+
elif self.__dc_model:
|
|
419
|
+
self.__material_def.SetDielectricMaterialModel(self.__edb_value(None))
|
|
420
|
+
|
|
421
|
+
@pyedb_function_handler()
|
|
422
|
+
def __edb_value(self, value):
|
|
423
|
+
"""Convert a value to an EDB value.
|
|
424
|
+
|
|
425
|
+
Parameters
|
|
426
|
+
----------
|
|
427
|
+
val : str, float, int
|
|
428
|
+
"""
|
|
429
|
+
return self.__edb.edb_value(value)
|
|
430
|
+
|
|
431
|
+
@pyedb_function_handler()
|
|
432
|
+
def __load_all_properties(self):
|
|
433
|
+
"""Load all properties of the material."""
|
|
434
|
+
for property in self.__properties.model_dump().keys():
|
|
435
|
+
_ = getattr(self, property)
|
|
436
|
+
|
|
437
|
+
@pyedb_function_handler()
|
|
438
|
+
def __property_value(self, material_property_id):
|
|
439
|
+
"""Get property value from a material property id."""
|
|
440
|
+
if is_ironpython: # pragma: no cover
|
|
441
|
+
property_box = _clr.StrongBox[float]()
|
|
442
|
+
self.__material_def.GetProperty(material_property_id, property_box)
|
|
443
|
+
return float(property_box)
|
|
444
|
+
else:
|
|
445
|
+
_, property_box = self.__material_def.GetProperty(material_property_id)
|
|
446
|
+
if isinstance(property_box, float):
|
|
447
|
+
return property_box
|
|
377
448
|
else:
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
449
|
+
return property_box.ToDouble()
|
|
450
|
+
|
|
451
|
+
# def __reset_property(self, name):
|
|
452
|
+
# """Reset a property using the default value of the EDB API.
|
|
453
|
+
#
|
|
454
|
+
# This method consists in resetting the value of a property by updating the inner property
|
|
455
|
+
# to ``None`` and accessing the property afterward. When one wants to access a property
|
|
456
|
+
# whose stored inner value is ``None``, the value is updated to the EDB API default value
|
|
457
|
+
# associated to that property.
|
|
458
|
+
# """
|
|
459
|
+
# # Update inner property to None
|
|
460
|
+
# setattr(self.__properties, name, None)
|
|
461
|
+
# # Trigger get value on the property
|
|
462
|
+
# _ = getattr(self, name)
|
|
381
463
|
|
|
382
464
|
|
|
383
465
|
class Materials(object):
|
|
384
466
|
"""Manages EDB methods for material management accessible from `Edb.materials` property."""
|
|
385
467
|
|
|
386
|
-
def
|
|
387
|
-
|
|
468
|
+
def __init__(self, edb: Edb):
|
|
469
|
+
self.__edb = edb
|
|
470
|
+
self.__edb_definition = edb.edb_api.definition
|
|
471
|
+
self.__syslib = os.path.join(self.__edb.base_path, "syslib")
|
|
472
|
+
self.__materials: dict[str, Material] = {
|
|
473
|
+
material_def.GetName(): Material(self.__edb, material_def)
|
|
474
|
+
for material_def in list(self.__edb.active_db.MaterialDefs)
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
def __contains__(self, item):
|
|
478
|
+
if isinstance(item, Material):
|
|
479
|
+
return item.name in self.__materials
|
|
480
|
+
else:
|
|
481
|
+
return item in self.__materials
|
|
388
482
|
|
|
389
|
-
def
|
|
390
|
-
self.
|
|
391
|
-
self._syslib = os.path.join(self._pedb.base_path, "syslib")
|
|
392
|
-
if not self.materials:
|
|
393
|
-
self.add_material("air")
|
|
394
|
-
self.add_material("copper", 1, 0.999991, 5.8e7, 0, 0)
|
|
395
|
-
self.add_material("fr4_epoxy", 4.4, 1, 0, 0.02, 0)
|
|
396
|
-
self.add_material("solder_mask", 3.1, 1, 0, 0.035, 0)
|
|
483
|
+
def __getitem__(self, item):
|
|
484
|
+
return self.__materials[item]
|
|
397
485
|
|
|
398
486
|
@property
|
|
399
487
|
def syslib(self):
|
|
400
|
-
"""
|
|
401
|
-
return self.
|
|
402
|
-
|
|
403
|
-
@pyedb_function_handler()
|
|
404
|
-
def _edb_value(self, value):
|
|
405
|
-
return self._pedb.edb_value(value)
|
|
488
|
+
"""Get the project sys library."""
|
|
489
|
+
return self.__syslib
|
|
406
490
|
|
|
407
491
|
@property
|
|
408
|
-
def
|
|
409
|
-
|
|
492
|
+
def materials(self):
|
|
493
|
+
"""Get materials."""
|
|
494
|
+
return self.__materials
|
|
410
495
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
return self._pedb.active_db
|
|
496
|
+
def __edb_value(self, value):
|
|
497
|
+
"""Convert a value to an EDB value.
|
|
414
498
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
499
|
+
Parameters
|
|
500
|
+
----------
|
|
501
|
+
val : str, float, int
|
|
502
|
+
"""
|
|
503
|
+
return self.__edb.edb_value(value)
|
|
419
504
|
|
|
420
505
|
@pyedb_function_handler()
|
|
421
|
-
def add_material(
|
|
422
|
-
self,
|
|
423
|
-
name="air",
|
|
424
|
-
permittivity=1.0006,
|
|
425
|
-
permeability=1.0000004,
|
|
426
|
-
conductivity=0,
|
|
427
|
-
dielectric_loss_tangent=0,
|
|
428
|
-
magnetic_loss_tangent=0,
|
|
429
|
-
):
|
|
506
|
+
def add_material(self, name: str, **kwargs):
|
|
430
507
|
"""Add a new material.
|
|
431
508
|
|
|
432
509
|
Parameters
|
|
433
510
|
----------
|
|
434
|
-
name : str
|
|
435
|
-
Material
|
|
436
|
-
permittivity : float, str, optional
|
|
437
|
-
Material permittivity. The default is ``1.0006``.
|
|
438
|
-
permeability : float, str, optional
|
|
439
|
-
Material permeability. The default is ``1.0000004``.
|
|
440
|
-
conductivity : float, str, optional
|
|
441
|
-
Material conductivity. The default is ``0``.
|
|
442
|
-
dielectric_loss_tangent : float, str, optional
|
|
443
|
-
Material dielectric loss tangent. The default is ``0``.
|
|
444
|
-
magnetic_loss_tangent : float, str, optional
|
|
445
|
-
Material magnetic loss tangent. The default is ``0``.
|
|
511
|
+
name : str
|
|
512
|
+
Material name.
|
|
446
513
|
|
|
447
514
|
Returns
|
|
448
515
|
-------
|
|
449
516
|
:class:`pyedb.dotnet.edb_core.materials.Material`
|
|
450
517
|
"""
|
|
451
|
-
if
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
518
|
+
if name in self.__materials:
|
|
519
|
+
raise ValueError(f"Material {name} already exists in material library.")
|
|
520
|
+
|
|
521
|
+
material_def = self.__edb_definition.MaterialDef.Create(self.__edb.active_db, name)
|
|
522
|
+
material = Material(self.__edb, material_def)
|
|
523
|
+
attributes_input_dict = {key: val for (key, val) in kwargs.items() if key in ATTRIBUTES + DC_ATTRIBUTES}
|
|
524
|
+
if "loss_tangent" in kwargs:
|
|
525
|
+
warnings.warn(
|
|
526
|
+
"This key is deprecated in versions >0.7.0 and will soon be removed. "
|
|
527
|
+
"Use key dielectric_loss_tangent instead.",
|
|
528
|
+
DeprecationWarning,
|
|
529
|
+
)
|
|
530
|
+
attributes_input_dict["dielectric_loss_tangent"] = kwargs["loss_tangent"]
|
|
531
|
+
if attributes_input_dict:
|
|
532
|
+
material.update(attributes_input_dict)
|
|
533
|
+
|
|
534
|
+
self.__materials[name] = material
|
|
535
|
+
return material
|
|
463
536
|
|
|
464
537
|
@pyedb_function_handler()
|
|
465
|
-
def add_conductor_material(self, name, conductivity):
|
|
466
|
-
"""Add a new conductor material
|
|
538
|
+
def add_conductor_material(self, name, conductivity, **kwargs):
|
|
539
|
+
"""Add a new conductor material.
|
|
467
540
|
|
|
468
541
|
Parameters
|
|
469
542
|
----------
|
|
470
543
|
name : str
|
|
471
544
|
Name of the new material.
|
|
472
|
-
conductivity : float
|
|
545
|
+
conductivity : str, float, int
|
|
473
546
|
Conductivity of the new material.
|
|
474
547
|
|
|
475
548
|
Returns
|
|
@@ -477,99 +550,99 @@ class Materials(object):
|
|
|
477
550
|
:class:`pyedb.dotnet.edb_core.materials.Material`
|
|
478
551
|
|
|
479
552
|
"""
|
|
480
|
-
if
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
return False
|
|
553
|
+
if name in self.__materials:
|
|
554
|
+
raise ValueError(f"Material {name} already exists in material library.")
|
|
555
|
+
|
|
556
|
+
extended_kwargs = {key: value for (key, value) in kwargs.items()}
|
|
557
|
+
extended_kwargs["conductivity"] = conductivity
|
|
558
|
+
material = self.add_material(name, **extended_kwargs)
|
|
559
|
+
|
|
560
|
+
self.__materials[name] = material
|
|
561
|
+
return material
|
|
490
562
|
|
|
491
563
|
@pyedb_function_handler()
|
|
492
|
-
def add_dielectric_material(self, name, permittivity,
|
|
564
|
+
def add_dielectric_material(self, name, permittivity, dielectric_loss_tangent, **kwargs):
|
|
493
565
|
"""Add a new dielectric material in library.
|
|
494
566
|
|
|
495
567
|
Parameters
|
|
496
568
|
----------
|
|
497
569
|
name : str
|
|
498
570
|
Name of the new material.
|
|
499
|
-
permittivity : float
|
|
571
|
+
permittivity : str, float, int
|
|
500
572
|
Permittivity of the new material.
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
permeability : float
|
|
504
|
-
Permeability of the new material.
|
|
573
|
+
dielectric_loss_tangent : str, float, int
|
|
574
|
+
Dielectric loss tangent of the new material.
|
|
505
575
|
|
|
506
576
|
Returns
|
|
507
577
|
-------
|
|
508
578
|
:class:`pyedb.dotnet.edb_core.materials.Material`
|
|
509
579
|
"""
|
|
510
|
-
if
|
|
511
|
-
|
|
512
|
-
new_material = self.materials[name]
|
|
513
|
-
new_material.permittivity = permittivity
|
|
514
|
-
new_material.loss_tangent = loss_tangent
|
|
515
|
-
new_material.permeability = permeability
|
|
516
|
-
return new_material
|
|
517
|
-
else:
|
|
518
|
-
warnings.warn("Material {} already exists in material library.".format(name))
|
|
519
|
-
return False
|
|
580
|
+
if name in self.__materials:
|
|
581
|
+
raise ValueError(f"Material {name} already exists in material library.")
|
|
520
582
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
""
|
|
583
|
+
extended_kwargs = {key: value for (key, value) in kwargs.items()}
|
|
584
|
+
extended_kwargs["permittivity"] = permittivity
|
|
585
|
+
extended_kwargs["dielectric_loss_tangent"] = dielectric_loss_tangent
|
|
586
|
+
material = self.add_material(name, **extended_kwargs)
|
|
524
587
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
material_name : str
|
|
528
|
-
|
|
529
|
-
Returns
|
|
530
|
-
-------
|
|
531
|
-
|
|
532
|
-
"""
|
|
533
|
-
material = self.materials[material_name]
|
|
534
|
-
if material:
|
|
535
|
-
return material.GetDielectricMaterialModel()
|
|
588
|
+
self.__materials[name] = material
|
|
589
|
+
return material
|
|
536
590
|
|
|
537
591
|
@pyedb_function_handler()
|
|
538
|
-
def
|
|
539
|
-
self,
|
|
592
|
+
def add_djordjevicsarkar_dielectric(
|
|
593
|
+
self,
|
|
594
|
+
name,
|
|
595
|
+
permittivity_at_frequency,
|
|
596
|
+
loss_tangent_at_frequency,
|
|
597
|
+
dielectric_model_frequency,
|
|
598
|
+
dc_conductivity=None,
|
|
599
|
+
dc_permittivity=None,
|
|
600
|
+
**kwargs,
|
|
540
601
|
):
|
|
541
|
-
"""
|
|
602
|
+
"""Add a dielectric using the Djordjevic-Sarkar model.
|
|
542
603
|
|
|
543
604
|
Parameters
|
|
544
605
|
----------
|
|
545
606
|
name : str
|
|
546
607
|
Name of the dielectric.
|
|
547
|
-
|
|
608
|
+
permittivity_at_frequency : str, float, int
|
|
548
609
|
Relative permittivity of the dielectric.
|
|
549
|
-
|
|
610
|
+
loss_tangent_at_frequency : str, float, int
|
|
550
611
|
Loss tangent for the material.
|
|
551
|
-
|
|
612
|
+
dielectric_model_frequency : str, float, int
|
|
552
613
|
Test frequency in GHz for the dielectric.
|
|
553
|
-
dc_permittivity : float, optional
|
|
554
|
-
DC Relative permittivity of the dielectric.
|
|
555
|
-
dc_conductivity : float, optional
|
|
556
|
-
DC Conductivity of the dielectric.
|
|
557
614
|
|
|
558
615
|
Returns
|
|
559
616
|
-------
|
|
560
617
|
:class:`pyedb.dotnet.edb_core.materials.Material`
|
|
561
|
-
Material definition.
|
|
562
618
|
"""
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
619
|
+
if name in self.__materials:
|
|
620
|
+
raise ValueError(f"Material {name} already exists in material library.")
|
|
621
|
+
|
|
622
|
+
material_model = self.__edb_definition.DjordjecvicSarkarModel()
|
|
623
|
+
material_model.SetRelativePermitivityAtFrequency(permittivity_at_frequency)
|
|
624
|
+
material_model.SetLossTangentAtFrequency(self.__edb_value(loss_tangent_at_frequency))
|
|
625
|
+
material_model.SetFrequency(dielectric_model_frequency)
|
|
567
626
|
if dc_conductivity is not None:
|
|
568
|
-
|
|
627
|
+
material_model.SetDCConductivity(dc_conductivity)
|
|
569
628
|
if dc_permittivity is not None:
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
629
|
+
material_model.SetUseDCRelativePermitivity(True)
|
|
630
|
+
material_model.SetDCRelativePermitivity(dc_permittivity)
|
|
631
|
+
try:
|
|
632
|
+
material = self.__add_dielectric_material_model(name, material_model)
|
|
633
|
+
for key, value in kwargs.items():
|
|
634
|
+
setattr(material, key, value)
|
|
635
|
+
if "loss_tangent" in kwargs:
|
|
636
|
+
warnings.warn(
|
|
637
|
+
"This key is deprecated in versions >0.7.0 and will soon be removed. "
|
|
638
|
+
"Use key dielectric_loss_tangent instead.",
|
|
639
|
+
DeprecationWarning,
|
|
640
|
+
)
|
|
641
|
+
setattr(material, "dielectric_loss_tangent", kwargs["loss_tangent"])
|
|
642
|
+
self.__materials[name] = material
|
|
643
|
+
return material
|
|
644
|
+
except MaterialModelException:
|
|
645
|
+
raise ValueError("Use realistic values to define DS model.")
|
|
573
646
|
|
|
574
647
|
@pyedb_function_handler()
|
|
575
648
|
def add_debye_material(
|
|
@@ -581,42 +654,61 @@ class Materials(object):
|
|
|
581
654
|
loss_tangent_high,
|
|
582
655
|
lower_freqency,
|
|
583
656
|
higher_frequency,
|
|
657
|
+
**kwargs,
|
|
584
658
|
):
|
|
585
|
-
"""
|
|
659
|
+
"""Add a dielectric with the Debye model.
|
|
586
660
|
|
|
587
661
|
Parameters
|
|
588
662
|
----------
|
|
589
663
|
name : str
|
|
590
664
|
Name of the dielectric.
|
|
591
|
-
permittivity_low : float
|
|
665
|
+
permittivity_low : float, int
|
|
592
666
|
Relative permittivity of the dielectric at the frequency specified
|
|
593
667
|
for ``lower_frequency``.
|
|
594
|
-
permittivity_high : float
|
|
668
|
+
permittivity_high : float, int
|
|
595
669
|
Relative permittivity of the dielectric at the frequency specified
|
|
596
670
|
for ``higher_frequency``.
|
|
597
|
-
loss_tangent_low : float
|
|
671
|
+
loss_tangent_low : float, int
|
|
598
672
|
Loss tangent for the material at the frequency specified
|
|
599
673
|
for ``lower_frequency``.
|
|
600
|
-
loss_tangent_high : float
|
|
674
|
+
loss_tangent_high : float, int
|
|
601
675
|
Loss tangent for the material at the frequency specified
|
|
602
676
|
for ``higher_frequency``.
|
|
603
|
-
lower_freqency : float
|
|
677
|
+
lower_freqency : str, float, int
|
|
604
678
|
Value for the lower frequency.
|
|
605
|
-
higher_frequency : float
|
|
679
|
+
higher_frequency : str, float, int
|
|
606
680
|
Value for the higher frequency.
|
|
607
681
|
|
|
608
682
|
Returns
|
|
609
683
|
-------
|
|
610
684
|
:class:`pyedb.dotnet.edb_core.materials.Material`
|
|
611
|
-
Material definition.
|
|
612
685
|
"""
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
686
|
+
if name in self.__materials:
|
|
687
|
+
raise ValueError(f"Material {name} already exists in material library.")
|
|
688
|
+
|
|
689
|
+
material_model = self.__edb_definition.DebyeModel()
|
|
690
|
+
# FIXME: Seems like there is a bug here (we need to provide higher value for
|
|
691
|
+
# lower_freqency than higher_frequency)
|
|
692
|
+
material_model.SetFrequencyRange(lower_freqency, higher_frequency)
|
|
693
|
+
material_model.SetLossTangentAtHighLowFrequency(loss_tangent_low, loss_tangent_high)
|
|
694
|
+
material_model.SetRelativePermitivityAtHighLowFrequency(
|
|
695
|
+
self.__edb_value(permittivity_low), self.__edb_value(permittivity_high)
|
|
618
696
|
)
|
|
619
|
-
|
|
697
|
+
try:
|
|
698
|
+
material = self.__add_dielectric_material_model(name, material_model)
|
|
699
|
+
for key, value in kwargs.items():
|
|
700
|
+
setattr(material, key, value)
|
|
701
|
+
if "loss_tangent" in kwargs:
|
|
702
|
+
warnings.warn(
|
|
703
|
+
"This key is deprecated in versions >0.7.0 and will soon be removed. "
|
|
704
|
+
"Use key dielectric_loss_tangent instead.",
|
|
705
|
+
DeprecationWarning,
|
|
706
|
+
)
|
|
707
|
+
setattr(material, "dielectric_loss_tangent", kwargs["loss_tangent"])
|
|
708
|
+
self.__materials[name] = material
|
|
709
|
+
return material
|
|
710
|
+
except MaterialModelException:
|
|
711
|
+
raise ValueError("Use realistic values to define Debye model.")
|
|
620
712
|
|
|
621
713
|
@pyedb_function_handler()
|
|
622
714
|
def add_multipole_debye_material(
|
|
@@ -625,8 +717,9 @@ class Materials(object):
|
|
|
625
717
|
frequencies,
|
|
626
718
|
permittivities,
|
|
627
719
|
loss_tangents,
|
|
720
|
+
**kwargs,
|
|
628
721
|
):
|
|
629
|
-
"""
|
|
722
|
+
"""Add a dielectric with the Multipole Debye model.
|
|
630
723
|
|
|
631
724
|
Parameters
|
|
632
725
|
----------
|
|
@@ -642,7 +735,6 @@ class Materials(object):
|
|
|
642
735
|
Returns
|
|
643
736
|
-------
|
|
644
737
|
:class:`pyedb.dotnet.edb_core.materials.Material`
|
|
645
|
-
Material definition.
|
|
646
738
|
|
|
647
739
|
Examples
|
|
648
740
|
--------
|
|
@@ -653,32 +745,58 @@ class Materials(object):
|
|
|
653
745
|
>>> loss_tan = [0.025, 0.026, 0.027, 0.028, 0.029, 0.030]
|
|
654
746
|
>>> diel = edb.materials.add_multipole_debye_material("My_MP_Debye", freq, rel_perm, loss_tan)
|
|
655
747
|
"""
|
|
748
|
+
if name in self.__materials:
|
|
749
|
+
raise ValueError(f"Material {name} already exists in material library.")
|
|
750
|
+
|
|
656
751
|
frequencies = [float(i) for i in frequencies]
|
|
657
752
|
permittivities = [float(i) for i in permittivities]
|
|
658
753
|
loss_tangents = [float(i) for i in loss_tangents]
|
|
659
|
-
|
|
660
|
-
|
|
754
|
+
material_model = self.__edb_definition.MultipoleDebyeModel()
|
|
755
|
+
material_model.SetParameters(
|
|
661
756
|
convert_py_list_to_net_list(frequencies),
|
|
662
757
|
convert_py_list_to_net_list(permittivities),
|
|
663
758
|
convert_py_list_to_net_list(loss_tangents),
|
|
664
759
|
)
|
|
665
|
-
|
|
760
|
+
try:
|
|
761
|
+
material = self.__add_dielectric_material_model(name, material_model)
|
|
762
|
+
for key, value in kwargs.items():
|
|
763
|
+
setattr(material, key, value)
|
|
764
|
+
if "loss_tangent" in kwargs:
|
|
765
|
+
warnings.warn(
|
|
766
|
+
"This key is deprecated in versions >0.7.0 and will soon be removed. "
|
|
767
|
+
"Use key dielectric_loss_tangent instead.",
|
|
768
|
+
DeprecationWarning,
|
|
769
|
+
)
|
|
770
|
+
setattr(material, "dielectric_loss_tangent", kwargs["loss_tangent"])
|
|
771
|
+
self.__materials[name] = material
|
|
772
|
+
return material
|
|
773
|
+
except MaterialModelException:
|
|
774
|
+
raise ValueError("Use realistic values to define Multipole Debye model.")
|
|
666
775
|
|
|
667
776
|
@pyedb_function_handler()
|
|
668
|
-
def
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
777
|
+
def __add_dielectric_material_model(self, name, material_model):
|
|
778
|
+
"""Add a dielectric material model.
|
|
779
|
+
|
|
780
|
+
Parameters
|
|
781
|
+
----------
|
|
782
|
+
name : str
|
|
783
|
+
Name of the dielectric.
|
|
784
|
+
material_model : Any
|
|
785
|
+
Dielectric material model.
|
|
786
|
+
"""
|
|
787
|
+
if self.__edb_definition.MaterialDef.FindByName(self.__edb.active_db, name).IsNull():
|
|
788
|
+
self.__edb_definition.MaterialDef.Create(self.__edb.active_db, name)
|
|
789
|
+
material_def = self.__edb_definition.MaterialDef.FindByName(self.__edb.active_db, name)
|
|
672
790
|
succeeded = material_def.SetDielectricMaterialModel(material_model)
|
|
673
791
|
if succeeded:
|
|
674
|
-
|
|
675
|
-
|
|
792
|
+
material = Material(self.__edb, material_def)
|
|
793
|
+
return material
|
|
794
|
+
raise MaterialModelException("Set dielectric material model failed.")
|
|
676
795
|
|
|
677
796
|
@pyedb_function_handler()
|
|
678
797
|
def duplicate(self, material_name, new_material_name):
|
|
679
798
|
"""Duplicate a material from the database.
|
|
680
799
|
|
|
681
|
-
|
|
682
800
|
Parameters
|
|
683
801
|
----------
|
|
684
802
|
material_name : str
|
|
@@ -688,53 +806,52 @@ class Materials(object):
|
|
|
688
806
|
|
|
689
807
|
Returns
|
|
690
808
|
-------
|
|
691
|
-
|
|
809
|
+
:class:`pyedb.dotnet.edb_core.materials.Material`
|
|
810
|
+
"""
|
|
811
|
+
if new_material_name in self.__materials:
|
|
812
|
+
raise ValueError(f"Material {new_material_name} already exists in material library.")
|
|
692
813
|
|
|
814
|
+
material = self.materials[material_name]
|
|
815
|
+
material_def = self.__edb_definition.MaterialDef.Create(self.__edb.active_db, new_material_name)
|
|
816
|
+
material_dict = material.to_dict()
|
|
817
|
+
new_material = Material(self.__edb, material_def)
|
|
818
|
+
new_material.update(material_dict)
|
|
693
819
|
|
|
694
|
-
|
|
695
|
-
|
|
820
|
+
self.__materials[new_material_name] = new_material
|
|
821
|
+
return new_material
|
|
696
822
|
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
823
|
+
@pyedb_function_handler()
|
|
824
|
+
def delete_material(self, material_name):
|
|
825
|
+
"""Remove a material from the database."""
|
|
826
|
+
material_def = self.__edb_definition.MaterialDef.FindByName(self.__edb.active_db, material_name)
|
|
827
|
+
if material_def.IsNull():
|
|
828
|
+
raise ValueError(f"Cannot find material {material_name}.")
|
|
829
|
+
material_def.Delete()
|
|
830
|
+
del self.__materials[material_name]
|
|
700
831
|
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
mass_density = self._edb_value(self.materials[material_name].mass_density)
|
|
715
|
-
material_model = self.materials[material_name]._edb_material_def.GetDielectricMaterialModel()
|
|
716
|
-
edb_material = self._edb.definition.MaterialDef.Create(self._db, new_material_name)
|
|
717
|
-
edb_material.SetProperty(self._edb.definition.MaterialPropertyId.Permittivity, permittivity)
|
|
718
|
-
edb_material.SetProperty(self._edb.definition.MaterialPropertyId.Permeability, permeability)
|
|
719
|
-
edb_material.SetProperty(self._edb.definition.MaterialPropertyId.Conductivity, conductivity)
|
|
720
|
-
edb_material.SetProperty(
|
|
721
|
-
self._edb.definition.MaterialPropertyId.DielectricLossTangent, dielectric_loss_tangent
|
|
722
|
-
)
|
|
723
|
-
edb_material.SetProperty(self._edb.definition.MaterialPropertyId.ThermalConductivity, thermal_conductivity)
|
|
724
|
-
edb_material.SetProperty(
|
|
725
|
-
self._edb.definition.MaterialPropertyId.ThermalExpansionCoefficient, thermal_expansion_coefficient
|
|
832
|
+
@pyedb_function_handler()
|
|
833
|
+
def update_material(self, material_name, input_dict):
|
|
834
|
+
"""Update material attributes."""
|
|
835
|
+
if material_name not in self.__materials:
|
|
836
|
+
raise ValueError(f"Material {material_name} does not exist in material library.")
|
|
837
|
+
|
|
838
|
+
material = self[material_name]
|
|
839
|
+
attributes_input_dict = {key: val for (key, val) in input_dict.items() if key in ATTRIBUTES + DC_ATTRIBUTES}
|
|
840
|
+
if "loss_tangent" in input_dict:
|
|
841
|
+
warnings.warn(
|
|
842
|
+
"This key is deprecated in versions >0.7.0 and will soon be removed. "
|
|
843
|
+
"Use key dielectric_loss_tangent instead.",
|
|
844
|
+
DeprecationWarning,
|
|
726
845
|
)
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
edb_material.SetDielectricMaterialModel(material_model)
|
|
733
|
-
|
|
734
|
-
return edb_material
|
|
846
|
+
attributes_input_dict["dielectric_loss_tangent"] = input_dict["loss_tangent"]
|
|
847
|
+
if attributes_input_dict:
|
|
848
|
+
material.update(attributes_input_dict)
|
|
849
|
+
self.__materials[material_name] = material
|
|
850
|
+
return material
|
|
735
851
|
|
|
736
852
|
@pyedb_function_handler()
|
|
737
|
-
def
|
|
853
|
+
def load_material(self, material):
|
|
854
|
+
"""Load material."""
|
|
738
855
|
if self.materials:
|
|
739
856
|
mat_keys = [i.lower() for i in self.materials.keys()]
|
|
740
857
|
mat_keys_case = [i for i in self.materials.keys()]
|
|
@@ -755,8 +872,26 @@ class Materials(object):
|
|
|
755
872
|
else:
|
|
756
873
|
self.materials[mat_keys_case[mat_keys.index(material["name"].lower())]]._load(material)
|
|
757
874
|
|
|
875
|
+
if material:
|
|
876
|
+
material_name = material["name"]
|
|
877
|
+
material_conductivity = material.get("conductivity", None)
|
|
878
|
+
if material_conductivity and material_conductivity > 1e4:
|
|
879
|
+
self.add_conductor_material(material_name, material_conductivity)
|
|
880
|
+
else:
|
|
881
|
+
material_permittivity = material["permittivity"]
|
|
882
|
+
if "loss_tangent" in material:
|
|
883
|
+
warnings.warn(
|
|
884
|
+
"This key is deprecated in versions >0.7.0 and will soon be removed. "
|
|
885
|
+
"Use key dielectric_loss_tangent instead.",
|
|
886
|
+
DeprecationWarning,
|
|
887
|
+
)
|
|
888
|
+
material_dlt = material["loss_tangent"]
|
|
889
|
+
else:
|
|
890
|
+
material_dlt = material["dielectric_loss_tangent"]
|
|
891
|
+
self.add_dielectric_material(material_name, material_permittivity, material_dlt)
|
|
892
|
+
|
|
758
893
|
@pyedb_function_handler()
|
|
759
|
-
def
|
|
894
|
+
def material_property_to_id(self, property_name):
|
|
760
895
|
"""Convert a material property name to a material property ID.
|
|
761
896
|
|
|
762
897
|
Parameters
|
|
@@ -766,78 +901,36 @@ class Materials(object):
|
|
|
766
901
|
|
|
767
902
|
Returns
|
|
768
903
|
-------
|
|
769
|
-
|
|
904
|
+
Any
|
|
770
905
|
"""
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
"
|
|
774
|
-
"
|
|
775
|
-
"
|
|
776
|
-
"
|
|
777
|
-
"
|
|
778
|
-
"
|
|
779
|
-
"
|
|
780
|
-
"
|
|
781
|
-
"
|
|
782
|
-
"
|
|
783
|
-
"
|
|
906
|
+
material_property_id = self.__edb_definition.MaterialPropertyId
|
|
907
|
+
property_name_to_id = {
|
|
908
|
+
"Permittivity": material_property_id.Permittivity,
|
|
909
|
+
"Permeability": material_property_id.Permeability,
|
|
910
|
+
"Conductivity": material_property_id.Conductivity,
|
|
911
|
+
"DielectricLossTangent": material_property_id.DielectricLossTangent,
|
|
912
|
+
"MagneticLossTangent": material_property_id.MagneticLossTangent,
|
|
913
|
+
"ThermalConductivity": material_property_id.ThermalConductivity,
|
|
914
|
+
"MassDensity": material_property_id.MassDensity,
|
|
915
|
+
"SpecificHeat": material_property_id.SpecificHeat,
|
|
916
|
+
"YoungsModulus": material_property_id.YoungsModulus,
|
|
917
|
+
"PoissonsRatio": material_property_id.PoissonsRatio,
|
|
918
|
+
"ThermalExpansionCoefficient": material_property_id.ThermalExpansionCoefficient,
|
|
919
|
+
"InvalidProperty": material_property_id.InvalidProperty,
|
|
784
920
|
}
|
|
785
921
|
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
Parameters
|
|
798
|
-
----------
|
|
799
|
-
material_name : str
|
|
800
|
-
Name of the existing material.
|
|
801
|
-
property_name : str
|
|
802
|
-
Name of the material property.
|
|
803
|
-
``permittivity``
|
|
804
|
-
``permeability``
|
|
805
|
-
``conductivity``
|
|
806
|
-
``dielectric_loss_tangent``
|
|
807
|
-
``magnetic_loss_tangent``
|
|
808
|
-
|
|
809
|
-
Returns
|
|
810
|
-
-------
|
|
811
|
-
float
|
|
812
|
-
The float value of the property.
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
Examples
|
|
816
|
-
--------
|
|
817
|
-
>>> from pyedb import Edb
|
|
818
|
-
>>> edb_app = Edb()
|
|
819
|
-
>>> returned_tuple = edb_app.materials.get_property_by_material_name("conductivity", "copper")
|
|
820
|
-
>>> edb_value = returned_tuple[0]
|
|
821
|
-
>>> float_value = returned_tuple[1]
|
|
822
|
-
|
|
823
|
-
"""
|
|
824
|
-
if self._edb.definition.MaterialDef.FindByName(self._pedb._db, material_name).IsNull():
|
|
825
|
-
self._pedb.logger.error("This material doesn't exists.")
|
|
922
|
+
if property_name == "loss_tangent":
|
|
923
|
+
warnings.warn(
|
|
924
|
+
"This key is deprecated in versions >0.7.0 and will soon be removed. "
|
|
925
|
+
"Use key dielectric_loss_tangent instead.",
|
|
926
|
+
DeprecationWarning,
|
|
927
|
+
)
|
|
928
|
+
property_name = "dielectric_loss_tangent"
|
|
929
|
+
match = difflib.get_close_matches(property_name, property_name_to_id, 1, 0.7)
|
|
930
|
+
if match:
|
|
931
|
+
return property_name_to_id[match[0]]
|
|
826
932
|
else:
|
|
827
|
-
|
|
828
|
-
if is_ironpython: # pragma: no cover
|
|
829
|
-
property_box = _clr.StrongBox[float]()
|
|
830
|
-
original_material.GetProperty(self.material_name_to_id(property_name), property_box)
|
|
831
|
-
return float(property_box)
|
|
832
|
-
else:
|
|
833
|
-
_, property_box = original_material.GetProperty(
|
|
834
|
-
self.material_name_to_id(property_name), self._edb_value(0.0)
|
|
835
|
-
)
|
|
836
|
-
if isinstance(property_box, float):
|
|
837
|
-
return property_box
|
|
838
|
-
else:
|
|
839
|
-
return property_box.ToDouble()
|
|
840
|
-
return False
|
|
933
|
+
return property_name_to_id["InvalidProperty"]
|
|
841
934
|
|
|
842
935
|
@pyedb_function_handler()
|
|
843
936
|
def load_amat(self, amat_file):
|
|
@@ -853,24 +946,24 @@ class Materials(object):
|
|
|
853
946
|
bool
|
|
854
947
|
"""
|
|
855
948
|
if not os.path.exists(amat_file):
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
for material_name,
|
|
859
|
-
if not material_name in
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
"
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
949
|
+
raise FileNotFoundError(f"File path {amat_file} does not exist.")
|
|
950
|
+
materials_dict = self.read_materials(amat_file)
|
|
951
|
+
for material_name, material_properties in materials_dict.items():
|
|
952
|
+
if not material_name in self:
|
|
953
|
+
if "tangent_delta" in material_properties:
|
|
954
|
+
material_properties["dielectric_loss_tangent"] = material_properties["tangent_delta"]
|
|
955
|
+
del material_properties["tangent_delta"]
|
|
956
|
+
elif "loss_tangent" in material_properties:
|
|
957
|
+
warnings.warn(
|
|
958
|
+
"This key is deprecated in versions >0.7.0 and will soon be removed. "
|
|
959
|
+
"Use key dielectric_loss_tangent instead.",
|
|
960
|
+
DeprecationWarning,
|
|
961
|
+
)
|
|
962
|
+
material_properties["dielectric_loss_tangent"] = material_properties["loss_tangent"]
|
|
963
|
+
del material_properties["loss_tangent"]
|
|
964
|
+
self.add_material(material_name, **material_properties)
|
|
965
|
+
else:
|
|
966
|
+
self.__edb.logger.warning(f"Material {material_name} already exist and was not loaded from AMAT file.")
|
|
874
967
|
return True
|
|
875
968
|
|
|
876
969
|
@staticmethod
|
|
@@ -886,11 +979,12 @@ class Materials(object):
|
|
|
886
979
|
Returns
|
|
887
980
|
-------
|
|
888
981
|
dict
|
|
889
|
-
{material name: dict of material
|
|
982
|
+
{material name: dict of material properties}.
|
|
890
983
|
"""
|
|
891
984
|
|
|
892
985
|
def get_line_float_value(line):
|
|
893
986
|
"""Retrieve the float value expected in the line of an AMAT file.
|
|
987
|
+
|
|
894
988
|
The associated string is expected to follow one of the following cases:
|
|
895
989
|
- simple('permittivity', 12.)
|
|
896
990
|
- permittivity='12'.
|
|
@@ -903,7 +997,7 @@ class Materials(object):
|
|
|
903
997
|
res = {}
|
|
904
998
|
_begin_search = re.compile(r"^\$begin '(.+)'")
|
|
905
999
|
_end_search = re.compile(r"^\$end '(.+)'")
|
|
906
|
-
|
|
1000
|
+
material_properties = [
|
|
907
1001
|
"thermal_conductivity",
|
|
908
1002
|
"permittivity",
|
|
909
1003
|
"dielectric_loss_tangent",
|
|
@@ -913,48 +1007,50 @@ class Materials(object):
|
|
|
913
1007
|
"specific_heat",
|
|
914
1008
|
"mass_density",
|
|
915
1009
|
]
|
|
916
|
-
keys = [
|
|
917
|
-
"thermal_conductivity",
|
|
918
|
-
"permittivity",
|
|
919
|
-
"tangent_delta",
|
|
920
|
-
"permeability",
|
|
921
|
-
"magnetic_loss_tangent",
|
|
922
|
-
"thermal_expansion_coeffcient",
|
|
923
|
-
"specific_heat",
|
|
924
|
-
"mass_density",
|
|
925
|
-
]
|
|
926
1010
|
|
|
927
1011
|
with open(amat_file, "r") as amat_fh:
|
|
928
1012
|
raw_lines = amat_fh.read().splitlines()
|
|
929
|
-
|
|
1013
|
+
material_name = ""
|
|
930
1014
|
for line in raw_lines:
|
|
931
1015
|
b = _begin_search.search(line)
|
|
932
1016
|
if b: # walk down a level
|
|
933
|
-
|
|
934
|
-
res.setdefault(
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
1017
|
+
material_name = b.group(1)
|
|
1018
|
+
res.setdefault(material_name, {})
|
|
1019
|
+
if len(res) > 165:
|
|
1020
|
+
pass
|
|
1021
|
+
if material_name:
|
|
1022
|
+
for material_property in material_properties:
|
|
1023
|
+
if material_property in line:
|
|
938
1024
|
value = get_line_float_value(line)
|
|
939
1025
|
if value is not None:
|
|
940
|
-
res[
|
|
1026
|
+
res[material_name][material_property] = value
|
|
1027
|
+
break
|
|
941
1028
|
# Extra case to avoid confusion ("conductivity" is included in "thermal_conductivity")
|
|
942
1029
|
if "conductivity" in line and "thermal_conductivity" not in line:
|
|
943
1030
|
value = get_line_float_value(line)
|
|
944
1031
|
if value is not None:
|
|
945
|
-
res[
|
|
1032
|
+
res[material_name]["conductivity"] = value
|
|
1033
|
+
# Extra case to avoid confusion ("conductivity" is included in "thermal_conductivity")
|
|
1034
|
+
if (
|
|
1035
|
+
"loss_tangent" in line
|
|
1036
|
+
and "dielectric_loss_tangent" not in line
|
|
1037
|
+
and "magnetic_loss_tangent" not in line
|
|
1038
|
+
):
|
|
1039
|
+
warnings.warn(
|
|
1040
|
+
"This key is deprecated in versions >0.7.0 and will soon be removed. "
|
|
1041
|
+
"Use key dielectric_loss_tangent instead.",
|
|
1042
|
+
DeprecationWarning,
|
|
1043
|
+
)
|
|
1044
|
+
value = get_line_float_value(line)
|
|
1045
|
+
if value is not None:
|
|
1046
|
+
res[material_name]["dielectric_loss_tangent"] = value
|
|
946
1047
|
end = _end_search.search(line)
|
|
947
1048
|
if end:
|
|
948
|
-
|
|
1049
|
+
material_name = ""
|
|
949
1050
|
|
|
950
1051
|
# Clean unwanted data
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
pass
|
|
955
|
-
try:
|
|
956
|
-
del res["$base_index$"]
|
|
957
|
-
except KeyError:
|
|
958
|
-
pass
|
|
1052
|
+
for key in ("$index$", "$base_index$"):
|
|
1053
|
+
if key in res:
|
|
1054
|
+
del res[key]
|
|
959
1055
|
|
|
960
1056
|
return res
|