@@ -20,26 +20,21 @@ namespace amrex
2020// Note:
2121// This is a helper function, it's not part of the AMReX Blueprint Interface.
2222// ---------------------------------------------------------------------------//
23- template <int NStructReal, int NStructInt , int NArrayReal, int NArrayInt>
23+ template <typename ParticleType , int NArrayReal, int NArrayInt>
2424void
25- ParticleTileToBlueprint (const ParticleTile<amrex::Particle<NStructReal,
26- NStructInt>,
25+ ParticleTileToBlueprint (const ParticleTile<ParticleType,
2726 NArrayReal,
2827 NArrayInt> &ptile,
2928 const Vector<std::string> &real_comp_names,
3029 const Vector<std::string> &int_comp_names,
3130 conduit::Node &res,
3231 const std::string &topology_name)
3332{
34- int num_particles = ptile.GetArrayOfStructs ().size ();
35- int struct_size = sizeof (Particle<NStructReal, NStructInt>);
33+ int num_particles = ptile.size ();
3634
3735 // knowing the above, we can zero copy the x,y,z positions + id, cpu
3836 // and any user fields in the AOS
3937
40- // get the first particle's struct
41- const auto &pstruct = ptile.GetArrayOfStructs ();
42-
4338 // setup a blueprint description for the particle mesh
4439 // create a coordinate set
4540 std::string coordset_name = topology_name + " _coords" ;
@@ -63,29 +58,56 @@ ParticleTileToBlueprint(const ParticleTile<amrex::Particle<NStructReal,
6358 // ----------------------------------//
6459 // point locations from from aos
6560 // ----------------------------------//
61+ char * pbuf = nullptr ;
6662
67- const char * pbuf_const = reinterpret_cast <const char *>(pstruct.data ());
68- char * pbuf = const_cast <char *>(pbuf_const);
63+ if constexpr (ParticleType::is_soa_particle)
64+ {
65+ amrex::ignore_unused (pbuf);
6966
70- ParticleReal* xp = reinterpret_cast <ParticleReal*>(pbuf); pbuf += sizeof (ParticleReal);
71- n_coords[" values/x" ].set_external (xp,
72- num_particles,
73- 0 ,
74- struct_size);
67+ const auto &soa = ptile.GetStructOfArrays ();
68+
69+ // for soa entries, we can use standard strides,
70+ // since these are contiguous arrays
71+
72+ n_coords[" values/x" ].set_external (const_cast <ParticleReal*>(&soa.GetRealData (0 )[0 ]),
73+ num_particles);
7574#if AMREX_SPACEDIM > 1
76- ParticleReal* yp = reinterpret_cast <ParticleReal*>(pbuf); pbuf += sizeof (ParticleReal);
77- n_coords[" values/y" ].set_external (yp,
78- num_particles,
79- 0 ,
80- struct_size);
75+ n_coords[" values/y" ].set_external (const_cast <ParticleReal*>(&soa.GetRealData (1 )[0 ]),
76+ num_particles);
8177#endif
8278#if AMREX_SPACEDIM > 2
83- ParticleReal* zp = reinterpret_cast <ParticleReal*>(pbuf); pbuf += sizeof (ParticleReal);
84- n_coords[" values/z" ].set_external (zp,
85- num_particles,
86- 0 ,
87- struct_size);
79+ n_coords[" values/z" ].set_external (const_cast <ParticleReal*>(&soa.GetRealData (2 )[0 ]),
80+ num_particles);
81+ #endif
82+ } else
83+ {
84+ // get the first particle's struct
85+ const auto &pstruct = ptile.GetArrayOfStructs ();
86+ const int struct_size = sizeof (ParticleType);
87+
88+ const char * pbuf_const = reinterpret_cast <const char *>(pstruct.data ());
89+ pbuf = const_cast <char *>(pbuf_const);
90+
91+ ParticleReal* xp = reinterpret_cast <ParticleReal*>(pbuf); pbuf += sizeof (ParticleReal);
92+ n_coords[" values/x" ].set_external (xp,
93+ num_particles,
94+ 0 ,
95+ struct_size);
96+ #if AMREX_SPACEDIM > 1
97+ ParticleReal* yp = reinterpret_cast <ParticleReal*>(pbuf); pbuf += sizeof (ParticleReal);
98+ n_coords[" values/y" ].set_external (yp,
99+ num_particles,
100+ 0 ,
101+ struct_size);
102+ #endif
103+ #if AMREX_SPACEDIM > 2
104+ ParticleReal* zp = reinterpret_cast <ParticleReal*>(pbuf); pbuf += sizeof (ParticleReal);
105+ n_coords[" values/z" ].set_external (zp,
106+ num_particles,
107+ 0 ,
108+ struct_size);
88109#endif
110+ }
89111
90112 // fields
91113 conduit::Node &n_fields = res[" fields" ];
@@ -95,65 +117,104 @@ ParticleTileToBlueprint(const ParticleTile<amrex::Particle<NStructReal,
95117 // -----------------------------
96118
97119 int vname_real_idx = 0 ;
98- // struct real fields, the first set are always the particle positions
99- // which we wrap above
100- for (int i = 0 ; i < NStructReal; i++)
120+ if constexpr (!ParticleType::is_soa_particle)
101121 {
102- ParticleReal* val = reinterpret_cast <ParticleReal*>(pbuf); pbuf += sizeof (ParticleReal);
103- conduit::Node &n_f = n_fields[real_comp_names.at (vname_real_idx)];
104- n_f[" topology" ] = topology_name;
105- n_f[" association" ] = " element" ;
106- n_f[" values" ].set_external (val,
107- num_particles,
108- 0 ,
109- struct_size);
122+ constexpr int struct_size = sizeof (ParticleType);
123+ constexpr int NStructReal = ParticleType::NReal;
110124
111- vname_real_idx++;
125+ // struct real fields, the first set are always the particle positions
126+ // which we wrap above
127+ for (int i = 0 ; i < NStructReal; i++)
128+ {
129+ ParticleReal* val = reinterpret_cast <ParticleReal*>(pbuf); pbuf += sizeof (ParticleReal);
130+ conduit::Node &n_f = n_fields[real_comp_names.at (vname_real_idx)];
131+ n_f[" topology" ] = topology_name;
132+ n_f[" association" ] = " element" ;
133+ n_f[" values" ].set_external (val,
134+ num_particles,
135+ 0 ,
136+ struct_size);
137+
138+ vname_real_idx++;
139+ }
112140 }
113141
114142 // ----------------------------------//
115143 // standard integer fields from aos
116144 // (id, cpu)
117145 // ----------------------------------//
118146
119- // id is the first int entry
120- int * id = reinterpret_cast <int *>(pbuf); pbuf += sizeof (int );
121- conduit::Node &n_f_id = n_fields[topology_name + " _id" ];
147+ if constexpr (!ParticleType::is_soa_particle)
148+ {
149+ const int struct_size = sizeof (ParticleType);
150+
151+ // id is the first int entry
152+ int * id = reinterpret_cast <int *>(pbuf); pbuf += sizeof (int );
153+ conduit::Node &n_f_id = n_fields[topology_name + " _id" ];
154+
155+ n_f_id[" topology" ] = topology_name;
156+ n_f_id[" association" ] = " element" ;
157+ n_f_id[" values" ].set_external (id,
158+ num_particles,
159+ 0 ,
160+ struct_size);
161+
162+ // cpu is the second int entry
163+ int * cpu = reinterpret_cast <int *>(pbuf); pbuf += sizeof (int );
164+ conduit::Node &n_f_cpu = n_fields[topology_name + " _cpu" ];
165+
166+ n_f_cpu[" topology" ] = topology_name;
167+ n_f_cpu[" association" ] = " element" ;
168+ n_f_cpu[" values" ].set_external (cpu,
169+ num_particles,
170+ 0 ,
171+ struct_size);
172+ } else {
173+ const auto &soa = ptile.GetStructOfArrays ();
174+
175+ // for soa entries, we can use standard strides,
176+ // since these are contiguous arrays
122177
123- n_f_id[" topology" ] = topology_name;
124- n_f_id[" association" ] = " element" ;
125- n_f_id[" values" ].set_external (id,
126- num_particles,
127- 0 ,
128- struct_size);
178+ // id is the first int entry
179+ conduit::Node &n_f_id = n_fields[topology_name + " _id" ];
129180
130- // cpu is the second int entry
131- int * cpu = reinterpret_cast <int *>(pbuf); pbuf += sizeof (int );
132- conduit::Node &n_f_cpu = n_fields[topology_name + " _cpu" ];
181+ n_f_id[" topology" ] = topology_name;
182+ n_f_id[" association" ] = " element" ;
183+ n_f_id[" values" ].set_external (const_cast <int *>(&soa.GetIntData (0 )[0 ]),
184+ num_particles);
133185
134- n_f_cpu[" topology" ] = topology_name;
135- n_f_cpu[" association" ] = " element" ;
136- n_f_cpu[" values" ].set_external (cpu,
137- num_particles,
138- 0 ,
139- struct_size);
186+ // cpu is the second int entry
187+ conduit::Node &n_f_cpu = n_fields[topology_name + " _cpu" ];
188+
189+ n_f_cpu[" topology" ] = topology_name;
190+ n_f_cpu[" association" ] = " element" ;
191+ n_f_cpu[" values" ].set_external (const_cast <int *>(&soa.GetIntData (0 )[0 ]),
192+ num_particles);
193+
194+ }
140195
141196 // --------------------------------
142197 // user defined, integer aos fields
143198 // --------------------------------
144199
145200 int vname_int_idx = 0 ;
146- for ( int i = 0 ; i < NStructInt; i++ )
201+ if constexpr (!ParticleType::is_soa_particle )
147202 {
148- int * val = reinterpret_cast <int *>(pbuf); pbuf += sizeof (int );
149- conduit::Node &n_f = n_fields[int_comp_names.at (vname_int_idx)];
150- n_f[" topology" ] = topology_name;
151- n_f[" association" ] = " element" ;
152- n_f[" values" ].set_external (val,
153- num_particles,
154- 0 ,
155- struct_size);
156- vname_int_idx++;
203+ constexpr int struct_size = sizeof (ParticleType);
204+ constexpr int NStructInt = ParticleType::NInt;
205+
206+ for (int i = 0 ; i < NStructInt; i++)
207+ {
208+ int * val = reinterpret_cast <int *>(pbuf); pbuf += sizeof (int );
209+ conduit::Node &n_f = n_fields[int_comp_names.at (vname_int_idx)];
210+ n_f[" topology" ] = topology_name;
211+ n_f[" association" ] = " element" ;
212+ n_f[" values" ].set_external (val,
213+ num_particles,
214+ 0 ,
215+ struct_size);
216+ vname_int_idx++;
217+ }
157218 }
158219
159220 // -------------------------
@@ -193,10 +254,9 @@ ParticleTileToBlueprint(const ParticleTile<amrex::Particle<NStructReal,
193254// ---------------------------------------------------------------------------//
194255// Converts a AMReX Particle Container into a Conduit Mesh Blueprint Hierarchy.
195256// ---------------------------------------------------------------------------//
196- template <int NStructReal, int NStructInt , int NArrayReal, int NArrayInt>
257+ template <typename ParticleType , int NArrayReal, int NArrayInt>
197258void
198- ParticleContainerToBlueprint (const ParticleContainer<NStructReal,
199- NStructInt,
259+ ParticleContainerToBlueprint (const ParticleContainer_impl<ParticleType,
200260 NArrayReal,
201261 NArrayInt> &pc,
202262 const Vector<std::string> &real_comp_names,
@@ -209,8 +269,13 @@ ParticleContainerToBlueprint(const ParticleContainer<NStructReal,
209269 // validate varnames, which are used to provide field names
210270 // for user defined aos and soa values.
211271
212- BL_ASSERT (real_comp_names.size () == (NStructReal + NArrayReal) );
213- BL_ASSERT (int_comp_names.size () == (NStructInt + NArrayInt) );
272+ if constexpr (ParticleType::is_soa_particle) {
273+ BL_ASSERT (real_comp_names.size () == NArrayReal);
274+ BL_ASSERT (int_comp_names.size () == NArrayInt);
275+ } else {
276+ BL_ASSERT (real_comp_names.size () == (ParticleType::NReal + NArrayReal) );
277+ BL_ASSERT (int_comp_names.size () == (ParticleType::NInt + NArrayInt) );
278+ }
214279
215280 int num_levels = pc.maxLevel () + 1 ;
216281 int num_domains = 0 ;
@@ -224,7 +289,7 @@ ParticleContainerToBlueprint(const ParticleContainer<NStructReal,
224289 int rank = ParallelDescriptor::MyProc ();
225290 int nprocs = ParallelDescriptor::NProcs ();
226291
227- using MyParConstIter = ParConstIter<NStructReal, NStructInt , NArrayReal, NArrayInt>;
292+ using MyParConstIter = ParConstIter_impl<ParticleType , NArrayReal, NArrayInt>;
228293
229294 //
230295 // blueprint expects unique ids for each domain published
0 commit comments