56#define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
57#define BOOST_MPL_LIMIT_VECTOR_SIZE 40
59#include "DCPSE/DCPSE_op/DCPSE_op.hpp"
60#include "DCPSE/DCPSE_op/DCPSE_Solver.hpp"
61#include "Operators/Vector/vector_dist_operators.hpp"
62#include "Vector/vector_dist_subset.hpp"
63#include "DCPSE/DCPSE_op/EqnsStruct.hpp"
64#include "OdeIntegrators/OdeIntegrators.hpp"
90constexpr int POLARIZATION= 0,VELOCITY = 1, VORTICITY = 2, EXTFORCE = 3,PRESSURE = 4, STRAIN_RATE = 5, STRESS = 6, MOLFIELD = 7, DPOL = 8, DV = 9, VRHS = 10, F1 = 11, F2 = 12, F3 = 13, F4 = 14, F5 = 15, F6 = 16, V_T = 17, DIV = 18, DELMU = 19, HPB = 20, FE = 21, R = 22;
104void *vectorGlobal=
nullptr,*vectorGlobal_bulk=
nullptr,*vectorGlobal_boundary=
nullptr;
106PropNAMES={
"00-Polarization",
"01-Velocity",
"02-Vorticity",
"03-ExternalForce",
"04-Pressure",
"05-StrainRate",
"06-Stress",
"07-MolecularField",
"08-DPOL",
"09-DV",
"10-VRHS",
"11-f1",
"12-f2",
"13-f3",
"14-f4",
"15-f5",
"16-f6",
"17-V_T",
"18-DIV",
"19-DELMU",
"20-HPB",
"21-FrankEnergy",
"22-R"};
107typedef aggregate<VectorS<2, double>,
VectorS<2, double>,
double[2][2],
VectorS<2, double>,double,
double[2][2],
double[2][2],
VectorS<2, double>,
VectorS<2, double>,
VectorS<2, double>,
VectorS<2, double>,double,double,double,double,double,double,
VectorS<2, double>,double,double,double,double,
double>
Activegels;
139template<
typename DX,
typename DY,
typename DXX,
typename DXY,
typename DYY>
148 PolarEv(DX &Dx,DY &Dy,DXX &Dxx,DXY &Dxy,DYY &Dyy):Dx(Dx),Dy(Dy),Dxx(Dxx),Dxy(Dxy),Dyy(Dyy)
157 auto Pol=getV<POLARIZATION>(Particles);
158 auto Pol_bulk=getV<POLARIZATION>(Particles_bulk);
159 auto h = getV<MOLFIELD>(Particles);
160 auto u = getV<STRAIN_RATE>(Particles);
161 auto dPol = getV<DPOL>(Particles);
162 auto W = getV<VORTICITY>(Particles);
163 auto delmu = getV<DELMU>(Particles);
164 auto H_p_b = getV<HPB>(Particles);
165 auto r = getV<R>(Particles);
166 auto dPol_bulk = getV<DPOL>(Particles_bulk);
167 Pol[x]=X.data.get<0>();
168 Pol[y]=X.data.get<1>();
169 Particles.
ghost_get<POLARIZATION>(SKIP_LABELLING);
170 H_p_b = Pol[x] * Pol[x] + Pol[y] * Pol[y];
172 h[y] = (Pol[x] * (Ks * Dyy(Pol[y]) + Kb * Dxx(Pol[y]) + (Ks - Kb) * Dxy(Pol[x])) -
173 Pol[y] * (Ks * Dxx(Pol[x]) + Kb * Dyy(Pol[x]) + (Ks - Kb) * Dxy(Pol[y])));
175 h[x] = -gama * (lambda * delmu - nu * (u[x][x] * Pol[x] * Pol[x] + u[y][y] * Pol[y] * Pol[y] + 2 * u[x][y] * Pol[x] * Pol[y]) / (H_p_b));
177 dPol_bulk[x] = ((h[x] * Pol[x] - h[y] * Pol[y]) / gama + lambda * delmu * Pol[x] -
178 nu * (u[x][x] * Pol[x] + u[x][y] * Pol[y]) + W[x][x] * Pol[x] +
180 dPol_bulk[y] = ((h[x] * Pol[y] + h[y] * Pol[x]) / gama + lambda * delmu * Pol[y] -
181 nu * (u[y][x] * Pol[x] + u[y][y] * Pol[y]) + W[y][x] * Pol[x] +
183 dxdt.data.get<0>()=dPol[x];
184 dxdt.data.get<1>()=dPol[y];
238template<
typename DX,
typename DY,
typename DXX,
typename DXY,
typename DYY>
252 CalcVelocity(DX &Dx,DY &Dy,DXX &Dxx,DXY &Dxy,DYY &Dyy,DX &Bulk_Dx,DY &Bulk_Dy):Dx(Dx),Dy(Dy),Dxx(Dxx),Dxy(Dxy),Dyy(Dyy),Bulk_Dx(Bulk_Dx),Bulk_Dy(Bulk_Dy)
261 double dt = t - t_old;
265 auto &v_cl = create_vcluster();
269 auto Pos = getV<PROP_POS>(Particles);
270 auto Pol=getV<POLARIZATION>(Particles);
271 auto V = getV<VELOCITY>(Particles);
272 auto H_p_b = getV<HPB>(Particles);
279 H_p_b = sqrt(Pol[x] * Pol[x] + Pol[y] * Pol[y]);
281 Pos = Pos + (t-t_old)*V;
283 Particles.
ghost_get<POLARIZATION, EXTFORCE, DELMU>();
285 Particles_boundary.
update();
287 Dx.update(Particles);
288 Dy.update(Particles);
289 Dxy.update(Particles);
290 Dxx.update(Particles);
291 Dyy.update(Particles);
293 Bulk_Dx.update(Particles_bulk);
294 Bulk_Dy.update(Particles_bulk);
296 state.data.get<0>()=Pol[x];
297 state.data.get<1>()=Pol[y];
300 if (v_cl.rank() == 0) {
301 std::cout <<
"Updating operators took " << tt.
getwct() <<
" seconds." << std::endl;
302 std::cout <<
"Time step " << ctr <<
" : " << t <<
" over." << std::endl;
303 std::cout <<
"----------------------------------------------------------" << std::endl;
312 auto & bulk = Particles_bulk.
getIds();
313 auto & boundary = Particles_boundary.
getIds();
314 auto Pol_bulk=getV<POLARIZATION>(Particles_bulk);
315 auto sigma = getV<STRESS>(Particles);
316 auto r = getV<R>(Particles);
317 auto h = getV<MOLFIELD>(Particles);
318 auto FranckEnergyDensity = getV<FE>(Particles);
319 auto f1 = getV<F1>(Particles);
320 auto f2 = getV<F2>(Particles);
321 auto f3 = getV<F3>(Particles);
322 auto f4 = getV<F4>(Particles);
323 auto f5 = getV<F5>(Particles);
324 auto f6 = getV<F6>(Particles);
325 auto dV = getV<DV>(Particles);
326 auto delmu = getV<DELMU>(Particles);
327 auto g = getV<EXTFORCE>(Particles);
328 auto P = getV<PRESSURE>(Particles);
329 auto P_bulk = getV<PRESSURE>(Particles_bulk);
330 auto RHS = getV<VRHS>(Particles);
331 auto RHS_bulk = getV<VRHS>(Particles_bulk);
332 auto div = getV<DIV>(Particles);
333 auto V_t = getV<V_T>(Particles);
334 auto u = getV<STRAIN_RATE>(Particles);
335 auto W = getV<VORTICITY>(Particles);
337 Pol_bulk[x]=state.data.get<0>();
338 Pol_bulk[y]=state.data.get<1>();
339 Particles.
ghost_get<POLARIZATION>(SKIP_LABELLING);
341 eq_id x_comp, y_comp;
345 int n = 0,nmax = 300,errctr = 0, Vreset = 0;
346 double V_err = 1,V_err_eps = 5 * 1e-3, V_err_old,
sum, sum1;
347 std::cout <<
"Calculate velocity (step t=" << t <<
")" << std::endl;
350 solverPetsc.setSolver(KSPGMRES);
351 solverPetsc.setPreconditioner(PCJACOBI);
352 Particles.
ghost_get<POLARIZATION>(SKIP_LABELLING);
355 -Ks * Dx(Pol[x]) * Dx(Pol[x]) - Kb * Dx(Pol[y]) * Dx(Pol[y]) + (Kb - Ks) * Dy(Pol[x]) * Dx(Pol[y]);
357 -Ks * Dy(Pol[y]) * Dx(Pol[y]) - Kb * Dy(Pol[x]) * Dx(Pol[x]) + (Kb - Ks) * Dx(Pol[y]) * Dx(Pol[x]);
359 -Ks * Dx(Pol[x]) * Dy(Pol[x]) - Kb * Dx(Pol[y]) * Dy(Pol[y]) + (Kb - Ks) * Dy(Pol[x]) * Dy(Pol[y]);
361 -Ks * Dy(Pol[y]) * Dy(Pol[y]) - Kb * Dy(Pol[x]) * Dy(Pol[x]) + (Kb - Ks) * Dx(Pol[y]) * Dy(Pol[x]);
362 Particles.
ghost_get<STRESS>(SKIP_LABELLING);
365 r = Pol[x] * Pol[x] + Pol[y] * Pol[y];
366 for (
int j = 0; j < bulk.size(); j++) {
367 auto p = bulk.get<0>(j);
370 for (
int j = 0; j < boundary.size(); j++) {
371 auto p = boundary.get<0>(j);
376 h[y] = (Pol[x] * (Ks * Dyy(Pol[y]) + Kb * Dxx(Pol[y]) + (Ks - Kb) * Dxy(Pol[x])) -
377 Pol[y] * (Ks * Dxx(Pol[x]) + Kb * Dyy(Pol[x]) + (Ks - Kb) * Dxy(Pol[y])));
378 Particles.
ghost_get<MOLFIELD>(SKIP_LABELLING);
381 FranckEnergyDensity = (Ks / 2.0) *
382 ((Dx(Pol[x]) * Dx(Pol[x])) + (Dy(Pol[x]) * Dy(Pol[x])) +
383 (Dx(Pol[y]) * Dx(Pol[y])) +
384 (Dy(Pol[y]) * Dy(Pol[y]))) +
385 ((Kb - Ks) / 2.0) * ((Dx(Pol[y]) - Dy(Pol[x])) * (Dx(Pol[y]) - Dy(Pol[x])));
389 f1 = gama * nu * Pol[x] * Pol[x] * (Pol[x] * Pol[x] - Pol[y] * Pol[y]) / (r);
390 f2 = 2.0 * gama * nu * Pol[x] * Pol[y] * (Pol[x] * Pol[x] - Pol[y] * Pol[y]) / (r);
391 f3 = gama * nu * Pol[y] * Pol[y] * (Pol[x] * Pol[x] - Pol[y] * Pol[y]) / (r);
392 f4 = 2.0 * gama * nu * Pol[x] * Pol[x] * Pol[x] * Pol[y] / (r);
393 f5 = 4.0 * gama * nu * Pol[x] * Pol[x] * Pol[y] * Pol[y] / (r);
394 f6 = 2.0 * gama * nu * Pol[x] * Pol[y] * Pol[y] * Pol[y] / (r);
395 Particles.
ghost_get<F1, F2, F3, F4, F5, F6>(SKIP_LABELLING);
396 texp_v<double> Dxf1 = Dx(f1),Dxf2 = Dx(f2),Dxf3 = Dx(f3),Dxf4 = Dx(f4),Dxf5 = Dx(f5),Dxf6 = Dx(f6),
397 Dyf1 = Dy(f1),Dyf2 = Dy(f2),Dyf3 = Dy(f3),Dyf4 = Dy(f4),Dyf5 = Dy(f5),Dyf6 = Dy(f6);
400 dV[x] = -0.5 * Dy(h[y]) + zeta * Dx(delmu * Pol[x] * Pol[x]) + zeta * Dy(delmu * Pol[x] * Pol[y]) -
401 zeta * Dx(0.5 * delmu * (Pol[x] * Pol[x] + Pol[y] * Pol[y])) -
402 0.5 * nu * Dx(-2.0 * h[y] * Pol[x] * Pol[y])
403 - 0.5 * nu * Dy(h[y] * (Pol[x] * Pol[x] - Pol[y] * Pol[y])) - Dx(sigma[x][x]) -
406 - 0.5 * nu * Dx(-gama * lambda * delmu * (Pol[x] * Pol[x] - Pol[y] * Pol[y]))
407 - 0.5 * Dy(-2.0 * gama * lambda * delmu * (Pol[x] * Pol[y]));
409 dV[y] = -0.5 * Dx(-h[y]) + zeta * Dy(delmu * Pol[y] * Pol[y]) + zeta * Dx(delmu * Pol[x] * Pol[y]) -
410 zeta * Dy(0.5 * delmu * (Pol[x] * Pol[x] + Pol[y] * Pol[y])) -
411 0.5 * nu * Dy(2.0 * h[y] * Pol[x] * Pol[y])
412 - 0.5 * nu * Dx(h[y] * (Pol[x] * Pol[x] - Pol[y] * Pol[y])) - Dx(sigma[y][x]) -
415 - 0.5 * nu * Dy(gama * lambda * delmu * (Pol[x] * Pol[x] - Pol[y] * Pol[y]))
416 - 0.5 * Dx(-2.0 * gama * lambda * delmu * (Pol[x] * Pol[y]));
420 auto Stokes1 =
eta * (Dxx(V[x]) + Dyy(V[x]))
421 + 0.5 * nu * (Dxf1 * Dx(V[x]) + f1 * Dxx(V[x]))
422 + 0.5 * nu * (Dxf2 * 0.5 * (Dx(V[y]) + Dy(V[x])) + f2 * 0.5 * (Dxx(V[y]) + Dyx(V[x])))
423 + 0.5 * nu * (Dxf3 * Dy(V[y]) + f3 * Dyx(V[y]))
424 + 0.5 * nu * (Dyf4 * Dx(V[x]) + f4 * Dxy(V[x]))
425 + 0.5 * nu * (Dyf5 * 0.5 * (Dx(V[y]) + Dy(V[x])) + f5 * 0.5 * (Dxy(V[y]) + Dyy(V[x])))
426 + 0.5 * nu * (Dyf6 * Dy(V[y]) + f6 * Dyy(V[y]));
427 auto Stokes2 =
eta * (Dxx(V[y]) + Dyy(V[y]))
428 - 0.5 * nu * (Dyf1 * Dx(V[x]) + f1 * Dxy(V[x]))
429 - 0.5 * nu * (Dyf2 * 0.5 * (Dx(V[y]) + Dy(V[x])) + f2 * 0.5 * (Dxy(V[y]) + Dyy(V[x])))
430 - 0.5 * nu * (Dyf3 * Dy(V[y]) + f3 * Dyy(V[y]))
431 + 0.5 * nu * (Dxf4 * Dx(V[x]) + f4 * Dxx(V[x]))
432 + 0.5 * nu * (Dxf5 * 0.5 * (Dx(V[y]) + Dy(V[x])) + f5 * 0.5 * (Dxx(V[y]) + Dyx(V[x])))
433 + 0.5 * nu * (Dxf6 * Dy(V[y]) + f6 * Dyx(V[y]));
437 std::cout <<
"Init of Velocity took " << tt.
getwct() <<
" seconds." << std::endl;
450 Particles.
ghost_get<PRESSURE>(SKIP_LABELLING);
451 RHS_bulk[x] = dV[x] + Bulk_Dx(
P);
452 RHS_bulk[y] = dV[y] + Bulk_Dy(
P);
453 Particles.
ghost_get<VRHS>(SKIP_LABELLING);
456 DCPSE_scheme<equations2d2, vector_type> Solver(Particles);
457 Solver.impose(Stokes1, bulk, RHS[0], x_comp);
458 Solver.impose(Stokes2, bulk, RHS[1], y_comp);
459 Solver.impose(V[x], boundary, 0, x_comp);
460 Solver.impose(V[y], boundary, 0, y_comp);
461 Solver.solve_with_solver(solverPetsc, V[x], V[y]);
462 Particles.
ghost_get<VELOCITY>(SKIP_LABELLING);
463 div = -(Dx(V[x]) + Dy(V[y]));
467 while (V_err >= V_err_eps && n <= nmax) {
468 Particles.
ghost_get<PRESSURE>(SKIP_LABELLING);
469 RHS_bulk[x] = dV[x] + Bulk_Dx(
P);
470 RHS_bulk[y] = dV[y] + Bulk_Dy(
P);
471 Particles.
ghost_get<VRHS>(SKIP_LABELLING);
473 Solver.impose_b(bulk, RHS[0], x_comp);
474 Solver.impose_b(bulk, RHS[1], y_comp);
475 Solver.impose_b(boundary, 0, x_comp);
476 Solver.impose_b(boundary, 0, y_comp);
477 Solver.solve_with_solver(solverPetsc, V[x], V[y]);
478 Particles.
ghost_get<VELOCITY>(SKIP_LABELLING);
479 div = -(Dx(V[x]) + Dy(V[y]));
484 for (
int j = 0; j < bulk.size(); j++) {
485 auto p = bulk.get<0>(j);
487 (Particles.
getProp<V_T>(p)[0] - Particles.
getProp<VELOCITY>(p)[0]) +
488 (Particles.
getProp<V_T>(p)[1] - Particles.
getProp<VELOCITY>(p)[1]) *
489 (Particles.
getProp<V_T>(p)[1] - Particles.
getProp<VELOCITY>(p)[1]);
490 sum1 += Particles.
getProp<VELOCITY>(p)[0] * Particles.
getProp<VELOCITY>(p)[0] +
491 Particles.
getProp<VELOCITY>(p)[1] * Particles.
getProp<VELOCITY>(p)[1];
501 if (V_err > V_err_old || abs(V_err_old - V_err) < 1e-8) {
509 std::cout <<
"CONVERGENCE LOOP BROKEN DUE TO INCREASE/VERY SLOW DECREASE IN DIVERGENCE" << std::endl;
521 Particles.
ghost_get<VELOCITY>(SKIP_LABELLING);
524 u[x][y] = 0.5 * (Dx(V[y]) + Dy(V[x]));
525 u[y][x] = 0.5 * (Dy(V[x]) + Dx(V[y]));
528 if (v_cl.rank() == 0) {
529 std::cout <<
"Rel l2 cgs err in V = " << V_err <<
" and took " << tt.
getwct() <<
" seconds with " << n
530 <<
" iterations. dt for the stepper is " << dt
536 W[x][y] = 0.5 * (Dy(V[x]) - Dx(V[y]));
537 W[y][x] = 0.5 * (Dx(V[y]) - Dy(V[x]));
540 if (ctr%wr_at==0 || ctr==wr_f){
542 Particles.write_frame(
"Polar",ctr);
560int main(
int argc,
char* argv[])
562 { openfpm_init(&argc,&argv);
565 size_t Gd = int(std::atof(argv[1]));
566 double tf = std::atof(argv[2]);
567 double dt = tf/std::atof(argv[3]);
568 wr_f=int(std::atof(argv[3]));
591 const size_t sz[2] = {Gd, Gd};
593 double Lx = box.
getHigh(0),Ly = box.getHigh(1);
594 size_t bc[2] = {NON_PERIODIC, NON_PERIODIC};
595 double spacing = box.getHigh(0) / (sz[0] - 1),rCut = 3.9 * spacing;
598 auto &v_cl = create_vcluster();
600 Particles.setPropNames(PropNAMES);
602 double x0=box.getLow(0), y0=box.getLow(1), x1=box.getHigh(0), y1=box.getHigh(1);
603 auto it = Particles.getGridIterator(sz);
604 while (it.isNext()) {
607 double xp = key.get(0) * it.getSpacing(0),yp = key.get(1) * it.getSpacing(1);
608 Particles.getLastPos()[x] = xp;
609 Particles.getLastPos()[y] = yp;
610 if (xp != x0 && yp != y0 && xp != x1 && yp != y1)
611 Particles.getLastSubset(0);
613 Particles.getLastSubset(1);
617 Particles.ghost_get<POLARIZATION>();
621 auto Pol = getV<POLARIZATION>(Particles);
622 auto V = getV<VELOCITY>(Particles);
623 auto g = getV<EXTFORCE>(Particles);
624 auto P = getV<PRESSURE>(Particles);
625 auto delmu = getV<DELMU>(Particles);
626 auto dPol = getV<DPOL>(Particles);
628 g = 0;delmu = -1.0;
P = 0;V = 0;
629 auto it2 = Particles.getDomainIterator();
630 while (it2.isNext()) {
633 Particles.getProp<POLARIZATION>(p)[x] = sin(2 * M_PI * (cos((2 * xp[x] - Lx) / Lx) - sin((2 * xp[y] - Ly) / Ly)));
634 Particles.getProp<POLARIZATION>(p)[y] = cos(2 * M_PI * (cos((2 * xp[x] - Lx) / Lx) - sin((2 * xp[y] - Ly) / Ly)));
637 Particles.ghost_get<POLARIZATION,EXTFORCE,DELMU>(SKIP_LABELLING);
656 auto & bulk = Particles_bulk.getIds();
657 auto & boundary = Particles_boundary.getIds();
659 auto P_bulk = getV<PRESSURE>(Particles_bulk);
660 auto Pol_bulk = getV<POLARIZATION>(Particles_bulk);;
661 auto dPol_bulk = getV<DPOL>(Particles_bulk);
662 auto dV_bulk = getV<DV>(Particles_bulk);
663 auto RHS_bulk = getV<VRHS>(Particles_bulk);
664 auto div_bulk = getV<DIV>(Particles_bulk);
666 Derivative_x Dx(Particles,ord,rCut), Bulk_Dx(Particles_bulk,ord,rCut);
667 Derivative_y Dy(Particles, ord, rCut), Bulk_Dy(Particles_bulk, ord,rCut);
668 Derivative_xy Dxy(Particles, ord, rCut);
670 Derivative_xx Dxx(Particles, ord, rCut);
671 Derivative_yy Dyy(Particles, ord, rCut);
673 boost::numeric::odeint::runge_kutta4< state_type_2d_ofp,double,state_type_2d_ofp,double,boost::numeric::odeint::vector_space_algebra_ofp> rk4;
675 vectorGlobal=(
void *) &Particles;
676 vectorGlobal_bulk=(
void *) &Particles_bulk;
677 vectorGlobal_boundary=(
void *) &Particles_boundary;
680 CalcVelocity<Derivative_x,Derivative_y,Derivative_xx,Derivative_xy,Derivative_yy> CalcVelocityObserver(Dx,Dy,Dxx,Dxy,Dyy,Bulk_Dx,Bulk_Dy);
683 tPol.data.get<0>()=Pol[x];
684 tPol.data.get<1>()=Pol[y];
691 double V_err = 1, V_err_old;
717 std::vector<double> inter_times;
719 size_t steps = integrate_const(rk4 ,
System , tPol , tim , tf , dt, CalcVelocityObserver);
722 std::cout <<
"Time steps: " << steps << std::endl;
724 Pol_bulk[x]=tPol.data.get<0>();
725 Pol_bulk[y]=tPol.data.get<1>();
727 Particles.deleteGhost();
728 Particles.write(
"Polar_Last");
729 Dx.deallocate(Particles);
730 Dy.deallocate(Particles);
731 Dxy.deallocate(Particles);
732 Dxx.deallocate(Particles);
733 Dyy.deallocate(Particles);
734 Bulk_Dx.deallocate(Particles_bulk);
735 Bulk_Dy.deallocate(Particles_bulk);
736 std::cout.precision(17);
738 if (v_cl.rank() == 0) {
739 std::cout <<
"The simulation took " << tt2.
getcputime() <<
"(CPU) ------ " << tt2.
getwct()
740 <<
"(Wall) Seconds.";
This class represent an N-dimensional box.
__device__ __host__ T getHigh(int i) const
get the high interval of the box
Test structure used for several test.
This class implement the point shape in an N-dimensional space.
Implementation of 1-D std::vector like structure.
In case T does not match the PETSC precision compilation create a stub structure.
Class for cpu time benchmarking.
void stop()
Stop the timer.
double getcputime()
Return the cpu time.
void start()
Start the timer.
double getwct()
Return the elapsed real time.
Main class that encapsulate a vector properties operand to be used for expressions construction.
void update()
Update the subset indexes.
openfpm::vector< aggregate< int > > & getIds()
Return the ids.
auto getProp(vect_dist_key_dx vec_key) -> decltype(v_prp.template get< id >(vec_key.getKey()))
Get the property of an element.
void ghost_get(size_t opt=WITH_POSITION)
It synchronize the properties and position of the ghost particles.
void map(size_t opt=NONE)
It move all the particles that does not belong to the local processor to the respective processor.
void deleteGhost()
Delete the particles on the ghost.
aggregate of properties, from a list of object if create a struct that follow the OPENFPM native stru...
[Definition of the system]
A 2d Odeint and Openfpm compatible structure.
It model an expression expr1 + ... exprn.