SolidWorks Simulation API - AddForce3

J’ai un cylindre et j’ai créé une face circulaire à l’aide d’un outil de chaîne. Je veux simuler le cylindre pour le déplacement et dans cette étape, je veux appliquer une force sur la face circulaire que j’ai sélectionnée. Je veux appliquer une force uniforme dans la direction Z du système de coordonnées d’environ 400N. Lorsque j’exécute ce code, j’ai obtenu le code d’erreur 6 pour l’AddForce3. Quelqu’un pourrait-il m’aider s’il vous plaît ? Je l’ai fait en C#. J’essaie d’abord avec un visage et une force. Je le ferai avec plusieurs visages et force quand cela fonctionnera. J’ai donné l’image du cylindre ci-dessous.

using SldWorks;
using SolidWorks.Interop.cosworks;
using SolidWorks.Interop.sldworks;
using SolidWorks.Interop.swconst;
using System;
using System.IO;
using System.Threading;
using ISldWorks = SolidWorks.Interop.sldworks.ISldWorks;
using ModelDoc2 = SolidWorks.Interop.sldworks.ModelDoc2;
using SelectionMgr = SolidWorks.Interop.sldworks.SelectionMgr;

class Program
{
    static void Main()
    {
        Console.WriteLine("Starting SolidWorks...");
        var swApp = Activator.CreateInstance(Type.GetTypeFromProgID("SldWorks.Application")) as ISldWorks;
        if (swApp == null)
        {
            Console.WriteLine("Failed to start SolidWorks.");
            return;
        }

        swApp.Visible = true;
        Console.WriteLine("SolidWorks launched.");
        Thread.Sleep(5000);

        string partFilePath = @"C:\Users\Student\Tasks\API Tasks\L1_4 Task07.SLDPRT";
        if (!System.IO.File.Exists(partFilePath))
        {
            Console.WriteLine("File not found: " + partFilePath);
            return;
        }

        int errors = 0, warnings = 0;
        ModelDoc2 model = swApp.OpenDoc6(partFilePath,
                                         (int)swDocumentTypes_e.swDocPART,
                                         (int)swOpenDocOptions_e.swOpenDocOptions_Silent,
                                         "", ref errors, ref warnings);

        if (model == null)
        {
            Console.WriteLine("Failed to open part file.");
            return;
        }

        Console.WriteLine("Part file opened.");

        Thread.Sleep(2500);

        string simDllPath = @"C:\Program Files\SOLIDWORKS Corp\SOLIDWORKS\Simulation\cosworks.dll";
        int loadResult = swApp.LoadAddIn(simDllPath);
        Console.WriteLine($"Simulation Add-in load result: {loadResult}");

        var simAddIn = swApp.GetAddInObject("CosmosWorks.CosmosWorks") as CwAddincallback;
        if (simAddIn == null)
        {
            Console.WriteLine("Failed to load Simulation Add-in object.");
            return;
        }
            
        CosmosWorks cosmos = simAddIn.CosmosWorks;
        CWModelDoc simDoc = cosmos?.ActiveDoc;
        if (simDoc == null)
        {
            Console.WriteLine("Simulation document not active.");
            return;
        }

        Thread.Sleep(1500);

        ICWStudyManager studyMgr = simDoc.StudyManager;
        studyMgr.ActiveStudy = 0;
        CWStudy study = studyMgr.GetStudy(0);
        if (study == null)
        {
            Console.WriteLine("No study found.");
            return;
        }

        Thread.Sleep(1500);

        // ==================== APPLY FORCE LOAD ====================
        Console.WriteLine("Applying force load...");

        // Get ModelDocExtension for face selection
        object selFace = null;
        
        SelectionMgr swSelMgr = model.SelectionManager;

        model.Extension.SelectByID2("", "FACE", 4.848210781, -0.473088237, 1.944270691, false, 0, null, 0);
        selFace = (object)swSelMgr.GetSelectedObject6(1, -1);

        if (selFace == null)
        {
            Console.WriteLine("Failed to select face. Check face name.");
        }
        else
        {
            // Get Loads and Fixtures manager
            ICWLoadsAndRestraintsManager loadMgr = study.LoadsAndRestraintsManager;

            if (loadMgr == null)
            {
                Console.WriteLine("Failed to get Loads/Fixtures manager.");
            }
            else
            {
                int loadErr = 0;

                double[] data = new double[6];
                // Create the force
                data[0] = 1.0;
                data[1] = 1.0;
                data[2] = 1.0;
                data[3] = 1.0;
                data[4] = 1.0;
                data[5] = 1.0;

                object[] forceArray = { data[0], data[1], data[2], data[3], data[4], data[5] };

                CWForce force = loadMgr.AddForce3(
                    (int)swsForceType_e.swsForceTypeNormal,        // Load type: force
                    (int)swsSelectionType_e.swsSelectionFaceEdgeVertexPoint,     // Apply on faces
                    -1,                                             // No reference direction
                    0,                                              // Not table-driven
                    0,                                              // Not table-driven
                    0,                                              // No rows
                    new object[0],                                  // DistValue irrelevant
                    new object[0],                                  // ForceValue irrelevant
                    false,                                          // Uniform loading
                    false,                                          // Not a beam
                    0,                                              // No non-uniform def
                    0,                                              // No non-uniform type
                    4,                                              // Ucode: 0 = Normal
                    400.0,                                          // Force magnitude (N)
                    (forceArray),                                   // Comps array [Fx, Fy, Fz...]
                    false,                                          // FlipOrigin = false
                    false,                                          // Not curved beam
                    null,                                           // DispArray not used
                    selFace,                                        // RefGeom not used
                    false,                                          // PerUnitLength = false
                    out loadErr                                     // Error code
                );


                if (force == null || loadErr != 0)
                {
                    Console.WriteLine($"Failed to apply force. Error code: {loadErr}");
                }
                else
                {
                    Console.WriteLine("Force of 400 N in +Z applied successfully.");
                }
            }
        }

        Console.WriteLine("Done. Press any key to exit.");
        Console.ReadKey();
    }
}

