@@ -791,9 +791,97 @@ TEST_F(ElectrostaticSolverTest, lansink2024_single_wire_L00_with_floating)
791791
792792 exportSolution (s, getTestCaseName ());
793793
794- auto expectedL00 = 320e-9 ; // Table 3 result has a mistake. This is the correct value.
794+ // Table 3 result has a mistake.
795+ // This is the correct value obtained through personal communication.
796+ auto expectedL00 = 320e-9 ;
795797
796798 //
797799 double rTol = 0.04 ;
798800 EXPECT_NEAR (0.0 , relError (expectedL00, computedL00), rTol);
801+ }
802+
803+ TEST_F (ElectrostaticSolverTest, lansink2024_small_one_centered_bem_comparison)
804+ {
805+ // Case from:
806+ // Rotgerink, J.L. et al. (2024, September).
807+ // Numerical Computation of In - cell Parameters for Multiwire Formalism in FDTD.
808+ // In 2024 International Symposium on Electromagnetic Compatibility
809+ // EMC Europe(pp. 334 - 339). IEEE.
810+
811+ // SMALL WIRE IS CENTERED AT ORIGIN.
812+ // This test compares multipolar expansion results between Tulip and BEM.
813+
814+ const std::string CASE{ " lansink2024_small_one_centered" };
815+ const std::string fn{ casesFolder () + CASE + " /" + CASE + " .pulmtln.in.json" };
816+ auto model{ Parser{fn}.readModel () };
817+
818+ auto fp = Driver::loadFromFile (fn).getFloatingPotentials ().electric ;
819+
820+ SolverInputs p;
821+ p.dirichletBoundaries = {
822+ {
823+ {1 , fp (0 ,0 )}, // Conductor 0,
824+ {2 , fp (0 ,1 )}, // Conductor 1,
825+ }
826+ };
827+ p.openBoundaries = { 3 };
828+
829+ ElectrostaticSolver s{ *model.getMesh (), p };
830+ s.Solve ();
831+
832+
833+ int order = 2 ;
834+
835+ // Tulip coefficients.
836+ multipolarCoefficients ab (order + 1 );
837+ mfem::Vector origin ({ 0.0 , 0.0 });
838+ for (int n = 0 ; n < order + 1 ; n++) {
839+ ab[n] = {
840+ s.getChargeMomentComponent (n, 0 , origin),
841+ s.getChargeMomentComponent (n, 1 , origin)
842+ };
843+ }
844+
845+ // BEM coefficients.
846+ multipolarCoefficients abBEM (order + 1 );
847+ abBEM[0 ] = { 1.0 , 0.0 };
848+ abBEM[1 ] = { 0.005 , 0.0 };
849+ abBEM[2 ] = { 8.7819e-5 , 0 };
850+
851+ // Checks normalizing by total charge.
852+ const double aTol = 1e-4 ;
853+ auto a0 = ab[0 ].first ;
854+ for (int n = 0 ; n < order + 1 ; n++) {
855+ EXPECT_NEAR (ab[n].first / a0, abBEM[n].first , aTol) << " for n=" << n;
856+ EXPECT_NEAR (ab[n].second / a0, abBEM[n].second , aTol) << " for n=" << n;
857+ }
858+
859+ // For debugging.
860+ // Export FEM solution.
861+ exportSolution (s, getTestCaseName ());
862+
863+ // Export multipolar expansion projection.
864+ auto multipolarSolution = s.getSolution ();
865+ std::function<double (const Vector&)> f =
866+ std::bind (&multipolarExpansion, std::placeholders::_1, ab, origin);
867+ FunctionCoefficient fc (f);
868+ multipolarSolution.phi ->ProjectCoefficient (fc);
869+ s.setSolution (multipolarSolution);
870+ exportSolution (s, getTestCaseName ()+" _from_multipolar_expansion_in_origin" );
871+
872+ // Computes and exports multipolar expansion with center of charge.
873+ {
874+ ElectrostaticSolver s{ *model.getMesh (), p };
875+ s.Solve ();
876+ auto centerOfCharge = s.getCenterOfCharge ();
877+ auto mCoeff = s.getMultipolarCoefficients (order);
878+ std::function<double (const Vector&)> f =
879+ std::bind (&multipolarExpansion, std::placeholders::_1, mCoeff , centerOfCharge);
880+ FunctionCoefficient fc (f);
881+ auto multipolarSolution = s.getSolution ();
882+ multipolarSolution.phi ->ProjectCoefficient (fc);
883+ s.setSolution (multipolarSolution);
884+ exportSolution (s, getTestCaseName () + " _from_multipolar_expansion_in_center_of_charge" );
885+ }
886+
799887}
0 commit comments