App.getActiveProject().getGeometryAssembly().clear(); var freq = [83.33, 100.00, 116.67, 133.33, 150.00, 166.67, 183.34, 200.00, 216.67, 233.34, 250.00, 266.67, 283.34, 300.00, 316.67, 333.34, 350.00, 366.67, 383.34, 400.01, 416.67, 433.34, 450.01, 466.67, 483.34, 500.01, 516.68, 533.34, 550.01, 566.68, 583.34, 600.01, 616.68, 633.34, 650.01, 666.68, 683.35, 700.01, 716.68, 733.35, 750.01, 766.68, 783.35, 800.01, 816.68, 833.35, 850.02, 866.68, 883.35, 900.02, 916.68, 933.35, 950.02, 966.68, 983.35, 1000.00, 1016.70, 1033.40, 1050.00, 1066.70] CreatePEC(); var units = " cm"; num_ridges = 4; // either 2 or 4 // Make the walls and a ridge build_walls(10,1,30); // Note that to avoid overlap, we need x0 >= y0 x0=0.04001; // previously 0.04 y0=0.04; // previously 0.04 build_ridges(x0, y0, 0.0, 0.1, 0.06, 0.3, 0.26, 0.1, 0.1, 1); CreateAntennaSource(); CreateGrid(); CreateSensors(); CreateAntennaSimulationData(); QueueSimulation(); // Try making copies of the ridge var new_ridges = new EllipticalPattern(); Output.println(new_ridges.getInstances()); new_ridges.setInstances(7); //new_ridges.clone(); //Output.println(new_ridges); // Makes the outer walls of the horn antenna // S is the side length of the bottom of the wall // a is the coefficient for the linear function the walls extrude according to function build_walls(S,m,H) { // Make the edges to define the square var edge1 = Line( new Cartesian3D(-S + units,-S + units, 0), new Cartesian3D(-S + units, S + units, 0)); var edge2 = Line( new Cartesian3D(-S + units, S + units, 0), new Cartesian3D(S + units, S + units, 0)); var edge3 = Line( new Cartesian3D(S + units,S + units, 0), new Cartesian3D(S + units, -S + units, 0)); var edge4 = Line( new Cartesian3D(S + units,-S + units, 0), new Cartesian3D(-S + units, -S + units, 0)); // Declare sketches to be made from the edges var wallSegment = new Sketch(); var bottomSegment = new Sketch(); wallSegment.addEdge(edge1); wallSegment.addEdge(edge2); wallSegment.addEdge(edge3); wallSegment.addEdge(edge4); bottomSegment.addEdge(edge1); bottomSegment.addEdge(edge2); bottomSegment.addEdge(edge3); bottomSegment.addEdge(edge4); // Let's start by making the bottom var bottomCover = new Cover(bottomSegment); var bottomRecipe = new Recipe(); bottomRecipe.append( bottomCover ); var bottomModel = new Model(); bottomModel.setRecipe( bottomRecipe ); // Add the surface //var bottom = App.getActiveProject().getGeometryAssembly().append(bottomModel); //bottom.name = "Bottom square"; // Now we need to extrude the edges to get height var walls = new Extrude( wallSegment, H + units); // Makes an Extrude var wallOptions = walls.getOptions(); // Gives the possible options for // We will use the draft law option to extrude linearly wallOptions.draftOption = SweepOptions.DraftLaw; // allows for draftlaw wallOptions.draftLaw = "("+m+"*x)"; // Set the expression for the extrude wallOptions.draftOption = 4; // 4 indicates we use draftlaw //Walter - Change the gap type to Extended to get the desired shape wallOptions.gapType = SweepOptions.Extended; // I actually don't like this when we have x^2, but it doesn't do much for just x //Walter - Create a shell instead of a solid part wallOptions.createSolid = false; // This way the shape isn't filled in walls.setOptions ( wallOptions ); // Sets the settings we assigned above // Make a recipe for a model var wallRecipe = new Recipe(); wallRecipe.append(walls); var wallModel = new Model(); wallModel.setRecipe(wallRecipe); wallModel.name = "Outer Walls"; wallModel.getCoordinateSystem().translate(new Cartesian3D(0,0,0)); // Makes the model start at the origin // Set the material for these parts var wallProject = App.getActiveProject().getGeometryAssembly().append(wallModel); // Adds the model to the project var pecMaterial = App.getActiveProject().getMaterialList().getMaterial( "PEC" ); // Makes the material available App.getActiveProject().setMaterial( wallProject, pecMaterial ); // Sets the material //App.getActiveProject().setMaterial( bottom, pecMaterial ); // Sets the material } // A function to build the inner ridges // Here are the arguments, which are primarily used when making the LawEdges // Bottom x distance from center // Bottom y distance from center // Top x distance from center // Top y distance from center // Full x // Full y // Full height function build_ridges(x_0, y_0, z_0, x_f, y_f, z_f, tau, beta, S, m) { // build_ridges(0.04, 0.04, 0.0, 0.1, 0.06, 0.3, 0.26, 0.1, 0.1, 1); // Logarithmic slopes //var Log1 = new LawEdge( "0.04 + u", "0.04 + 0.02/0.26*u", "1/10*ln((exp(3)-1.0)/0.26*u+1.0)", 0, 0.26); // alpha = z_max/beta //var Log2 = new LawEdge( "0.04 + u", "-0.04 - 0.02/0.26*u", "1/10*ln((exp(3)-1.0)/0.26*u+1.0)", 0, 0.26); var Log1 = new LawEdge( ""+x_0+" + ("+z_f+"-"+x_0+")/"+tau+"*u", ""+y_0+" + ("+y_f+"-"+y_0+")/"+tau+"*u", ""+beta+"*ln((exp("+z_f+"/"+beta+")-1.0)/"+tau+"*u+1.0)", 0, tau); // alpha = z_max/beta var Log2 = new LawEdge( ""+x_0+" + ("+z_f+"-"+x_0+")/"+tau+"*u", "-"+y_0+" - ("+y_f+"-"+y_0+")/"+tau+"*u", ""+beta+"*ln((exp("+z_f+"/"+beta+")-1.0)/"+tau+"*u+1.0)", 0, tau); // Inner straight slopes var IS1 = new LawEdge( ""+x_0+" + ("+z_f+"-"+x_0+")/"+tau+"*u", ""+y_0+" + ("+y_f+"-"+y_0+")/"+tau+"*u", "("+z_f+"-"+z_0+")/"+tau+"*u", 0, tau); // a_0 + at, b_0 + bt, c_0 + ct var IS2 = new LawEdge( ""+x_0+" + ("+z_f+"-"+x_0+")/"+tau+"*u", "-"+y_0+" - ("+y_f+"-"+y_0+")/"+tau+"*u", "("+z_f+"-"+z_0+")/"+tau+"*u", 0, tau); // Bottom line var BL1 = new LawEdge(""+x_0+" + ("+x_f+"-"+x_0+")/"+tau+"*u", ""+y_0+"", ""+z_0+"", 0, tau); var BL2 = new LawEdge(""+x_0+" + ("+x_f+"-"+x_0+")/"+tau+"*u", "-"+y_0+"", ""+z_0+"", 0, tau); // Top line var TL1 = new LawEdge(""+z_f+" + "+x_f+"/"+tau+"*u", ""+y_f+"", ""+z_f+"", 0, tau); var TL2 = new LawEdge(""+z_f+" + "+x_f+"/"+tau+"*u", "-"+y_f+"", ""+z_f+"", 0, tau); // Outer Straight slopes var OS1 = new LawEdge( ""+x_f+" + "+z_f+"/"+tau+"*u", ""+y_0+" + ("+y_f+" - "+y_0+")/"+tau+"*u", ""+z_f+"/"+tau+"*u", 0, tau); var OS2 = new LawEdge( ""+x_f+" + "+z_f+"/"+tau+"*u", "-"+y_0+" - ("+y_f+" - "+y_0+")/"+tau+"*u", ""+z_f+"/"+tau+"*u", 0, tau); // Inner top line var ITL = new LawEdge( ""+z_f+"", "-"+y_f+" + 2*"+y_f+"/"+tau+"*u", ""+z_f+"", 0, tau); // Outer top line var OTL = new LawEdge( ""+x_f+" + "+z_f+"", "-"+y_f+" + 2*"+y_f+"/"+tau+"*u", ""+z_f+"", 0, tau); // Inner bottom line var IBL = new LawEdge( ""+x_0+"", "-"+y_0+" + 2*"+y_0+"/"+tau+"*u", ""+z_0+"", 0, tau); // Outer bottom line var OBL = new LawEdge( ""+x_f+"", "-"+y_0+" + 2*"+y_0+"/"+tau+"*u", ""+z_0+"", 0, tau); // Make the sketches var straightEdge1 = new Sketch(); // All straight edges (IS1, BL1, TL1, OS1) var straightEdge2 = new Sketch(); // All straight edges (IS2, BL2, TL2, OS2) var curvedLog1 = new Sketch(); // Logarithmic edge (IS1 and Log1) var curvedLog2 = new Sketch(); // Logarithmic edge (IS2 and Log2) var topRectangle = new Sketch(); // Top rectangle var bottomRectangle = new Sketch(); // Bottom rectangle // Add the edges to the sketches straightEdge1.addEdges( [IS1, BL1, TL1, OS1] ); // Inner straight slope curvedLog1.addEdges( [IS1, Log1] ); // Right logarithm part straightEdge2.addEdges( [IS2, BL2, TL2, OS2] ); // Inner straight slope curvedLog2.addEdges( [IS2, Log2] ); // Left logarithm part topRectangle.addEdges( [ITL, OTL, TL1, TL2] ); // Top rectangle bottomRectangle.addEdges( [IBL, OBL, BL1, BL2] ); // Bottom Rectangle //WALTER - The Elliptical pattern is added as a recipe to the parts //In this case the location of the center and direction of the normal are simple, but for more complex scenarios, may need to use mroe functionality to find them. var ePattern = new EllipticalPattern(); ePattern.setCenter(new CoordinateSystemPosition(0,0,0)); ePattern.setNormal(new CoordinateSystemDirection(0,0,1)); ePattern.setInstances(num_ridges); ePattern.setRotated(true); var cov = new Array(); cov.push(new Cover(straightEdge1)); cov.push(new Cover(straightEdge2)); cov.push(new Cover(curvedLog1)); cov.push(new Cover(curvedLog2)); cov.push(new Cover(topRectangle)); cov.push(new Cover(bottomRectangle)); var pecMaterial = App.getActiveProject().getMaterialList().getMaterial( "PEC" ); //WALTER - We can loop over all our parts and add them to the project as follows. You can use similar concepts above. models = new Assembly(); for(var w = 0; w < cov.length; w++) { var r = new Recipe(); r.append(cov[w]); r.append(ePattern); var m = new Model(); m.setRecipe(r); m.name = "Test Surface " + (w+1); //WALTER - Seperate array for the models, though we could just get them from the GemoetryAssembly again models.append(m); App.getActiveProject().setMaterial( m, pecMaterial ); } // Work on the loft var vertex_position1 = curvedLog1.getPosition(curvedLog1.getVertexIds()[0]); var vertex_position2 = curvedLog2.getPosition(curvedLog2.getVertexIds()[0]); var loft = new Loft(models.at(2).pickFace(new Cartesian3D (0, 0, 0), vertex_position1, 0.5), "0.0", models.at(3).pickFace(new Cartesian3D(0,0,0), vertex_position2, 0.5), "0.0"); loft.setPart1(models.at(2)); loft.setPart2(models.at(3)); var r12 = new Recipe(); r12.append( loft ); r12.append(ePattern); var m12 = new Model(); m12.setRecipe( r12 ); m12.name = "Loft 1"; models.append(m12); //WALTER - append the assembly to the project, then loop over it to assign the material var assembly = App.getActiveProject().getGeometryAssembly().append(models); for(x = 0; x < assembly.size(); x++) { Output.println(assembly.at(x)); App.getActiveProject().setMaterial( assembly.at(x), pecMaterial ); } } // CreatPEC Function function CreatePEC() //borrowed from XF demo { //Make the material. We will use PEC, or Perfect Electrical Conductor: var pec = new Material(); pec.name = "PEC"; var pecProperties = new PEC(); // This is the electric properties that defines PEC var pecMagneticFreespace = new MagneticFreespace(); // We could make a material that acts as PEC and PMC, but in this case we just care about electrical components. var pecPhysicalMaterial = new PhysicalMaterial(); pecPhysicalMaterial.setElectricProperties( pecProperties ); pecPhysicalMaterial.setMagneticProperties( pecMagneticFreespace ); pec.setDetails( pecPhysicalMaterial ); // PEC is historically a "white" material, so we can easily change its appearance: var pecBodyAppearance = pec.getAppearance(); var pecFaceAppearance = pecBodyAppearance.getFaceAppearance(); // The "face" appearance is the color/style associated with the surface of geometry objects pecFaceAppearance.setColor( new Color( 255, 255, 255, 255 ) ); // Set the surface color to white. (255 is the maximum intensity, these are in order R,G,B,A). // Check for an existing material if( null != App.getActiveProject().getMaterialList().getMaterial( pec.name ) ) { App.getActiveProject().getMaterialList().removeMaterial( pec.name ); } App.getActiveProject().getMaterialList().addMaterial( pec ); } function CreateAntennaSource() { // Here we will create our waveform, create our circuit component definition for the feed, and create // a CircuitComponent that will attach those to our current geometry. var waveformList = App.getActiveProject().getWaveformList(); // clear the waveform list waveformList.clear(); // Create a gaussian derivative input wave var waveform = new Waveform(); var GDer = new GaussianDerivativeWaveformShape (); GDer.pulseWidth = 2e-9; waveform.setWaveformShape( GDer ); waveform.name ="Gaussian Derivative"; var waveformInList = waveformList.addWaveform( waveform ); // Now to create the circuit component definition: var componentDefinitionList = App.getActiveProject().getCircuitComponentDefinitionList(); // clear the list componentDefinitionList.clear(); // Create our Feed var feed1 = new Feed(); var feed2 = new Feed(); feed1.feedType = Feed.Voltage; // Set its type enumeration to be Voltage. //feed2.feedType = Feed.Voltage; // Set its type enumeration to be Voltage. // Define a 50-ohm resistance for this feed var rlc = new RLCSpecification(); rlc.setResistance( "50 ohm" ); rlc.setCapacitance( "0" ); rlc.setInductance( "0" ); feed1.setImpedanceSpecification( rlc ); feed1.setWaveform( waveformInList ); // Make sure to use the reference that was returned by the list, or query the list directly feed1.name = "50-Ohm Voltage Source"; var feedInList = componentDefinitionList.addCircuitComponentDefinition( feed1 ); feed2.setImpedanceSpecification( rlc ); feed2.setWaveform( waveformInList ); // Make sure to use the reference that was returned by the list, or query the list directly feed2.name = "50-Ohm Voltage Source 2"; var feedInList = componentDefinitionList.addCircuitComponentDefinition( feed2 ); // Now create a circuit component that will be the feed point for our simulation var componentList = App.getActiveProject().getCircuitComponentList(); componentList.clear(); var component1 = new CircuitComponent(); var component2 = new CircuitComponent(); component1.name = "Source"; component2.name = "Source"; component1.setAsPort( true ); component2.setAsPort( true ); // Define the endpoints of this feed - these are defined in world position, but you can also attach them to edges, faces, etc. var coordinate1 = new CoordinateSystemPosition( -x0, 0, 0); var coordinate2 = new CoordinateSystemPosition( x0, 0, 0); var coordinate3 = new CoordinateSystemPosition( 0, -x0, 0); var coordinate4 = new CoordinateSystemPosition( 0, x0, 0); component1.setCircuitComponentDefinition( feed1 ); component1.setCircuitComponentDefinition( feed1 ); component1.setEndpoint1( coordinate1 ); component1.setEndpoint2( coordinate2 ); component2.setCircuitComponentDefinition( feed2 ); component2.setCircuitComponentDefinition( feed2 ); component2.setEndpoint1( coordinate3 ); component2.setEndpoint2( coordinate4 ); componentList.addCircuitComponent( component1 ); //componentList.addCircuitComponent( component2 ); } // Make the grid function CreateGrid() { // Set up the grid spacing for the antenna var grid = App.getActiveProject().getGrid(); var cellSizes = grid.getCellSizesSpecification(); cellSizes.setTargetSizes( Cartesian3D( 0.001, 0.001, 0.001) ); // And we need to set the Minimum Sizes - these are the minimum deltas that we will allow in this project. // We'll use the scalar ratio of 20% here. cellSizes.setMinimumSizes( Cartesian3D( ".1", ".1", ".1" ) ); cellSizes.setMinimumIsRatioX( true ); cellSizes.setMinimumIsRatioY( true ); cellSizes.setMinimumIsRatioZ( true ); grid.specifyPaddingExtent( Cartesian3D( "20", "20", "20" ), Cartesian3D( "20", "20", "20" ), true, true ); } // Make the sensors to detect the emitted signal function CreateSensors() { // Here we will create a sensor definition and attach it to a near-field sensor on the surface of one of our objects. var sensorDataDefinitionList = App.getActiveProject().getSensorDataDefinitionList(); sensorDataDefinitionList.clear(); // Create a sensor var farSensor = new FarZoneSensor(); farSensor.retrieveSteadyStateData = true; farSensor.setAngle1IncrementRadians(Math.PI/36.0); farSensor.setAngle2IncrementRadians(Math.PI/36.0); farSensor.name = "Far Zone Sensor"; var FarZoneSensorList = App.getActiveProject().getFarZoneSensorList(); FarZoneSensorList.clear(); FarZoneSensorList.addFarZoneSensor( farSensor ); } function CreateAntennaSimulationData() { // This function modifies the NewSimulationData parameters of the project. // They're called "New" because they get applied every time we create an instance of this // project and place it on our simulation queue. var simData = App.getActiveProject().getNewSimulationData(); var FOI = simData.getFOIParameters(); FOI.clearAllSpecifiedFrequencies(); FOI.foiSource = 1; for(var k = 0;k < 60;k++) { FOI.addSpecifiedFrequency(freq[k] + " MHz"); } // These should already be set, however just to make sure the current project is set up correctly simData.excitationType = NewSimulationData.DiscreteSources; simData.enableSParameters = true; } function QueueSimulation() { // Create and start the simulation. Project must be saved in order to run. var simulation = App.getActiveProject().createSimulation( false ); Output.println( "Successfully created the simulation." ); var projectId = simulation.getProjectId(); var simulationId = simulation.getSimulationId(); var numRuns = simulation.getRunCount(); }