Bonjour,
On voit dans la doc que :
If ForceType = swsForceType_e.swsForceTypeNormal Then Specify:

  • Comps with an array of six values: [1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
  • Ucode with 0
    Donc il faudrait essayer avec Ucode à 0 au lieu de 4.

Ensuite l’erreur indique un Invalid array. Ca peut être aussi le paramètre DispArray qui n’accepte pas de valeur nulle.

J’ai mis à jour le code comme ci-dessous. Maintenant, j’ai le code d’erreur 3.

        object selFace = null;
        object selBeam = null;

        SelectionMgr swSelMgr = model.SelectionManager;

        model.Extension.SelectByID2("", "SOLIDBODY", 1.83008089, 0.343248073, 1.970325039, false, 0, null, 0);
        selBeam = (object)swSelMgr.GetSelectedObject6(1, -1);

        model.Extension.SelectByID2("", "FACE", 4.848210781, -0.473088237, 1.944270691, false, 0, null, 0);
        selFace = (object)swSelMgr.GetSelectedObject6(1, -1);

        object[] beamArray = { selBeam };

        if (selFace == null)
        {
            Console.WriteLine("Failed to select face. Check face name.");
        }
        else
        {
            // Get Loads and Fixtures manager
            ICWLoadsAndRestraintsManager loadMgr = study.LoadsAndRestraintsManager;

            if (loadMgr == null)
            {
                Console.WriteLine("Failed to get Loads/Fixtures manager.");
            }
            else
            {
                int loadErr = 0;

                double[] data = new double[6];
                // Create the force
                data[0] = 1.0;
                data[1] = 1.0;
                data[2] = 1.0;
                data[3] = 1.0;
                data[4] = 1.0;
                data[5] = 1.0;

                object[] forceArray = { data[0], data[1], data[2], data[3], data[4], data[5] };
                

                CWForce force = loadMgr.AddForce3(
                    (int)swsForceType_e.swsForceTypeNormal,        // Load type: force
                    (int)swsSelectionType_e.swsSelectionFaceEdgeVertexPoint,     // Apply on faces
                    -1,                                             // No reference direction
                    0,                                              // Not table-driven
                    0,                                              // Not table-driven
                    0,                                              // No rows
                    new object[0],                                  // DistValue irrelevant
                    new object[0],                                  // ForceValue irrelevant
                    false,                                          // Uniform loading
                    false,                                          // Not a beam
                    0,                                              // No non-uniform def
                    0,                                              // No non-uniform type
                    0,                                              // Ucode: 0 = Normal
                    400.0,                                          // Force magnitude (N)
                    (forceArray),                                   // Comps array [Fx, Fy, Fz...]
                    false,                                          // FlipOrigin = false
                    false,                                          // Not curved beam
                    (beamArray),                                    // DispArray
                    selFace,                                        // RefGeom not used
                    false,                                          // PerUnitLength = false
                    out loadErr                                     // Error code
                );

@m_blt Pourriez-vous également m’aider à ce sujet ?

Bonsoir @Krishna_Prasanth_Thiruvalluvar ,

Le paramètre (beamArray) que vous passez à la fonction AddForce3 devrait être un tableau contenant des faces ou des arêtes d’un corps Solidworks.
Dans votre code, il s’agit du corps volumique lui-même et non des ses faces ou arêtes. Voir les instructions suivantes :

Dans votre cas, le plus simple pour créer des efforts suivant Z consiste à :

  • sélectionner une arête ou un axe de direction Z, ou une face de normale Z, et de l’affecter au paramètre ReferenceGeometry ;
  • sélectionner les faces supportant l’effort, et de les passer sous forme de tableau au paramètre (DispArray) ;
  • définir la valeur uCode comme combinaison additive de 1, 2 et 4, selon les composantes souhaitées. Pour la direction Z seule : uCode = 4;
  • définir les valeur des composantes et les passer dans le tableau (ComponentValues) (seules les trois premières sont nécessaires).

Syntaxe VBA:

Set force = loadMgr.AddForce3(swsForceTypeForceOrMoment, _
swsSelectionFaceEdgeVertexPoint, 0, 0, 0, 0, (DistanceValues), (ForceValues), _
False, False, 0, 0, 1 + 2 + 4, 0, (ComponentValues), False, False, (DispArray), _
ReferenceGeometry, False, loadErr)

Dois-je utiliser uniquement le selBeam ou utiliser à la fois selBeam et selFace pour sélectionner la face souhaitée pour appliquer la force normale ? Je me suis trompé dans la question initiale car je veux une force normale agissant sur n’importe quelle face du cylindre. Pourriez-vous m’aider sur la manière dont je devrais procéder ?

Comme il s’agit d’une force normale maintenant, UCode devrait être à 0. Qu’en est-il des autres paramètres ?

Bonjour,

La macro jointe, en VBA, crée un effort normal à chacune des faces préalablement sélectionnées sur un corps SW.
Pour que l’effort soit normal à chaque face, if faut :

  • que le type d’effort soit swsForceTypeNormal,
  • que uCode = 0
  • que la valeur de l’effort (123.0) soit passée dans le paramètre TorqueNFVal
  • et que ReferenceGeometry soit vide.

Sans commentaires et sans garantie… :wink:

AddForce.swp (60,5 Ko)

Stupéfiant! Merci beaucoup. J’ai modifié le code C# en fonction du VBA, puis j’ai appliqué la force dessus.

Ma prochaine tâche consiste à exporter le déplacement en un point précis. J’ai donc essayé d’utiliser la méthode GetDisplacementComponentForAllStepsAtNode et la méthode GetDisplacementAtPoints. Mais je n’ai pas pu obtenir le résultat escompté.

À l’aide de la méthode GetDisplacementComponentForAllStepsAtNode, j’ai trouvé le nœud le plus proche du point qui m’intéresse, puis j’ai transmis ce numéro de nœud à la méthode pour afficher la valeur de déplacement sur la console.

À l’aide de la méthode GetDisplacementAtPoints, j’ai directement saisi les coordonnées du nœud le plus proche du point qui m’intéresse, puis j’ai essayé de les afficher sur la console. Mais cela n’a pas fonctionné non plus. Comment puis-je rendre cela possible ? Je suis intéressé par l’exportation des valeurs de déplacement dans .csv fichier. J’ai donc voulu faire cette étape.

Le code ci-dessous est effectué après le maillage, puis l’exécution de la simulation. J’ai trouvé le déplacement maximum et minimum, puis le point où je veux mesurer le déplacement est maintenant mentionné directement dans le code. J’ai trouvé le nœud le plus proche et j’ai essayé les méthodes mentionnées ci-dessus. Le code donne le code d’erreur 4 lorsque j’utilise la première méthode

        // Create displacement plot
        CWResults results = study.Results;
        Thread.Sleep(2000);
        if (results == null)
        {
            Console.WriteLine("No results available.");
            return;
        }

        int errCode;
        CWPlot dispPlot = results.CreatePlot(
            (int)swsPlotResultTypes_e.swsResultDisplacementOrAmplitude,
            (int)swsDisplacementComponent_e.swsDisplacementComponentURES,
            (int)swsUnit_e.swsUnitSI,
            false,
            out errCode);

        if (dispPlot == null || errCode != 0)
        {
            Console.WriteLine($"Failed to create displacement plot. Error: {errCode}");
            return;
        }
                
        // Optional: Change units to millimeters
        errCode = dispPlot.SetComponentUnitAndValueByElem(
            (int)swsDisplacementComponent_e.swsDisplacementComponentURES,
            (int)swsLinearUnit_e.swsLinearUnitMillimeters,
            false);
        if (errCode != 0)
        {
            Console.WriteLine("Failed to set units for displacement plot.");
        }

        dispPlot = results.GetPlot("Displacement1", out errCode);

        // Activate plot
        errCode = dispPlot.ActivatePlot();
        if (errCode != 0)
        {
            Console.WriteLine("Failed to activate displacement plot.");
            return;
        }
        Thread.Sleep(1500);

        object[] dispResults = (object[])dispPlot.GetMinMaxResultValues(out errCode);
        if (errCode != 0 || dispResults == null || dispResults.Length < 4)
        {
            Console.WriteLine("Failed to get displacement results.");
            return;
        }

        double minDisp = Convert.ToDouble(dispResults[1]);
        double maxDisp = Convert.ToDouble(dispResults[3]);

        Console.WriteLine($"Resultant Displacement:\n  Min: {minDisp} mm\n  Max: {maxDisp} mm");

        Thread.Sleep(1500);

        // Step 1: Get all mesh nodes
        object[] nodesRaw = (object[])mesh.GetNodes();

        double[] targetPoint = new double[] { 4500, -280, 1980 }; // millimeters

        double minDistance = double.MaxValue;
        int closestNodeId = -1;
        double[] closestNodeCoords = new double[3];

        for (int i = 0; i < nodesRaw.Length; i += 4)
        {
            int nodeId = Convert.ToInt32(nodesRaw[i]);  // Node ID

            // Coordinates as floats, cast to double
            double x = Convert.ToDouble(nodesRaw[i + 1]) * 1000.0;
            double y = Convert.ToDouble(nodesRaw[i + 2]) * 1000.0;
            double z = Convert.ToDouble(nodesRaw[i + 3]) * 1000.0;

            double dx = x - targetPoint[0];
            double dy = y - targetPoint[1];
            double dz = z - targetPoint[2];
            double distance = Math.Sqrt(dx * dx + dy * dy + dz * dz);

            if (distance < minDistance)
            {
                minDistance = distance;
                closestNodeId = nodeId;
                closestNodeCoords[0] = x;
                closestNodeCoords[1] = y;
                closestNodeCoords[2] = z;
            }
        }

        Console.WriteLine("Closest node to target point:");
        Console.WriteLine($"Node ID: {closestNodeId}");
        Console.WriteLine($"Coordinates: X = {closestNodeCoords[0]}, Y = {closestNodeCoords[1]}, Z = {closestNodeCoords[2]}");
        Console.WriteLine($"Distance to target: {minDistance} mm");

        Thread.Sleep(2000);

        // Verify we have a valid node ID
        if (closestNodeId == -1)
        {
            Console.WriteLine("No valid node found near the target point.");
            return;
        }

        object dispValuesObj = results.GetDisplacementComponentForAllStepsAtNode(
            (int)swsDisplacementComponent_e.swsDisplacementComponentURES,
            80066,
            null,
            (int)swsLinearUnit_e.swsLinearUnitMillimeters,
            out int dispErrCode
        );

        Console.WriteLine("Raw dispValuesObj output:");

        // Check for errors first
        if (dispErrCode != 0)
        {
            Console.WriteLine($"Failed to get displacement. Error code: {dispErrCode}");
            return;
        }

        // Check if we got DBNull
        if (dispValuesObj == DBNull.Value)
        {
            Console.WriteLine("No displacement data available for this node.");
            return;
        }

        // Now try to cast to Array
        Array dispArray = null;
        try
        {
            dispArray = (Array)dispValuesObj;
        }
        catch (InvalidCastException)
        {
            Console.WriteLine("Invalid data type returned. Expected array.");
            return;
        }

        if (dispArray != null && dispArray.Length > 0)
        {
            for (int i = 0; i < dispArray.Length; i++)
            {
                object value = dispArray.GetValue(i);
                Console.WriteLine($"  Index {i}: {value}");
            }
            object firstValue = dispArray.GetValue(0);
            double dispAtPoint = Convert.ToDouble(firstValue);
            Console.WriteLine(
                $"Displacement at point ({closestNodeCoords[0]}, {closestNodeCoords[1]}, {closestNodeCoords[2]}): {dispAtPoint} mm"
            );
        }
        else
        {
            Console.WriteLine("No displacement values returned (array was null or empty).");
        }

Bonsoir,

Le problème de la méthode GetDisplacementComponentForAllStepsAtNode est sans doute lié au fait que l’étude est statique.

Pour le nœud transmis par le paramètre NNodeNum, cette fonction est destinée à renvoyer les valeurs du déplacement, pour les pas de calcul successifs effectués par le solveur.
Dans le cas d’une étude statique, il n’y a qu’un seul pas calculé correspondant à l’état final sollicité, et la fonction échoue avec le code erreur 4.
L’animation dans les résultats est une simple interpolation entre l’état initial non sollicité et l’état final sollicité.

Si vous effectuez une étude non linéaire, le solveur réalise le calcul par incréments successifs, chaque pas donnant lieu à des résultats, et la méthode GetDisplacementComponentForAllStepsAtNode fonctionne et renvoie le tableau des déplacements…

Bonne après-midi

Oh, c’est logique maintenant. Mais je veux faire une étude statique et obtenir le dispalecent dans le . Fichier CSV ? Puis-je utiliser la méthode GetDisplacementAtPoints ? Si oui, aidez-moi avec le code.