Can you try specifying the data type for each of the material property in the schema - specifically in the param material_props block. For Ex : “E1” : float, “E2” : float … etc
Based on the attached screenshot , i am not sure what the full error message is but it looks like the input material property is not a valid dictionary. Maybe it is missing the type for each of the material parameter.
It seems that no matter what I say in the comment, CompositesAI still misses material properties completely and gets the wrong list of Strings for “Plots” (must be exactly what I defined in my API). See the new code that I tried:
Perform a cylindrical bending laminate analysis and obtain generated figures and numerical probe results.
:param L: float. Required. Length of the laminate in meters.
Example: 4.0
:param h: float. Required. Thickness of the laminate in meters.
Example: 1.0
:param q0: float. Required. Applied transverse load in Pascals.
Example: 1_000_000
:param layer_angles: list[float]. Required. Fiber orientation angles (in degrees) from bottom to top for each laminate layer.
Example: [0, 45, -45, 90]
:param material_props: dict[str, float]. Required. Dictionary of material properties for orthotropic materials.
Must include exactly the following 9 keys with float values in SI units:
- "E1": float — Young’s modulus in x₁ direction (Pa)
- "E2": float — Young’s modulus in x₂ direction (Pa)
- "E3": float — Young’s modulus in x₃ direction (Pa)
- "G12": float — Shear modulus in x₁-x₂ plane (Pa)
- "G13": float — Shear modulus in x₁-x₃ plane (Pa)
- "G23": float — Shear modulus in x₂-x₃ plane (Pa)
- "nu12": float — Poisson’s ratio ν₁₂ (dimensionless)
- "nu13": float — Poisson’s ratio ν₁₃ (dimensionless)
- "nu23": float — Poisson’s ratio ν₂₃ (dimensionless)
Example:
{
"E1": 1.4e11,
"E2": 1.0e10,
"E3": 1.0e10,
"G12": 7.0e9,
"G13": 7.0e9,
"G23": 3.36e9,
"nu12": 0.3,
"nu13": 0.3,
"nu23": 0.49
}
:param disp_x1: list[float]. Required. x₁ coordinates for extracting displacement components [U, V, W].
Must lie within the laminate: 0 ≤ x₁ ≤ L.
Example: [0, 0, 2]
:param strain_x1: list[float]. Required. x₁ coordinates for extracting strain components [ε₁₁, ε₃₃, γ₂₃, γ₁₃, γ₁₂].
Must lie within the laminate: 0 ≤ x₁ ≤ L.
Example: [2, 2, 0, 0, 2]
:param stress_x1: list[float]. Required. x₁ coordinates for extracting stress components [σ₁₁, σ₂₂, σ₃₃, σ₂₃, σ₁₃, σ₁₂].
Must lie within the laminate: 0 ≤ x₁ ≤ L.
Example: [2, 2, 2, 0, 0, 2]
:param probe_x1: float. Optional. x₁ coordinate for probing a specific point.
Must satisfy: 0 ≤ x₁ ≤ L.
Required if "probe" is included in plots.
Example: 2.0
:param probe_x3: float. Optional. x₃ coordinate through the laminate thickness for probing.
Must satisfy: -h/2 ≤ x₃ ≤ h/2.
Required if "probe" is included in plots.
Example: 0.0
:param plots: list[str]. Required. List of output types to generate. Only the following exact strings are allowed:
- "2d_combined": Generate three 2D plots (displacements, strains, stresses) at specified x₁ locations.
- "2d_standalone": Generate separate 2D plots for each component at specified x₁ locations.
- "3d": Generate 3D plots where x₁ is x-axis, x₃ is y-axis, and value is z-axis.
- "probe": Return numerical values at a specific point (x₁, x₃).
Example:
["2d_combined", "probe"]
["2d_standalone"]
["3d"]
:return: dict. Dictionary containing URLs to generated plots and numerical results if probing is requested.
Have you played with OpenAI API endpoint directly? Currently, please make sure it works with API first. You can use API endpoint provided by CompositesAI
Sharing my Tools class for UDFRC homogenization for reference. I also pass the material properties explicitly in my function as these are like required keys - Maybe you could try once with this change to see if it works.
This seems like a good idea. Looks like CompositesAI cannot deal with a list. For non list inputs it doesn’t seem to have this issue. I’ll give it a try and see what happens.
@Haodong@Avinash thanks for the advice. The issue has been resolved. You can also test it and see if it works for you.
Examples:
1.
Can you perform cylindrical bending analysis with transversely isotropic material with E1=70GPa, E2 = 10 GPa, and G12 = 7 GPa, nu12=0.3, nu23=0.1? The height of the laminate is 0.1m and the length of the laminate is 0.4m (single layer), and load is 10^6 Pa. Provide the plots for displacements (all displacements plotted together, same for strains, and stresses), strains, and stresses (y axis) with thickness x3 as the x axis. Display the plots.
Can you perform cylindrical bending analysis with material properties E1=1.4e+11, E2=E3=1.0e+10, G12=G13=7.0e+09, G23=3.4e+09, nu12=nu13=0.30, nu23=0.49? The height of the laminate is 0.1m and the length of the laminate is 0.4m with layup [-30/30] and load is 10^6 Pa. Provide the plots for displacements (all displacements plotted together, same for strains, and stresses), strains, and stresses (y axis) with thickness x3 as the x axis. Display the plots.
You can also use your own customized laminate and see if this works for you. However, the plots may not always be displayed. You may need to explicitly ask AI to show the plots in the chat.
Regarding previous comment, it seems difficult to fix this at the moment
Because CompositesAI is struggling to get the correct list. So I changed the logic and specify single-value parameters instead of a list, which fixed the issue.
import requests
class Tools:
def __init__(self):
self.base_url = (
"https://composites-ai-tools-api-a88cb33feb62.herokuapp.com/api/v1/"
)
def cylindrical_bending_analysis(
self,
L: float,
h: float,
q0: float,
layer_angles: list,
material_type: str,
# isotropic
E: float = None,
nu: float = None,
# transversely isotropic
E1: float = None,
E2: float = None,
G12: float = None,
nu12: float = None,
nu23: float = None,
# orthotropic
E3: float = None,
nu13: float = None,
G13: float = None,
G23: float = None,
# output locations
disp_x1: list = None,
strain_x1: list = None,
stress_x1: list = None,
probe_x1: float = None,
probe_x3: float = None,
# plot booleans
plot_2d_combined: bool = False,
plot_2d_standalone: bool = False,
plot_3d: bool = False,
probe: bool = False,
) -> dict:
"""
Perform a cylindrical bending laminate analysis and obtain generated figures and numerical probe results.
:param L: float. Required. Length of the laminate in meters.
:param h: float. Required. Thickness of the laminate in meters.
:param q0: float. Required. Applied transverse load in Pascals.
:param layer_angles: list[float]. Required. Ply angles from bottom to top.
:param material_type: str. One of ["isotropic", "transversely_isotropic", "orthotropic"].
:param E, nu: float. For isotropic materials.
:param E1, E2, G12, nu12, nu23: float. For transversely isotropic materials.
:param E3, nu13, G13, G23: float. Additional engineering constants for orthotropic materials.
- "E1": float — Young’s modulus in x₁ direction (Pa)
- "E2": float — Young’s modulus in x₂ direction (Pa)
- "E3": float — Young’s modulus in x₃ direction (Pa)
- "G12": float — Shear modulus in x₁-x₂ plane (Pa)
- "G13": float — Shear modulus in x₁-x₃ plane (Pa)
- "G23": float — Shear modulus in x₂-x₃ plane (Pa)
- "nu12": float — Poisson’s ratio ν₁₂ (dimensionless)
- "nu13": float — Poisson’s ratio ν₁₃ (dimensionless)
- "nu23": float — Poisson’s ratio ν₂₃ (dimensionless)
:param disp_x1: list[float]. Locations to extract displacements.
:param strain_x1: list[float]. Locations to extract strains.
:param stress_x1: list[float]. Locations to extract stresses.
:param probe_x1: float. Required if probe is True.
:param probe_x3: float. Required if probe is True.
:param plot_2d_combined, plot_2d_standalone, plot_3d, probe: bool.
- "2d_combined": Generate three 2D plots (displacements, strains, stresses) at specified x₁ locations.
- "2d_standalone": Generate separate 2D plots for each component at specified x₁ locations.
- "3d": Generate 3D plots where x₁ is x-axis, x₃ is y-axis, and value is z-axis.
- "probe": Return numerical values at a specific point (x₁, x₃).
:return: dict. Contains URLs to generated plots and probe results if requested.
"""
# build material_props
if material_type == "isotropic":
G = E / (2 * (1 + nu))
material_props = {
"E1": E,
"E2": E,
"E3": E,
"G12": G,
"G13": G,
"G23": G,
"nu12": nu,
"nu13": nu,
"nu23": nu,
}
elif material_type == "transversely_isotropic":
G23 = E2 / (2 * (1 + nu23))
material_props = {
"E1": E1,
"E2": E2,
"E3": E2,
"G12": G12,
"G13": G12,
"G23": G23,
"nu12": nu12,
"nu13": nu12,
"nu23": nu23,
}
elif material_type == "orthotropic":
material_props = {
"E1": E1,
"E2": E2,
"E3": E3,
"G12": G12,
"G13": G13,
"G23": G23,
"nu12": nu12,
"nu13": nu13,
"nu23": nu23,
}
else:
raise ValueError(f"Unknown material_type '{material_type}'")
plots = []
if plot_2d_combined:
plots.append("2d_combined")
if plot_2d_standalone:
plots.append("2d_standalone")
if plot_3d:
plots.append("3d")
if probe:
plots.append("probe")
payload = {
"L": L,
"h": h,
"q0": q0,
"layer_angles": layer_angles,
"material_props": material_props,
"disp_x1": disp_x1,
"strain_x1": strain_x1,
"stress_x1": stress_x1,
"plots": plots,
}
if probe and probe_x1 is not None and probe_x3 is not None:
payload["probe_x1"] = probe_x1
payload["probe_x3"] = probe_x3
headers = {"Content-Type": "application/json"}
response = requests.post(self.base_url + "cylindrical-bending-analysis", json=payload, headers=headers)
try:
response.raise_for_status()
return response.json()
except Exception as e:
return {
"error": str(e),
"status_code": response.status_code,
"text": response.text,
}