public void Vector()
        {
            Vector3D v0 = new Vector3D();
            Vector3D v1 = new Vector3D(0.0, 1.0, 2.0);
            Vector3D v2 = new Vector3D(0.0, 1.0, 2.0);
            Vector3D v3 = new Vector3D(1.0, 1.0, 1.0);

            // Basic equivalence
            Assert.Equal(v1, v2);
            Assert.NotEqual(v1, v3);

            // Addition
            Assert.Equal(v1, v1 + v0);
            Assert.Equal(v1, v1 - v0);

            // Constant multiplication
            Assert.Equal(2 * v3, new Vector3D(2.0, 2.0, 2.0));
            Assert.Equal(2 * v1, v1 + v1);

            // Length
            Vector3D a = new Vector3D(1.0, 1.0, 0.0);
            Assert.Equal(Math.Sqrt(2.0), a.Length);
            Assert.Equal(Math.Sqrt(3.0), v3.Length);

            // Rotation
            Vector3D vo = new Vector3D(1.0, 0.0, 0.0);
            Vector3D ve = new Vector3D(0.0, 1.0, 0.0);
            Assert.True((ve - Vector3D.RotateZ(vo, Math.PI / 2)).x < eps);
            Assert.True((ve - Vector3D.RotateZ(vo, Math.PI / 2)).y < eps);
            Assert.True((ve - Vector3D.RotateZ(vo, Math.PI / 2)).z < eps);
        }
 public ExcitationField(string name, EType type, Vector3D ev)
     : base(name)
 {
     m_type = type;
     m_vector = ev;
 }
        public void Transform()
        {
            // TScale
            Vector3D vi = new Vector3D(1, 1, 1);
            TScale s = new TScale(1, 1, 2);
            Vector3D vo = s * vi;
            
            Assert.True(AlmostEqual(vi.x * s.x, vo.x));
            Assert.True(AlmostEqual(vi.y * s.y, vo.y));
            Assert.True(AlmostEqual(vi.z * s.z, vo.z));

            // TTranslate
            TTranslate t1 = new TTranslate(1, 0, 1);
            vo = t1 * vi;
            Assert.True(AlmostEqual(vi.x + t1.x, vo.x));

            TTranslate t2 = new TTranslate(vi);
            vo = t2 * vi;
            Assert.True(AlmostEqual(2 * vi.x, vo.x));
            Assert.True(AlmostEqual(2 * vi.y, vo.y));
            Assert.True(AlmostEqual(2 * vi.z, vo.z));

            // Rotate origin
            vi = new Vector3D(1, 0, 0);
            TRotateOrigin ro = new TRotateOrigin(0, 0, 1, Math.PI);
            vo = ro * vi;
            Assert.True(AlmostEqual(-vi.x, vo.x));
            ro = new TRotateOrigin(0, 1, 0, Math.PI);
            vo = ro * vi;
            Assert.True(AlmostEqual(-vi.x, vo.x));
            ro = new TRotateOrigin(1, 0, 0, Math.PI/2);
            vo = ro * vi;
            Assert.True(AlmostEqual(vi.x, vo.x));
            ro = new TRotateOrigin(1, 0, 1, Math.PI);
            vo = ro * vi;
            Assert.True(AlmostEqual(vi.x, vo.z));

            // Rotate X
            vi = new Vector3D(1, 1, 0);
            TRotateX rx = new TRotateX(Math.PI / 2);
            vo = rx * vi;
            Assert.True(AlmostEqual(vi.x, vo.x));
            Assert.True(AlmostEqual(vi.y, vo.z));

            // Rotate Y
            vi = new Vector3D(1, 0, 0);
            TRotateY ry = new TRotateY(Math.PI);
            vo = ry * vi;
            Assert.True(AlmostEqual(vi.x, -vo.x));

            // Rotate Z
            vi = new Vector3D(1, 1, 1);
            TRotateZ rz = new TRotateZ(Math.PI);
            vo = rz * vi;
            Assert.True(AlmostEqual(vi.x, -vo.x));
            Assert.True(AlmostEqual(vi.y, -vo.y));
        }
 /// <summary>
 /// Adds the coordinates of a vector to the lines of the grid.
 /// </summary>
 /// <param name="v">The vector containing the coordinates to be added to the grid lines.</param>
 public void Add(Vector3D v)
 {
     XLines.Add(v.x);
     YLines.Add(v.y);
     ZLines.Add(v.z);
     XLines = XLines.Distinct().ToList();
     YLines = YLines.Distinct().ToList();
     ZLines = ZLines.Distinct().ToList();
 }
        public void Cylinder_ExportToXmlAndParse_MatchesOriginal()
        {
            var v1 = new Vector3D(0.0, 0.0, 0.0);
            var v2 = new Vector3D(5.0, 0.0, 0.0);
            double radius = 2.0;
            Cylinder refCylinder = new Cylinder(null, null, 0, v1, v2, radius);

            XElement xmlCylinder = refCylinder.ToXElement();
            Cylinder dutCylinder = (Cylinder)Primitive.FromXElement(xmlCylinder, null);

            Assert.Equal(v1, dutCylinder.P1);
            Assert.Equal(v2, dutCylinder.P2);
            Assert.Equal(radius, dutCylinder.Radius);
        }
        public NF2FFBox(string name, Vector3D p1, Vector3D p2, double or = Double.NaN)
            : base(name)
        {
            // E-field
            Dump.EDumpMode dm = Dump.EDumpMode.NODE_INTERPOLATION;
            Dump.EDumpType dumpType = Dump.EDumpType.E_FIELD_TIME_DOMAIN;
            Dump.EFileType ft = Dump.EFileType.HDF5_FILE;
            m_primitives.Add(new Box(this, new Dump("nf2ff_E_xn", dm, dumpType, ft, optResolution: or), 0,
                new Vector3D(p1.x, p1.y, p1.z), new Vector3D(p1.x, p2.y, p2.z)));
            m_primitives.Add(new Box(this, new Dump("nf2ff_E_xp", dm, dumpType, ft, optResolution: or), 0,
                new Vector3D(p2.x, p1.y, p1.z), new Vector3D(p2.x, p2.y, p2.z)));
            m_primitives.Add(new Box(this, new Dump("nf2ff_E_yn", dm, dumpType, ft, optResolution: or), 0,
                new Vector3D(p1.x, p1.y, p1.z), new Vector3D(p2.x, p1.y, p2.z)));
            m_primitives.Add(new Box(this, new Dump("nf2ff_E_yp", dm, dumpType, ft, optResolution: or), 0,
                new Vector3D(p1.x, p2.y, p1.z), new Vector3D(p2.x, p2.y, p2.z)));
            m_primitives.Add(new Box(this, new Dump("nf2ff_E_zn", dm, dumpType, ft, optResolution: or), 0,
                new Vector3D(p1.x, p1.y, p1.z), new Vector3D(p2.x, p2.y, p1.z)));
            m_primitives.Add(new Box(this, new Dump("nf2ff_E_zp", dm, dumpType, ft, optResolution: or), 0,
                new Vector3D(p1.x, p1.y, p2.z), new Vector3D(p2.x, p2.y, p2.z)));

            // H-field
            dumpType = Dump.EDumpType.H_FIELD_TIME_DOMAIN;
            m_primitives.Add(new Box(this, new Dump("nf2ff_H_xn", dm, dumpType, ft, optResolution: or), 0,
                new Vector3D(p1.x, p1.y, p1.z), new Vector3D(p1.x, p2.y, p2.z)));
            m_primitives.Add(new Box(this, new Dump("nf2ff_H_xp", dm, dumpType, ft, optResolution: or), 0,
                new Vector3D(p2.x, p1.y, p1.z), new Vector3D(p2.x, p2.y, p2.z)));
            m_primitives.Add(new Box(this, new Dump("nf2ff_H_yn", dm, dumpType, ft, optResolution: or), 0,
                new Vector3D(p1.x, p1.y, p1.z), new Vector3D(p2.x, p1.y, p2.z)));
            m_primitives.Add(new Box(this, new Dump("nf2ff_H_yp", dm, dumpType, ft, optResolution: or), 0,
                new Vector3D(p1.x, p2.y, p1.z), new Vector3D(p2.x, p2.y, p2.z)));
            m_primitives.Add(new Box(this, new Dump("nf2ff_H_zn", dm, dumpType, ft, optResolution: or), 0,
                new Vector3D(p1.x, p1.y, p1.z), new Vector3D(p2.x, p2.y, p1.z)));
            m_primitives.Add(new Box(this, new Dump("nf2ff_H_zp", dm, dumpType, ft, optResolution: or), 0,
                new Vector3D(p1.x, p1.y, p2.z), new Vector3D(p2.x, p2.y, p2.z)));
        }
 public SARBox(string name, List<double> fs, Vector3D p1, Vector3D p2)
     : base(name + "-box")
 {
     Dump d = new Dump(name,
         Dump.EDumpMode.CELL_INTERPOLATION,
         Dump.EDumpType.ONE_GRAM_AVG_SAR_FREQ_DOMAIN,
         Dump.EFileType.HDF5_FILE, fs);
     m_primitives.Add(new Box(this, d, 0, p1, p2));
 }
        public static Vector3D RotateZ(Vector3D v, double a)
        {
            double x = Math.Cos(a) * v.x - Math.Sin(a) * v.y;
            double y = Math.Sin(a) * v.x + Math.Cos(a) * v.y;

            return new Vector3D(x, y, v.z);
        }
 public static Vector3D RotateXYZ(Vector3D p, Vector3D e, double a)
 {
     throw new NotImplementedException();
 }
        public static Vector3D RotateX(Vector3D v, double a)
        {
            double y = Math.Cos(a) * v.y - Math.Sin(a) * v.z;
            double z = Math.Sin(a) * v.y + Math.Cos(a) * v.z;

            return new Vector3D(v.x, y, z);
        }
        public static Vector3D RotateY(Vector3D v, double a)
        {
            double x =  Math.Cos(a) * v.x + Math.Sin(a) * v.z;
            double z = -Math.Sin(a) * v.x + Math.Cos(a) * v.z;

            return new Vector3D(x, v.y, z);
        }
        public bool Equals(Vector3D v)
        {
            if ((object)v == null)
            {
                return false;
            }

            return base.Equals((Vector2D)v) && this.z == v.z;
        }
        public void GenerateSarSimulationInput(string outputDirectory)
        {
            Compound simulationSpace = new Compound("space");
            Compound solidSpace = new Compound("solid-space");
            simulationSpace.Add(solidSpace);
            solidSpace.Add(endo);

            var headPhantom = new CSXCAD.Ara.HeadPhantom();
            headPhantom.Transformations.Add(new TRotateX(Math.PI / 2));
            headPhantom.Transformations.Add(new TTranslate(32.0, 80.0, -headPhantom.Width / 2 - 7.0)); // TODO: Make endo width/height accessibles
            solidSpace.Add(headPhantom);

            double airBox = 40;
            double envResolution = Math.Round(lambdaMin / 20 / unit);
            double maxRatio = 1.5;

            RectilinearGrid grid = new BoundingGrid_6x3();

            Vector3D dutPosition = new Vector3D(
                antenna.AbsoluteTransformation.X,
                antenna.AbsoluteTransformation.Y,
                antenna.AbsoluteTransformation.Z);

            solidSpace.Transformations.Add(new TTranslate(-dutPosition));

            grid.Move(-dutPosition);
            grid.Add(new Vector3D(0, 0, 0));
            grid.ZLines.Add(-(antenna.Parent as CSXCAD.Ara.PCB).Thickness);
            grid.Sort();
            grid.SmoothMesh(dutResolution, maxRatio);

            grid.Add(headPhantom.BoundingBox.P1);
            grid.Add(headPhantom.BoundingBox.P2);
            grid.SmoothMesh(sarResolution, maxRatio);

            grid.AddAirbox(airBox);
            grid.SmoothMesh(envResolution, maxRatio);

            simulationSpace.Add(new SARBox("SAR", frequency,
                new Vector3D(headPhantom.XGridPoints.First(), headPhantom.YGridPoints.First(), headPhantom.ZGridPoints.First()),
                new Vector3D(headPhantom.XGridPoints.Last(), headPhantom.YGridPoints.Last(), headPhantom.ZGridPoints.Last())));
            simulationSpace.Add(new NF2FFBox("nf2ff",
                new Vector3D(grid.XLines.First(), grid.YLines.First(), grid.ZLines.First()),
                new Vector3D(grid.XLines.Last(), grid.YLines.Last(), grid.ZLines.Last()),
                lambdaMin / 15 / unit));

            grid.AddPML(8);

            Simulation fdtd = new Simulation();
            fdtd.Excitation = new GaussExcitation(frequency, bandwidth);

            // Export
            XDocument doc = new XDocument(
                new XDeclaration("1.0", "utf-8", "yes"),
                new XComment("CyPhy generated openEMS simulation file"),
                new XElement("openEMS",
                    fdtd.ToXElement(),
                    new XElement("ContinuousStructure",
                        new XAttribute("CoordSystem", 0),
                        simulationSpace.ToXElement(),
                        grid.ToXElement()
                    )
                )
            );

            System.IO.Directory.CreateDirectory(Path.Combine(outputDirectory));
            string openEmsInput = Path.Combine(outputDirectory, "openEMS_input.xml");
            doc.Save(openEmsInput);

            string nf2ffInput = Path.Combine(outputDirectory, "nf2ff_input.xml");
            var nf2ff = new Postprocess.NF2FF(frequency);
            nf2ff.ToXDocument().Save(nf2ffInput);

            File.WriteAllText(Path.Combine(outputDirectory, "run_sar.cmd"), AraRFAnalysis.Properties.Resources.run_sar);
        }
        public void GenerateFarFieldSimulationInput(string outputDirectory)
        {
            Compound simulationSpace = new Compound("space");
            Compound solidSpace = new Compound("solid-space");
            simulationSpace.Add(solidSpace);

            Compound dut;
            if (excludeEndo == true)
            {
                dut = endo.GetModule(slotIndex);
            }
            else
            {
                dut = endo;
            }
            solidSpace.Add(dut); // modifies dut parent (!)

            double airBox = 40;
            double maxRes = Math.Round(lambdaMin / 20 / unit);
            double maxRatio = 1.5;

            RectilinearGrid grid = new RectilinearGrid();
            grid.Add(dut.BoundingBox.P1);
            grid.Add(dut.BoundingBox.P2);

            Vector3D antennaPosition = new Vector3D(
                antenna.AbsoluteTransformation.X,
                antenna.AbsoluteTransformation.Y,
                antenna.AbsoluteTransformation.Z);

            solidSpace.Transformations.Add(new TTranslate(-antennaPosition));

            grid.Move(-antennaPosition);
            grid.Add(new Vector3D(0, 0, 0));
            grid.ZLines.Add(-(antenna.Parent as CSXCAD.Ara.PCB).Thickness);
            grid.Sort();

            grid.SmoothMesh(dutResolution, maxRatio);
            grid.AddAirbox(airBox);
            grid.SmoothMesh(maxRes, maxRatio);

            simulationSpace.Add(new NF2FFBox("nf2ff",
                new Vector3D(grid.XLines.First(), grid.YLines.First(), grid.ZLines.First()),
                new Vector3D(grid.XLines.Last(), grid.YLines.Last(), grid.ZLines.Last()),
                lambdaMin / 15 / unit));

            grid.AddPML(8);

            Simulation fdtd = new Simulation();
            fdtd.Excitation = new GaussExcitation(frequency, bandwidth);

            // Export
            XDocument doc = new XDocument(
                new XDeclaration("1.0", "utf-8", "yes"),
                new XComment("CyPhy generated openEMS simulation file"),
                new XElement("openEMS",
                    fdtd.ToXElement(),
                    new XElement("ContinuousStructure",
                        new XAttribute("CoordSystem", 0),
                        simulationSpace.ToXElement(),
                        grid.ToXElement()
                    )
                )
            );

            if (dut is CSXCAD.Ara.Module)
            {
                dut.Parent = endo;
            }

            System.IO.Directory.CreateDirectory(outputDirectory);
            string openEmsInput = Path.Combine(outputDirectory, "openEMS_input.xml");
            doc.Save(openEmsInput);

            string nf2ffInput = Path.Combine(outputDirectory, "nf2ff_input.xml");
            var nf2ff = new Postprocess.NF2FF(frequency);
            nf2ff.ToXDocument().Save(nf2ffInput);

            File.WriteAllText(Path.Combine(outputDirectory, "run_farfield.cmd"), AraRFAnalysis.Properties.Resources.run_farfield);
        }
        static void ExportAntenna_InvertedF()
        {
            double thickness = 0.01;
            double airBox = 5.0;
            double innerResolution = 0.5;
            double outerResolution = 5.0;

            var antenna = new CSXCAD.Antenna.InvertedF_2400MHz(thickness);

            const double pcbThickness = 1.5;
            var lumpedPort = new LumpedPort(90, 1, 50, new Vector3D(0.0, 0.0, -pcbThickness), new Vector3D(0.0, 0.0, 0), ENormDir.Z, true);
            antenna.Add(lumpedPort);

            double margin = 2.0;
            double groundWidth = 5.0;
            var p1 = new Vector3D(antenna.BoundingBox.P1.x-margin, -groundWidth-margin, -pcbThickness);
            var p2 = new Vector3D(antenna.BoundingBox.P2.x+margin, antenna.BoundingBox.P2.y+margin, 0);

            var substrate = new Dielectric("pcb", 3.38, 1e-3 * 2 * Math.PI * 2.45e9 * 3.38 * Material.Eps0);
            substrate.EdgeColor = new Material.Color(10, 255, 10, 128);
            substrate.FillColor = new Material.Color(10, 255, 10, 128);
            var pcb = new CSXCAD.Box(null, substrate, 60, p1, p2);
            //antenna.Add(pcb);

            var topGround = new Metal("bottom-ground");
            topGround.EdgeColor = new Material.Color(235, 148, 7, 255);
            topGround.FillColor = topGround.EdgeColor;
            var topGroundPlane = new CSXCAD.Box(null, topGround, 100,
                new Vector3D(antenna.BoundingBox.P1.x, 0, -pcbThickness),
                new Vector3D(antenna.BoundingBox.P2.x, -groundWidth, -pcbThickness));
            antenna.Add(topGroundPlane);

            var bottomGround = new Metal("top-ground");
            bottomGround.EdgeColor = new Material.Color(235, 148, 7, 255);
            bottomGround.FillColor = bottomGround.EdgeColor;
            var topGroundPlaneLeft = new CSXCAD.Box(null, bottomGround, 100,
                new Vector3D(antenna.BoundingBox.P1.x, 0, 0),
                new Vector3D(-0.46/2-0.45, -groundWidth, 0));
            var topGroundPlaneRight = new CSXCAD.Box(null, bottomGround, 100,
                new Vector3D(0.46/2+0.45, 0, 0),
                new Vector3D(antenna.BoundingBox.P2.x, -groundWidth, 0));
            antenna.Add(topGroundPlaneLeft);
            antenna.Add(topGroundPlaneRight);

            Simulation fdtd = new Simulation();
            fdtd.Excitation = new GaussExcitation(2450e6, 500e6);

            RectilinearGrid grid = new RectilinearGrid(); ;
            grid.Add(new Vector3D(0,0,0));

            grid.SmoothMesh(innerResolution);
            grid.AddAirbox(airBox);
            grid.SmoothMesh(outerResolution);
            var nf2ff = new NF2FFBox("nf2ff",
                new Vector3D(grid.XLines.First(), grid.YLines.First(), grid.ZLines.First()),
                new Vector3D(grid.XLines.Last(), grid.YLines.Last(), grid.ZLines.Last()));
            antenna.Add(nf2ff);
            grid.AddPML(8);

            XDocument doc = new XDocument(
                new XDeclaration("1.0", "utf-8", "yes"),
                new XComment("Test XML file for CyPhy generated openEMS simulations"),
                new XElement("openEMS",
                    fdtd.ToXElement(),
                    new XElement("ContinuousStructure",
                        new XAttribute("CoordSystem", 0),
                        antenna.ToXElement(),
                        grid.ToXElement()
                    )
                )
            );

            doc.Save("InvertedF.xml");
        }
        private void GenerateDirectivitySimulationInput()
        {
            // Constants
            double unit = 1e-3;
            double c0 = 299792458.0;
            double lambda0 = c0 / m_f0;
            double lambdaMin = c0 / (m_f0 + m_fc);

            Compound simulationSpace = new Compound("space");
            Compound solidSpace = new Compound("solid-space");
            simulationSpace.Add(solidSpace);

            Compound dut;
            if (m_excludeEndo == true)
            {
                dut = m_endo.GetModule(m_slotIndex);
            }
            else
            {
                dut = m_endo;
            }
            solidSpace.Add(dut); // modifies dut parent (!)

            // Set up simulation grid, nf2ff and SAR
            Logger.WriteInfo("Constructing FDTD simulation grid...");
            double airBox = 40;
            double maxRes = Math.Round(lambdaMin / 20 / unit);
            double maxRatio = 1.5;

            RectilinearGrid grid = new RectilinearGrid();
            grid.Add(dut.BoundingBox.P1);
            grid.Add(dut.BoundingBox.P2);

            #region openems_workaround

            // openEMS v0.0.31 seems to handle transformations on excitation (lumped port),
            // SAR and NF2FF simulation components incorrectly.
            // Applied workarounds:
            // 1. The entire design is moved so that the antenna feedpoint is in the origin
            // 2. The SAR and NF2FF boxes are added late, w/o transformations

            Vector3D antennaPosition = new Vector3D(
                m_antenna.AbsoluteTransformation.X,
                m_antenna.AbsoluteTransformation.Y,
                m_antenna.AbsoluteTransformation.Z);

            solidSpace.Transformations.Add(new TTranslate(-antennaPosition));

            grid.Move(-antennaPosition);
            grid.Add(new Vector3D(0, 0, 0));
            grid.ZLines.Add(-(m_antenna.Parent as CSXCAD.Ara.PCB).Thickness);
            grid.Sort();

            grid.SmoothMesh(m_dutResolution, maxRatio);
            grid.AddAirbox(airBox);
            grid.SmoothMesh(maxRes, maxRatio);

            simulationSpace.Add(new NF2FFBox("nf2ff",
                new Vector3D(grid.XLines.First(), grid.YLines.First(), grid.ZLines.First()),
                new Vector3D(grid.XLines.Last(), grid.YLines.Last(), grid.ZLines.Last()),
                lambdaMin / 15 / unit));
            #endregion

            grid.AddPML(8);

            Simulation fdtd = new Simulation();
            fdtd.Excitation = new GaussExcitation(m_f0, m_fc);

            // Export
            XDocument doc = new XDocument(
                new XDeclaration("1.0", "utf-8", "yes"),
                new XComment("CyPhy generated openEMS simulation file"),
                new XElement("openEMS",
                    fdtd.ToXElement(),
                    new XElement("ContinuousStructure",
                        new XAttribute("CoordSystem", 0),
                        simulationSpace.ToXElement(),
                        grid.ToXElement()
                    )
                )
            );

            if (dut is CSXCAD.Ara.Module)
            {
                dut.Parent = m_endo;
            }

            string openEmsInput = Path.Combine(mainParameters.OutputDirectory, "openEMS_input.xml");
            doc.Save(openEmsInput);

            string nf2ffInput = Path.Combine(mainParameters.OutputDirectory, "nf2ff_input.xml");
            var nf2ff = new Postprocess.NF2FF(m_f0);
            nf2ff.ToXDocument().Save(nf2ffInput);
        }
        static void ExportAntenna_Small_15x6mm()
        {
            double thickness = 0.01;
            double airBox = 5.0;
            double innerResolution = 0.5;
            double outerResolution = 5.0;

            var antenna = new CSXCAD.Antenna.Small_15x6mm_2400MHz(thickness);

            const double pcbThickness = 1.5;
            var lumpedPort = new LumpedPort(90, 1, 50, new Vector3D(0.0, 0.0, -pcbThickness), new Vector3D(0.0, 0.0, 0), ENormDir.Z, true);
            antenna.Add(lumpedPort);

            double margin = 2.0;
            double groundWidth = 5.0;
            var p1 = new Vector3D(antenna.BoundingBox.P1.x - margin, -groundWidth - margin, -pcbThickness);
            var p2 = new Vector3D(antenna.BoundingBox.P2.x + margin, antenna.BoundingBox.P2.y + margin, 0);

            double epsRel = 4.88;
            var substrate = new Dielectric("pcb", epsRel, 1e-3 * 2 * Math.PI * 2.45e9 * epsRel * Material.Eps0);
            substrate.EdgeColor = new Material.Color(10, 255, 10, 128);
            substrate.FillColor = new Material.Color(10, 255, 10, 128);
            var pcb = new CSXCAD.Box(null, substrate, 60, p1, p2);
            antenna.Add(pcb);

            var bottomGround = new Metal("bottom-ground");
            bottomGround.EdgeColor = new Material.Color(235, 148, 7, 255);
            bottomGround.FillColor = bottomGround.EdgeColor;
            var bottomGroundPlane = new CSXCAD.Box(null, bottomGround, 100,
                new Vector3D(antenna.BoundingBox.P1.x - antenna.D1, antenna.D4 / 2, -pcbThickness),
                new Vector3D(antenna.BoundingBox.P2.x + antenna.D3, -groundWidth, -pcbThickness-0.01));
            antenna.Add(bottomGroundPlane);

            var topGround = new Metal("top-ground");
            topGround.EdgeColor = new Material.Color(235, 148, 7, 255);
            topGround.FillColor = topGround.EdgeColor;
            var topGroundPlane = new CSXCAD.Box(null, topGround, 100,
                new Vector3D(antenna.BoundingBox.P1.x - antenna.D1, -antenna.D4 / 2, 0),
                new Vector3D(antenna.BoundingBox.P2.x + antenna.D3, -groundWidth, 0.01));
            antenna.Add(topGroundPlane);

            var viaMetal = new Metal("via");
            viaMetal.EdgeColor = new Material.Color(235, 148, 7, 255);
            viaMetal.FillColor = viaMetal.EdgeColor;
            var via = new Cylinder(null, viaMetal, 100,
                new Vector3D(-(antenna.W1 / 2 + antenna.D5 + antenna.W2 / 2), 0, -pcbThickness),
                new Vector3D(-(antenna.W1 / 2 + antenna.D5 + antenna.W2 / 2), 0, 0),
                0.25);
            antenna.Add(via);

            Simulation fdtd = new Simulation();
            fdtd.Excitation = new GaussExcitation(2450e6, 500e6);

            RectilinearGrid grid = new RectilinearGrid(); ;
            grid.Add(new Vector3D(0, 0, 0));
            grid.Add(pcb.P1);
            grid.Add(pcb.P2);
            /*
            foreach (var v in antenna.antennaPoly)
            {
                grid.Add(new Vector3D(v.x, v.y, 0));
            }
            */

            grid.SmoothMesh(innerResolution);
            grid.AddAirbox(airBox);
            grid.SmoothMesh(outerResolution);
            var nf2ff = new NF2FFBox("nf2ff",
                new Vector3D(grid.XLines.First(), grid.YLines.First(), grid.ZLines.First()),
                new Vector3D(grid.XLines.Last(), grid.YLines.Last(), grid.ZLines.Last()));
            antenna.Add(nf2ff);
            grid.AddPML(8);

            XDocument doc = new XDocument(
                new XDeclaration("1.0", "utf-8", "yes"),
                new XComment("Test XML file for CyPhy generated openEMS simulations"),
                new XElement("openEMS",
                    fdtd.ToXElement(),
                    new XElement("ContinuousStructure",
                        new XAttribute("CoordSystem", 0),
                        antenna.ToXElement(),
                        grid.ToXElement()
                    )
                )
            );

            doc.Save("Small_15x6mm.xml");
        }
        private void GenerateSarSimulationInput()
        {
            // Constants
            double unit = 1e-3;
            double c0 = 299792458.0;
            double lambda0 = c0 / m_f0;
            double f_c = 500e6;
            double lambdaMin = c0 / (m_f0 + f_c);

            Compound simulationSpace = new Compound("space");
            Compound solidSpace = new Compound("solid-space");
            simulationSpace.Add(solidSpace);
            solidSpace.Add(m_endo);

            var headPhantom = new CSXCAD.Ara.HeadPhantom();
            headPhantom.Transformations.Add(new TRotateX(Math.PI / 2));
            headPhantom.Transformations.Add(new TTranslate(32.0, 80.0, -headPhantom.Width / 2 - 7.0)); // TODO: Make endo width/height accessibles
            solidSpace.Add(headPhantom);

            // Set up simulation grid, nf2ff and SAR
            Logger.WriteInfo("Constructing FDTD simulation grid...");
            double airBox = 40;
            double envResolution = Math.Round(lambdaMin / 20 / unit);
            double maxRatio = 1.5;

            RectilinearGrid grid = new BoundingGrid_6x3();

            #region openems_workaround

            // openEMS v0.0.31 seems to handle transformations on excitation (lumped port),
            // SAR and NF2FF simulation components incorrectly.
            // Applied workarounds:
            // 1. The entire design is moved so that the antenna feedpoint is in the origin
            // 2. The SAR and NF2FF boxes are added late, w/o transformations

            Vector3D dutPosition = new Vector3D(
                m_antenna.AbsoluteTransformation.X,
                m_antenna.AbsoluteTransformation.Y,
                m_antenna.AbsoluteTransformation.Z);

            solidSpace.Transformations.Add(new TTranslate(-dutPosition));

            grid.Move(-dutPosition);
            grid.Add(new Vector3D(0, 0, 0));
            grid.ZLines.Add(-(m_antenna.Parent as CSXCAD.Ara.PCB).Thickness);
            grid.Sort();
            grid.SmoothMesh(m_dutResolution, maxRatio);

            grid.Add(headPhantom.BoundingBox.P1);
            grid.Add(headPhantom.BoundingBox.P2);
            grid.SmoothMesh(m_sarResolution, maxRatio);

            grid.AddAirbox(airBox);
            grid.SmoothMesh(envResolution, maxRatio);

            simulationSpace.Add(new SARBox("SAR", m_f0,
                new Vector3D(headPhantom.XGridPoints.First(), headPhantom.YGridPoints.First(), headPhantom.ZGridPoints.First()),
                new Vector3D(headPhantom.XGridPoints.Last(), headPhantom.YGridPoints.Last(), headPhantom.ZGridPoints.Last())));
            simulationSpace.Add(new NF2FFBox("nf2ff",
                new Vector3D(grid.XLines.First(), grid.YLines.First(), grid.ZLines.First()),
                new Vector3D(grid.XLines.Last(), grid.YLines.Last(), grid.ZLines.Last()),
                lambdaMin / 15 / unit));

            #endregion

            grid.AddPML(8);

            Simulation fdtd = new Simulation();
            fdtd.Excitation = new GaussExcitation(m_f0, m_fc);

            // Export
            XDocument doc = new XDocument(
                new XDeclaration("1.0", "utf-8", "yes"),
                new XComment("CyPhy generated openEMS simulation file"),
                new XElement("openEMS",
                    fdtd.ToXElement(),
                    new XElement("ContinuousStructure",
                        new XAttribute("CoordSystem", 0),
                        simulationSpace.ToXElement(),
                        grid.ToXElement()
                    )
                )
            );

            string openEmsInput = Path.Combine(mainParameters.OutputDirectory, "openEMS_input.xml");
            doc.Save(openEmsInput);

            string nf2ffInput = Path.Combine(mainParameters.OutputDirectory, "nf2ff_input.xml");
            var nf2ff = new Postprocess.NF2FF(m_f0);
            nf2ff.ToXDocument().Save(nf2ffInput);
        }
 public SARBox(string name, double f, Vector3D p1, Vector3D p2)
     : this(name, new List<double> { f }, p1, p2)
 {
 }
        public void Box_ExportToXmlAndParse_MatchesOriginal()
        {
            var v1 = new Vector3D(0.0, 0.0, 0.0);
            var v2 = new Vector3D(5.0, 0.0, 0.0);
            Box refBox = new Box(null, null, 0, v1, v2);

            XElement xmlBox = refBox.ToXElement();
            XmlCompound xb = new XmlCompound(null, "test-compound", new Vector3D(), 0.0);
            Box dutBox = (Box)Primitive.FromXElement(xmlBox, null);

            Assert.Equal(v1, dutBox.P1);
            Assert.Equal(v2, dutBox.P2);
        }
        public LumpedPort(uint priority, uint portNum, double r, Vector3D p1, Vector3D p2,
            ENormDir dir, bool excite = false)
            : base("port-" + portNum)
        {
            m_portNum = portNum;
            m_rInternal = Double.NaN;

            m_time = null;
            m_uTdValue = null;
            m_iTdValue = null;
            Freqs = null;
            m_uFdValue = null;
            m_iFdValue = null;

            if (p1.Coordinates[(uint)dir] == p2.Coordinates[(uint)dir])
            {
                Console.WriteLine("Error: Excitation vector normal direction component must not be zero");
                return;
            }

            double dirSign = p1.Coordinates[(uint)dir] < p2.Coordinates[(uint)dir] ? +1.0 : -1.0;

            // Lumped element
            Material le;
            if (r > 0 && r != Double.NaN)
            {
                m_rInternal = r;
                le = new LumpedElement("port_resist_" + portNum, dir, r: r, c: 1);
            }
            else
            {
                m_rInternal = Double.NaN;
                le = new Metal("port_resist_" + portNum);
            }
            m_primitives.Add(new Box(this, le, priority, p1, p2));
            ZReference = m_rInternal;

            // Excitation
            Vector3D ev = new Vector3D();
            ev[(int)dir] = 1.0;
            ExcitationField ef = new ExcitationField("port_excite_" + portNum,
                ExcitationField.EType.E_FIELD_SOFT, -dirSign * ev);
            m_primitives.Add(new Box(this, ef, priority, p1, p2));

            // Probes
            Vector3D u1 = 0.5 * (p1 + p2);
            Vector3D u2 = 0.5 * (p1 + p2);
            u1[(int)dir] = p1[(int)dir];
            u2[(int)dir] = p2[(int)dir];
            Probe probe_u = new Probe("port_ut" + portNum, Probe.EType.VOLTAGE_PROBE, -dirSign);
            m_primitives.Add(new Box(this, probe_u, priority, u1, u2));

            Vector3D i1 = new Vector3D(p1.x, p1.y, p1.z);
            Vector3D i2 = new Vector3D(p2.x, p2.y, p2.z);
            i1[(int)dir] = 0.5 * (p1[(int)dir] + p2[(int)dir]);
            i2[(int)dir] = 0.5 * (p1[(int)dir] + p2[(int)dir]);
            Probe probe_i = new Probe("port_it" + portNum, Probe.EType.CURRENT_PROBE, dirSign, dir);
            m_primitives.Add(new Box(this, probe_i, priority, i1, i2));
        }
 /// <summary>
 /// Shifts the existing grid points with the amount defined by the vector coordinates.
 /// </summary>
 /// <param name="v">The coordinates defining the amount of shifting.</param>
 public void Move(Vector3D v)
 {
     XLines = (from line in XLines select line + v.x).ToList();
     YLines = (from line in YLines select line + v.y).ToList();
     ZLines = (from line in ZLines select line + v.z).ToList();
 }