From 517c22a44c4204f9219b145e2a8f426ba1a4ea8d Mon Sep 17 00:00:00 2001 From: Oliver Henrich Date: Tue, 26 Oct 2021 18:02:21 +0100 Subject: [PATCH 001/117] Added rotated BP initialisation --- src/blue_phase_init.c | 179 +++++++++++++++++++++++++++++++++++++++++- src/blue_phase_init.h | 4 + src/blue_phase_rt.c | 20 +++++ 3 files changed, 202 insertions(+), 1 deletion(-) diff --git a/src/blue_phase_init.c b/src/blue_phase_init.c index 9e74335f3..c764ba06a 100644 --- a/src/blue_phase_init.c +++ b/src/blue_phase_init.c @@ -13,7 +13,7 @@ * (c) 2012-2021 The University of Edinburgh * * Contributing authors: - * Oliver Henrich (o.henrich@ucl.ac.uk) + * Oliver Henrich (oliver.henrich@strath.ac.uk) * Juho Lintuvuori * *****************************************************************************/ @@ -104,6 +104,96 @@ int blue_phase_O8M_init(cs_t * cs, fe_lc_param_t * param, field_t * fq) { return 0; } +/***************************************************************************** + * + * blue_phase_O8M_rot_init + * + * Initialisation of a rotated BP I + * + *****************************************************************************/ + +int blue_phase_O8M_rot_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, const double euler_angles[3]) { + + int ic, jc, kc; + int nlocal[3]; + int noffset[3]; + int index; + + double q[3][3]; + double x, y, z; + double r2; + double cosx, cosy, cosz, sinx, siny, sinz; + double q0; + double amplitude0; + + double MZ[3][3], MXp[3][3], MZp[3][3]; + double r[3], r_rot[3]; + int ik, il, im, in; + PI_DOUBLE(pi); + + assert(cs); + assert(fq); + + cs_nlocal(cs, nlocal); + cs_nlocal_offset(cs, noffset); + + r2 = sqrt(2.0); + q0 = param->q0; + amplitude0 = param->amplitude0; + + blue_phase_M_rot(MZ, 2,pi*euler_angles[0]/180.0); + blue_phase_M_rot(MXp,0,pi*euler_angles[1]/180.0); + blue_phase_M_rot(MZp,2,pi*euler_angles[2]/180.0); + + for (ic = 1; ic <= nlocal[X]; ic++) { + x = noffset[X] + ic; + for (jc = 1; jc <= nlocal[Y]; jc++) { + y = noffset[Y] + jc; + for (kc = 1; kc <= nlocal[Z]; kc++) { + z = noffset[Z] + kc; + + r[X] = x; + r[Y] = y; + r[Z] = z; + + for(ik=0; ik<3; ik++){ + r_rot[ik] = 0.0; + for(il=0; il<3; il++){ + for(im=0; im<3; im++){ + for(in=0; in<3; in++){ + r_rot[ik] += MZp[ik][il] * MXp[il][im] * MZ[im][in] * r[in]; + } + } + } + } + + cosx = cos(r2*q0*r_rot[X]); + cosy = cos(r2*q0*r_rot[Y]); + cosz = cos(r2*q0*r_rot[Z]); + sinx = sin(r2*q0*r_rot[X]); + siny = sin(r2*q0*r_rot[Y]); + sinz = sin(r2*q0*r_rot[Z]); + + q[X][X] = amplitude0*(-2.0*cosy*sinz + sinx*cosz + cosx*siny); + q[X][Y] = amplitude0*( r2*cosy*cosz + r2*sinx*sinz - sinx*cosy); + q[X][Z] = amplitude0*( r2*cosx*cosy + r2*sinz*siny - cosx*sinz); + q[Y][X] = q[X][Y]; + q[Y][Y] = amplitude0*(-2.0*sinx*cosz + siny*cosx + cosy*sinz); + q[Y][Z] = amplitude0*( r2*cosz*cosx + r2*siny*sinx - siny*cosz); + q[Z][X] = q[X][Z]; + q[Z][Y] = q[Y][Z]; + q[Z][Z] = - q[X][X] - q[Y][Y]; + + index = cs_index(cs, ic, jc, kc); + field_tensor_set(fq, index, q); + + } + } + } + + return 0; +} + /***************************************************************************** * * blue_phase_O2_init @@ -160,6 +250,93 @@ int blue_phase_O2_init(cs_t * cs, fe_lc_param_t * param, field_t * fq) { return 0; } +/***************************************************************************** + * + * blue_phase_O2_rot_init + * + * This initialisation is for a rotated BP II. + * + *****************************************************************************/ + +int blue_phase_O2_rot_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, const double euler_angles[3]) { + + int ic, jc, kc; + int nlocal[3]; + int noffset[3]; + int index; + + double q[3][3]; + double x, y, z; + double cosx, cosy, cosz, sinx, siny, sinz; + double q0; + double amplitude0; + + double MZ[3][3], MXp[3][3], MZp[3][3]; + double r[3], r_rot[3]; + int ik, il, im, in; + PI_DOUBLE(pi); + + assert(cs); + assert(fq); + + cs_nlocal(cs, nlocal); + cs_nlocal_offset(cs, noffset); + + q0 = param->q0; + amplitude0 = param->amplitude0; + + blue_phase_M_rot(MZ, 2,pi*euler_angles[0]/180.0); + blue_phase_M_rot(MXp,0,pi*euler_angles[1]/180.0); + blue_phase_M_rot(MZp,2,pi*euler_angles[2]/180.0); + + for (ic = 1; ic <= nlocal[X]; ic++) { + x = noffset[X] + ic; + for (jc = 1; jc <= nlocal[Y]; jc++) { + y = noffset[Y] + jc; + for (kc = 1; kc <= nlocal[Z]; kc++) { + z = noffset[Z] + kc; + + r[X] = x; + r[Y] = y; + r[Z] = z; + + for(ik=0; ik<3; ik++){ + r_rot[ik] = 0.0; + for(il=0; il<3; il++){ + for(im=0; im<3; im++){ + for(in=0; in<3; in++){ + r_rot[ik] += MZp[ik][il] * MXp[il][im] * MZ[im][in] * r[in]; + } + } + } + } + + cosx = cos(2.0*q0*r_rot[X]); + cosy = cos(2.0*q0*r_rot[Y]); + cosz = cos(2.0*q0*r_rot[Z]); + sinx = sin(2.0*q0*r_rot[X]); + siny = sin(2.0*q0*r_rot[Y]); + sinz = sin(2.0*q0*r_rot[Z]); + + q[X][X] = amplitude0*(cosz - cosy); + q[X][Y] = amplitude0*sinz; + q[X][Z] = amplitude0*siny; + q[Y][X] = q[X][Y]; + q[Y][Y] = amplitude0*(cosx - cosz); + q[Y][Z] = amplitude0*sinx; + q[Z][X] = q[X][Z]; + q[Z][Y] = q[Y][Z]; + q[Z][Z] = - q[X][X] - q[Y][Y]; + + index = cs_index(cs, ic, jc, kc); + field_tensor_set(fq, index, q); + } + } + } + + return 0; +} + /***************************************************************************** * * blue_phase_H2D_init diff --git a/src/blue_phase_init.h b/src/blue_phase_init.h index c4fb865a5..6a1d8d921 100644 --- a/src/blue_phase_init.h +++ b/src/blue_phase_init.h @@ -22,7 +22,11 @@ int blue_phase_twist_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, int helical_axis); int blue_phase_O8M_init(cs_t * cs, fe_lc_param_t * param, field_t * fq); +int blue_phase_O8M_rot_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, + const double euler_angles[3]); int blue_phase_O2_init(cs_t * cs, fe_lc_param_t * param, field_t * fq); +int blue_phase_O2_rot_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, + const double euler_angles[3]); int blue_phase_O5_init(cs_t * cs, fe_lc_param_t * param, field_t * fq); int blue_phase_H2D_init(cs_t * cs, fe_lc_param_t * param, field_t * fq); int blue_phase_H3DA_init(cs_t * cs, fe_lc_param_t * param, field_t * fq); diff --git a/src/blue_phase_rt.c b/src/blue_phase_rt.c index cf7051bfe..88655bc42 100644 --- a/src/blue_phase_rt.c +++ b/src/blue_phase_rt.c @@ -344,6 +344,8 @@ __host__ int blue_phase_rt_initial_conditions(pe_t * pe, rt_t * rt, cs_t * cs, double nhat[3] = {1.0, 0.0, 0.0}; double nhat2[3] = {64.0, 3.0, 1.0}; + double euler_angles[3] = {0.0, 0.0, 0.0}; + fe_lc_param_t param; fe_lc_param_t * feparam = ¶m; @@ -415,11 +417,29 @@ __host__ int blue_phase_rt_initial_conditions(pe_t * pe, rt_t * rt, cs_t * cs, blue_phase_O8M_init(cs, feparam, q); } + if (strcmp(key1, "o8m_rot") == 0) { + pe_info(pe, "Initialising Q_ab using rotated O8M (BPI)\n"); + if (strcmp(key1, "lc_q_euler_angles") == 0) { + rt_double_parameter_vector(rt, "lc_q_euler_angles", euler_angles); + pe_info(pe, "Euler angles alpha_z=%g, beta_x'=%g, gamma_z'=%g\n", euler_angles[0], euler_angles[1], euler_angles[2]); + } + blue_phase_O8M_rot_init(cs, feparam, q, euler_angles); + } + if (strcmp(key1, "o2") == 0) { pe_info(pe, "Initialising Q_ab using O2 (BPII)\n"); blue_phase_O2_init(cs, feparam, q); } + if (strcmp(key1, "o2_rot") == 0) { + pe_info(pe, "Initialising Q_ab using rotated O2 (BPII)\n"); + if (strcmp(key1, "lc_q_euler_angles") == 0) { + rt_double_parameter_vector(rt, "lc_q_euler_angles", euler_angles); + pe_info(pe, "Euler angles alpha_z=%g, beta_x'=%g, gamma_z'=%g\n", euler_angles[0], euler_angles[1], euler_angles[2]); + } + blue_phase_O2_rot_init(cs, feparam, q, euler_angles); + } + if (strcmp(key1, "o5") == 0) { pe_info(pe, "Initialising Q_ab using O5\n"); blue_phase_O5_init(cs, feparam, q); From 58a5065732096341244e3ab2ab8c5a7712ae5814 Mon Sep 17 00:00:00 2001 From: Oliver Henrich Date: Tue, 26 Oct 2021 19:26:15 +0100 Subject: [PATCH 002/117] Corrected Euler angle sign --- src/blue_phase_init.c | 40 ++++++++++++++++++++++++---------------- src/blue_phase_rt.c | 12 ++++-------- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/src/blue_phase_init.c b/src/blue_phase_init.c index c764ba06a..7287c8738 100644 --- a/src/blue_phase_init.c +++ b/src/blue_phase_init.c @@ -115,8 +115,7 @@ int blue_phase_O8M_init(cs_t * cs, fe_lc_param_t * param, field_t * fq) { int blue_phase_O8M_rot_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, const double euler_angles[3]) { int ic, jc, kc; - int nlocal[3]; - int noffset[3]; + int ntotal[3], nlocal[3], noffset[3]; int index; double q[3][3]; @@ -134,6 +133,7 @@ int blue_phase_O8M_rot_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, cons assert(cs); assert(fq); + cs_ntotal(cs, ntotal); cs_nlocal(cs, nlocal); cs_nlocal_offset(cs, noffset); @@ -141,9 +141,9 @@ int blue_phase_O8M_rot_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, cons q0 = param->q0; amplitude0 = param->amplitude0; - blue_phase_M_rot(MZ, 2,pi*euler_angles[0]/180.0); - blue_phase_M_rot(MXp,0,pi*euler_angles[1]/180.0); - blue_phase_M_rot(MZp,2,pi*euler_angles[2]/180.0); + blue_phase_M_rot(MZ, 2,-1.0*pi*euler_angles[0]/180.0); + blue_phase_M_rot(MXp,0,-1.0*pi*euler_angles[1]/180.0); + blue_phase_M_rot(MZp,2,-1.0*pi*euler_angles[2]/180.0); for (ic = 1; ic <= nlocal[X]; ic++) { x = noffset[X] + ic; @@ -152,9 +152,9 @@ int blue_phase_O8M_rot_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, cons for (kc = 1; kc <= nlocal[Z]; kc++) { z = noffset[Z] + kc; - r[X] = x; - r[Y] = y; - r[Z] = z; + r[X] = x - ntotal[X]/2; + r[Y] = y - ntotal[Y]/2; + r[Z] = z - ntotal[Z]/2; for(ik=0; ik<3; ik++){ r_rot[ik] = 0.0; @@ -167,6 +167,10 @@ int blue_phase_O8M_rot_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, cons } } + r_rot[X] += ntotal[X]/2; + r_rot[Y] += ntotal[Y]/2; + r_rot[Z] += ntotal[Z]/2; + cosx = cos(r2*q0*r_rot[X]); cosy = cos(r2*q0*r_rot[Y]); cosz = cos(r2*q0*r_rot[Z]); @@ -261,8 +265,7 @@ int blue_phase_O2_init(cs_t * cs, fe_lc_param_t * param, field_t * fq) { int blue_phase_O2_rot_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, const double euler_angles[3]) { int ic, jc, kc; - int nlocal[3]; - int noffset[3]; + int ntotal[3], nlocal[3], noffset[3]; int index; double q[3][3]; @@ -279,15 +282,16 @@ int blue_phase_O2_rot_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, const assert(cs); assert(fq); + cs_ntotal(cs, ntotal); cs_nlocal(cs, nlocal); cs_nlocal_offset(cs, noffset); q0 = param->q0; amplitude0 = param->amplitude0; - blue_phase_M_rot(MZ, 2,pi*euler_angles[0]/180.0); - blue_phase_M_rot(MXp,0,pi*euler_angles[1]/180.0); - blue_phase_M_rot(MZp,2,pi*euler_angles[2]/180.0); + blue_phase_M_rot(MZ, 2,-1.0*pi*euler_angles[0]/180.0); + blue_phase_M_rot(MXp,0,-1.0*pi*euler_angles[1]/180.0); + blue_phase_M_rot(MZp,2,-1.0*pi*euler_angles[2]/180.0); for (ic = 1; ic <= nlocal[X]; ic++) { x = noffset[X] + ic; @@ -296,9 +300,9 @@ int blue_phase_O2_rot_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, const for (kc = 1; kc <= nlocal[Z]; kc++) { z = noffset[Z] + kc; - r[X] = x; - r[Y] = y; - r[Z] = z; + r[X] = x - ntotal[X]/2; + r[Y] = y - ntotal[Y]/2; + r[Z] = z - ntotal[Z]/2; for(ik=0; ik<3; ik++){ r_rot[ik] = 0.0; @@ -311,6 +315,10 @@ int blue_phase_O2_rot_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, const } } + r_rot[X] += ntotal[X]/2; + r_rot[Y] += ntotal[Y]/2; + r_rot[Z] += ntotal[Z]/2; + cosx = cos(2.0*q0*r_rot[X]); cosy = cos(2.0*q0*r_rot[Y]); cosz = cos(2.0*q0*r_rot[Z]); diff --git a/src/blue_phase_rt.c b/src/blue_phase_rt.c index 88655bc42..89e0f757d 100644 --- a/src/blue_phase_rt.c +++ b/src/blue_phase_rt.c @@ -419,10 +419,8 @@ __host__ int blue_phase_rt_initial_conditions(pe_t * pe, rt_t * rt, cs_t * cs, if (strcmp(key1, "o8m_rot") == 0) { pe_info(pe, "Initialising Q_ab using rotated O8M (BPI)\n"); - if (strcmp(key1, "lc_q_euler_angles") == 0) { - rt_double_parameter_vector(rt, "lc_q_euler_angles", euler_angles); - pe_info(pe, "Euler angles alpha_z=%g, beta_x'=%g, gamma_z'=%g\n", euler_angles[0], euler_angles[1], euler_angles[2]); - } + rt_double_parameter_vector(rt, "lc_q_euler_angles", euler_angles); + pe_info(pe, "Euler angles alpha_z=%g, beta_x'=%g, gamma_z'=%g\n", euler_angles[0], euler_angles[1], euler_angles[2]); blue_phase_O8M_rot_init(cs, feparam, q, euler_angles); } @@ -433,10 +431,8 @@ __host__ int blue_phase_rt_initial_conditions(pe_t * pe, rt_t * rt, cs_t * cs, if (strcmp(key1, "o2_rot") == 0) { pe_info(pe, "Initialising Q_ab using rotated O2 (BPII)\n"); - if (strcmp(key1, "lc_q_euler_angles") == 0) { - rt_double_parameter_vector(rt, "lc_q_euler_angles", euler_angles); - pe_info(pe, "Euler angles alpha_z=%g, beta_x'=%g, gamma_z'=%g\n", euler_angles[0], euler_angles[1], euler_angles[2]); - } + rt_double_parameter_vector(rt, "lc_q_euler_angles", euler_angles); + pe_info(pe, "Euler angles alpha_z=%g, beta_x'=%g, gamma_z'=%g\n", euler_angles[0], euler_angles[1], euler_angles[2]); blue_phase_O2_rot_init(cs, feparam, q, euler_angles); } From 0e8ecda2eaa00c550560f4cf6dc959266938a2f4 Mon Sep 17 00:00:00 2001 From: Oliver Henrich Date: Wed, 27 Oct 2021 13:07:55 +0100 Subject: [PATCH 003/117] Division by float --- src/blue_phase_init.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/blue_phase_init.c b/src/blue_phase_init.c index 7287c8738..85e2306b5 100644 --- a/src/blue_phase_init.c +++ b/src/blue_phase_init.c @@ -152,9 +152,9 @@ int blue_phase_O8M_rot_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, cons for (kc = 1; kc <= nlocal[Z]; kc++) { z = noffset[Z] + kc; - r[X] = x - ntotal[X]/2; - r[Y] = y - ntotal[Y]/2; - r[Z] = z - ntotal[Z]/2; + r[X] = x - ntotal[X]/2.0; + r[Y] = y - ntotal[Y]/2.0; + r[Z] = z - ntotal[Z]/2.0; for(ik=0; ik<3; ik++){ r_rot[ik] = 0.0; @@ -167,9 +167,9 @@ int blue_phase_O8M_rot_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, cons } } - r_rot[X] += ntotal[X]/2; - r_rot[Y] += ntotal[Y]/2; - r_rot[Z] += ntotal[Z]/2; + r_rot[X] += ntotal[X]/2.0; + r_rot[Y] += ntotal[Y]/2.0; + r_rot[Z] += ntotal[Z]/2.0; cosx = cos(r2*q0*r_rot[X]); cosy = cos(r2*q0*r_rot[Y]); @@ -300,9 +300,9 @@ int blue_phase_O2_rot_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, const for (kc = 1; kc <= nlocal[Z]; kc++) { z = noffset[Z] + kc; - r[X] = x - ntotal[X]/2; - r[Y] = y - ntotal[Y]/2; - r[Z] = z - ntotal[Z]/2; + r[X] = x - ntotal[X]/2.0; + r[Y] = y - ntotal[Y]/2.0; + r[Z] = z - ntotal[Z]/2.0; for(ik=0; ik<3; ik++){ r_rot[ik] = 0.0; @@ -315,9 +315,9 @@ int blue_phase_O2_rot_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, const } } - r_rot[X] += ntotal[X]/2; - r_rot[Y] += ntotal[Y]/2; - r_rot[Z] += ntotal[Z]/2; + r_rot[X] += ntotal[X]/2.0; + r_rot[Y] += ntotal[Y]/2.0; + r_rot[Z] += ntotal[Z]/2.0; cosx = cos(2.0*q0*r_rot[X]); cosy = cos(2.0*q0*r_rot[Y]); From 32afa0e8357a9f755da331df95d8bd714e3e467d Mon Sep 17 00:00:00 2001 From: Oliver Henrich Date: Wed, 27 Oct 2021 16:55:36 +0100 Subject: [PATCH 004/117] Added regression tests for rotated BP1 and BP2 --- tests/regression/d3q19/long64-chol-bp1rot.inp | 89 ++++++++++ tests/regression/d3q19/long64-chol-bp1rot.log | 109 ++++++++++++ tests/regression/d3q19/long64-chol-bp2.inp | 2 +- tests/regression/d3q19/long64-chol-bp2rot.inp | 89 ++++++++++ tests/regression/d3q19/long64-chol-bp2rot.log | 160 ++++++++++++++++++ 5 files changed, 448 insertions(+), 1 deletion(-) create mode 100644 tests/regression/d3q19/long64-chol-bp1rot.inp create mode 100644 tests/regression/d3q19/long64-chol-bp1rot.log create mode 100644 tests/regression/d3q19/long64-chol-bp2rot.inp create mode 100644 tests/regression/d3q19/long64-chol-bp2rot.log diff --git a/tests/regression/d3q19/long64-chol-bp1rot.inp b/tests/regression/d3q19/long64-chol-bp1rot.inp new file mode 100644 index 000000000..88b066fc3 --- /dev/null +++ b/tests/regression/d3q19/long64-chol-bp1rot.inp @@ -0,0 +1,89 @@ +############################################################################## +# +# BPI test. +# Following initialisation in serial-init-bp1.inp with different orientation +# +############################################################################## + +N_cycles 20000 + +############################################################################## +# +# System and MPI +# +############################################################################## + +size 32_32_32 +grid 2_2_2 + +############################################################################## +# +# Fluid parameters +# +############################################################################## + +viscosity 1.666666666666 + +############################################################################## +# +# Free energy parameters +# +############################################################################### + +free_energy lc_blue_phase +fd_gradient_calculation 3d_7pt_fluid + +############################################################################### +# +# Blue Phase free energy +# +############################################################################### + +lc_a0 0.014384711 +lc_gamma 3.1764706 +lc_q0 0.27768018 +lc_kappa0 0.01 +lc_kappa1 0.01 + +lc_xi 0.7 +lc_Gamma 0.1 + +lc_q_initialisation o8m_rot +lc_q_euler_angles 90_0_0 +lc_q_init_amplitude -0.2 +lc_init_redshift 0.83 +lc_anchoring_method none + +############################################################################### +# +# Colloid parameters +# +############################################################################### + +colloid_init no_colloids + +############################################################################### +# +# Periodic conditions / boundaries +# +############################################################################### + +boundary_walls_on no +periodicity 1_1_1 + +############################################################################### +# +# Output frequency and type +# +############################################################################### + +freq_statistics 20000 +config_at_end no + +############################################################################### +# +# Miscellaneous +# +############################################################################### + +random_seed 8361235 diff --git a/tests/regression/d3q19/long64-chol-bp1rot.log b/tests/regression/d3q19/long64-chol-bp1rot.log new file mode 100644 index 000000000..9a6a20cee --- /dev/null +++ b/tests/regression/d3q19/long64-chol-bp1rot.log @@ -0,0 +1,109 @@ +Welcome to Ludwig v0.14.0 (MPI version running on 8 processes) +Start time: Wed Oct 27 16:36:54 2021 + +Compiler: + name: Gnu 11.2.0 + version-string: 11.2.0 + +Note assertions via standard C assert() are on. + +Target thread model: None. + +Read 24 user parameters from long64-chol-bp1rot.inp + +System details +-------------- +System size: 32 32 32 +Decomposition: 2 2 2 +Local domain: 16 16 16 +Periodic: 1 1 1 +Halo nhalo: 2 +Reorder: true +Initialised: 1 + +Free energy details +------------------- + +Blue phase free energy selected. + +Liquid crystal blue phase free energy +Bulk parameter A0: = 1.4384711e-02 +Magnitude of order gamma = 3.1764706e+00 +Pitch wavevector q0 = 2.7768018e-01 +... gives pitch length = 2.2627417e+01 +Elastic constant kappa0 = 1.0000000e-02 +Elastic constant kappa1 = 1.0000000e-02 +Amplitude (uniaxial) order = -2.0000000e-01 +Effective aspect ratio xi = 7.0000000e-01 +Chirality = 1.3500000e+00 +Reduced temperature = -5.0000003e-01 +Initial redshift = 8.3000000e-01 +Dynamic redshift update = no +Liquid crystal activity No + +Using Beris-Edwards solver: +Rotational diffusion const = 1.0000000e-01 +LC fluctuations: = off + +System properties +---------------- +Mean fluid density: 1.00000e+00 +Shear viscosity 1.66667e+00 +Bulk viscosity 1.66667e+00 +Temperature 0.00000e+00 +External body force density 0.00000e+00 0.00000e+00 0.00000e+00 +External E-field amplitude 0.00000e+00 0.00000e+00 0.00000e+00 +External E-field frequency 0.00000e+00 +External magnetic field 0.00000e+00 0.00000e+00 0.00000e+00 + +Lattice Boltzmann distributions +------------------------------- +Model: d3q19 +SIMD vector len: 1 +Number of sets: 1 +Halo type: full +Input format: binary +Output format: binary +I/O grid: 1 1 1 + +Lattice Boltzmann collision +--------------------------- +Relaxation time scheme: M10 +Hydrodynamic modes: on +Ghost modes: on +Isothermal fluctuations: off +Shear relaxation time: 5.50000e+00 +Bulk relaxation time: 5.50000e+00 +Ghost relaxation time: 1.00000e+00 +[User ] Random number seed: 8361235 + +Hydrodynamics +------------- +Hydrodynamics: on + +Order parameter I/O +------------------- +Order parameter I/O format: +I/O decomposition: 1 1 1 + +Advection scheme order: 1 (default) +Gradient calculation: 3d_7pt_fluid + + +Initialising Q_ab using rotated O8M (BPI) +Euler angles alpha_z=90, beta_x'=0, gamma_z'=0 +Initial conditions. + +Scalars - total mean variance min max +[rho] 32768.00 1.00000000000 2.2204460e-16 1.00000000000 1.00000000000 +[phi] 4.1905445e-13 1.2788527e-17 6.0000000e-02 -4.4966058e-01 4.4966058e-01 +[phi] -1.3582468e-12 -4.1450404e-17 5.0000000e-02 -6.0000000e-01 6.0000000e-01 +[phi] -1.1957657e-12 -3.6491873e-17 5.0000000e-02 -6.0000000e-01 6.0000000e-01 +[phi] 3.9868186e-13 1.2166805e-17 6.0000000e-02 -4.4966058e-01 4.4966058e-01 +[phi] -1.7553736e-12 -5.3569752e-17 5.0000000e-02 -6.0000000e-01 6.0000000e-01 + +Momentum - x y z +[total ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 +[fluid ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 + +Starting time step loop. diff --git a/tests/regression/d3q19/long64-chol-bp2.inp b/tests/regression/d3q19/long64-chol-bp2.inp index 0b3ba9e0d..297a2992b 100644 --- a/tests/regression/d3q19/long64-chol-bp2.inp +++ b/tests/regression/d3q19/long64-chol-bp2.inp @@ -1,7 +1,7 @@ ############################################################################## # # BPII test -# Following initialisation of serial-init-bp.inp +# Following initialisation of serial-init-bp2.inp # ############################################################################## diff --git a/tests/regression/d3q19/long64-chol-bp2rot.inp b/tests/regression/d3q19/long64-chol-bp2rot.inp new file mode 100644 index 000000000..eaee7e54e --- /dev/null +++ b/tests/regression/d3q19/long64-chol-bp2rot.inp @@ -0,0 +1,89 @@ +############################################################################## +# +# BPII test +# Following initialisation of serial-init-bp2.inp with different orientation +# +############################################################################## + +N_cycles 20000 + +############################################################################## +# +# System and MPI +# +############################################################################## + +size 32_32_32 +grid 2_2_2 + +############################################################################## +# +# Fluid parameters +# +############################################################################## + +viscosity 1.666666666666 + +############################################################################## +# +# Free energy parameters +# +############################################################################### + +free_energy lc_blue_phase +fd_gradient_calculation 3d_7pt_fluid + +############################################################################### +# +# Blue Phase free energy +# +############################################################################### + +lc_a0 0.0069 +lc_gamma 3.0 +lc_q0 0.1963495 +lc_kappa0 0.02 +lc_kappa1 0.02 + +lc_xi 0.7 +lc_Gamma 0.1 + +lc_q_initialisation o2_rot +lc_q_euler_angles 45_45_0 +lc_q_init_amplitude 0.3 +lc_init_redshift 0.91 +lc_anchoring_method none + +############################################################################### +# +# Colloid parameters +# +############################################################################### + +colloid_init no_colloids + +############################################################################### +# +# Periodic conditions / boundaries +# +############################################################################### + +boundary_walls_on no +periodicity 1_1_1 + +############################################################################### +# +# Output frequency and type +# +############################################################################### + +freq_statistics 20000 +config_at_end no + +############################################################################### +# +# Miscellaneous +# +############################################################################### + +random_seed 8361235 diff --git a/tests/regression/d3q19/long64-chol-bp2rot.log b/tests/regression/d3q19/long64-chol-bp2rot.log new file mode 100644 index 000000000..8baae6c66 --- /dev/null +++ b/tests/regression/d3q19/long64-chol-bp2rot.log @@ -0,0 +1,160 @@ +Welcome to Ludwig v0.14.0 (MPI version running on 8 processes) +Start time: Wed Oct 27 16:43:26 2021 + +Compiler: + name: Gnu 11.2.0 + version-string: 11.2.0 + +Note assertions via standard C assert() are on. + +Target thread model: None. + +Read 24 user parameters from long64-chol-bp2rot.inp + +System details +-------------- +System size: 32 32 32 +Decomposition: 2 2 2 +Local domain: 16 16 16 +Periodic: 1 1 1 +Halo nhalo: 2 +Reorder: true +Initialised: 1 + +Free energy details +------------------- + +Blue phase free energy selected. + +Liquid crystal blue phase free energy +Bulk parameter A0: = 6.9000000e-03 +Magnitude of order gamma = 3.0000000e+00 +Pitch wavevector q0 = 1.9634950e-01 +... gives pitch length = 3.2000007e+01 +Elastic constant kappa0 = 2.0000000e-02 +Elastic constant kappa1 = 2.0000000e-02 +Amplitude (uniaxial) order = 3.0000000e-01 +Effective aspect ratio xi = 7.0000000e-01 +Chirality = 2.0057255e+00 +Reduced temperature = 0.0000000e+00 +Initial redshift = 9.1000000e-01 +Dynamic redshift update = no +Liquid crystal activity No + +Using Beris-Edwards solver: +Rotational diffusion const = 1.0000000e-01 +LC fluctuations: = off + +System properties +---------------- +Mean fluid density: 1.00000e+00 +Shear viscosity 1.66667e+00 +Bulk viscosity 1.66667e+00 +Temperature 0.00000e+00 +External body force density 0.00000e+00 0.00000e+00 0.00000e+00 +External E-field amplitude 0.00000e+00 0.00000e+00 0.00000e+00 +External E-field frequency 0.00000e+00 +External magnetic field 0.00000e+00 0.00000e+00 0.00000e+00 + +Lattice Boltzmann distributions +------------------------------- +Model: d3q19 +SIMD vector len: 1 +Number of sets: 1 +Halo type: full +Input format: binary +Output format: binary +I/O grid: 1 1 1 + +Lattice Boltzmann collision +--------------------------- +Relaxation time scheme: M10 +Hydrodynamic modes: on +Ghost modes: on +Isothermal fluctuations: off +Shear relaxation time: 5.50000e+00 +Bulk relaxation time: 5.50000e+00 +Ghost relaxation time: 1.00000e+00 +[User ] Random number seed: 8361235 + +Hydrodynamics +------------- +Hydrodynamics: on + +Order parameter I/O +------------------- +Order parameter I/O format: +I/O decomposition: 1 1 1 + +Advection scheme order: 1 (default) +Gradient calculation: 3d_7pt_fluid + + +Initialising Q_ab using rotated O2 (BPII) +Euler angles alpha_z=45, beta_x'=45, gamma_z'=0 +Initial conditions. + +Scalars - total mean variance min max +[rho] 32768.00 1.00000000000 2.2204460e-16 1.00000000000 1.00000000000 +[phi] -1.0206918e-12 -3.1149042e-17 8.4935422e-02 -5.9727840e-01 5.9727840e-01 +[phi] -7.8728135e-12 -2.4025920e-16 4.5000000e-02 -3.0000000e-01 3.0000000e-01 +[phi] -1.4608759e-11 -4.4582393e-16 4.5000000e-02 -3.0000000e-01 3.0000000e-01 +[phi] 4.4785463e+02 1.3667439e-02 9.3490906e-02 -5.9885749e-01 6.0000000e-01 +[phi] 1.2765777e+02 3.8958061e-03 4.4853901e-02 -2.9998998e-01 2.9998998e-01 + +Momentum - x y z +[total ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 +[fluid ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 + +Starting time step loop. + +Scalars - total mean variance min max +[rho] 32768.00 1.00000000000 2.3534397e-10 0.99994882568 1.00004618664 +[phi] -6.1782286e+01 -1.8854457e-03 1.1641226e-02 -1.7865819e-01 3.3310126e-01 +[phi] 1.6566248e+02 5.0556177e-03 1.0451679e-02 -2.4498503e-01 2.5672772e-01 +[phi] -1.2027857e+01 -3.6706108e-04 1.0174710e-02 -2.4772676e-01 2.5529376e-01 +[phi] 3.9270784e+01 1.1984492e-03 1.1978320e-02 -1.7294678e-01 3.4809866e-01 +[phi] 2.5982022e+00 7.9290839e-05 1.0810133e-02 -2.5451840e-01 2.6076295e-01 + +Free energies - timestep f v f/v f_bulk/v f_grad/v redshift +[fe] 20000 -7.0999051989e-01 3.2768000000e+04 -2.1667191159e-05 -3.1595817022e-05 9.9286258634e-06 9.1000000000e-01 + +Momentum - x y z +[total ] 4.6159604e-13 4.8495236e-13 7.4037998e-14 +[fluid ] 4.6159604e-13 4.8495236e-13 7.4037998e-14 + +Velocity - x y z +[minimum ] -1.5631767e-05 -1.5180160e-05 -1.6060168e-05 +[maximum ] 1.2889113e-05 2.0437814e-05 1.3411893e-05 + +Completed cycle 20000 + +Timer resolution: 1e-06 second + +Timer statistics + Section: tmin tmax total + Total: 602.078 602.078 602.078 602.078200 (1 call) + Time step loop: 0.023 0.121 602.025 0.030101 (20000 calls) + Propagation: 0.002 0.013 41.057 0.002053 (20000 calls) + Propagtn (krnl) : 0.002 0.013 40.951 0.002048 (20000 calls) + Collision: 0.004 0.020 95.821 0.004791 (20000 calls) + Collision (krnl) : 0.004 0.020 95.733 0.004787 (20000 calls) + Lattice halos: 0.001 0.032 32.279 0.001614 (20000 calls) + phi gradients: 0.003 0.024 85.017 0.004251 (20000 calls) + phi grad (krnl) : 0.003 0.017 69.708 0.003485 (20000 calls) + phi halos: 0.000 0.017 15.202 0.000760 (20000 calls) + BBL: 0.000 0.000 0.016 0.000001 (20000 calls) + Force calculation: 0.007 0.037 170.190 0.008509 (20000 calls) + Phi force (krnl) : 0.003 0.027 70.392 0.003520 (20000 calls) + phi update: 0.006 0.067 171.798 0.008590 (20000 calls) + Velocity Halo : 0.000 0.045 15.034 0.000752 (20000 calls) +BE mol field (krnl) : 0.002 0.014 42.845 0.002142 (20000 calls) +BP BE update (krnl) : 0.003 0.016 66.731 0.003337 (20000 calls) + Advectn (krnl) : 0.001 0.016 32.028 0.001601 (20000 calls) + Advectn BCS (krnl) : 0.000 0.011 12.049 0.000602 (20000 calls) + Free1: 0.000 0.015 0.027 0.000001 (20000 calls) +Warning: key/value present in input but not used: +(Line 71): boundary_walls_on no + +End time: Wed Oct 27 16:53:28 2021 +Ludwig finished normally. From 2b5ac1a49b1fef1524d5721d379c51984d75e98d Mon Sep 17 00:00:00 2001 From: Oliver Henrich Date: Thu, 28 Oct 2021 15:52:26 +0100 Subject: [PATCH 005/117] Added comment regarding sequence of rotations --- src/blue_phase_init.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/blue_phase_init.c b/src/blue_phase_init.c index 85e2306b5..47531c3c1 100644 --- a/src/blue_phase_init.c +++ b/src/blue_phase_init.c @@ -110,6 +110,11 @@ int blue_phase_O8M_init(cs_t * cs, fe_lc_param_t * param, field_t * fq) { * * Initialisation of a rotated BP I * + * The sequence of rotations follows the standard Euler angles: + * 1) rotation around z-axis obtaining frame x'-y'-z + * 2) rotation around x'-axis obtaining frame x'-y''-z' + * 3) rotation around z'-axis obtaining final reference + * *****************************************************************************/ int blue_phase_O8M_rot_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, const double euler_angles[3]) { @@ -260,6 +265,11 @@ int blue_phase_O2_init(cs_t * cs, fe_lc_param_t * param, field_t * fq) { * * This initialisation is for a rotated BP II. * + * The sequence of rotations follows the standard Euler angles: + * 1) rotation around z-axis obtaining frame x'-y'-z + * 2) rotation around x'-axis obtaining frame x'-y''-z' + * 3) rotation around z'-axis obtaining final reference + * *****************************************************************************/ int blue_phase_O2_rot_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, const double euler_angles[3]) { From 32772c1c808735a0656b5a71cda3708531352ce4 Mon Sep 17 00:00:00 2001 From: Oliver Henrich Date: Thu, 28 Oct 2021 18:58:20 +0100 Subject: [PATCH 006/117] Added more comments regarding rotated BP initialisations --- src/blue_phase_init.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/blue_phase_init.c b/src/blue_phase_init.c index 47531c3c1..02ef785bb 100644 --- a/src/blue_phase_init.c +++ b/src/blue_phase_init.c @@ -113,7 +113,7 @@ int blue_phase_O8M_init(cs_t * cs, fe_lc_param_t * param, field_t * fq) { * The sequence of rotations follows the standard Euler angles: * 1) rotation around z-axis obtaining frame x'-y'-z * 2) rotation around x'-axis obtaining frame x'-y''-z' - * 3) rotation around z'-axis obtaining final reference + * 3) rotation around z'-axis obtaining final frame * *****************************************************************************/ @@ -146,6 +146,8 @@ int blue_phase_O8M_rot_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, cons q0 = param->q0; amplitude0 = param->amplitude0; + /* Set up rotation matrices with negative angles. Clockwise rotation */ + /* of arguments leads to counterclockwise rotation of the Q-tensor. */ blue_phase_M_rot(MZ, 2,-1.0*pi*euler_angles[0]/180.0); blue_phase_M_rot(MXp,0,-1.0*pi*euler_angles[1]/180.0); blue_phase_M_rot(MZp,2,-1.0*pi*euler_angles[2]/180.0); @@ -268,7 +270,7 @@ int blue_phase_O2_init(cs_t * cs, fe_lc_param_t * param, field_t * fq) { * The sequence of rotations follows the standard Euler angles: * 1) rotation around z-axis obtaining frame x'-y'-z * 2) rotation around x'-axis obtaining frame x'-y''-z' - * 3) rotation around z'-axis obtaining final reference + * 3) rotation around z'-axis obtaining final frame * *****************************************************************************/ @@ -299,6 +301,8 @@ int blue_phase_O2_rot_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, const q0 = param->q0; amplitude0 = param->amplitude0; + /* Set up rotation matrices with negative angles. Clockwise rotation */ + /* of arguments leads to counterclockwise rotation of the Q-tensor. */ blue_phase_M_rot(MZ, 2,-1.0*pi*euler_angles[0]/180.0); blue_phase_M_rot(MXp,0,-1.0*pi*euler_angles[1]/180.0); blue_phase_M_rot(MZp,2,-1.0*pi*euler_angles[2]/180.0); From e3810858b2bb490e1dce3dc8e45af65ec3703068 Mon Sep 17 00:00:00 2001 From: Oliver Henrich Date: Thu, 28 Oct 2021 19:08:36 +0100 Subject: [PATCH 007/117] Added separate routines for bulk and gradient contributions to molecular field --- src/blue_phase.c | 183 +++++++++++++++++++++++++++++++++++++++++++++++ src/blue_phase.h | 14 ++++ 2 files changed, 197 insertions(+) diff --git a/src/blue_phase.c b/src/blue_phase.c index c3b0c98ad..c37ed3e14 100644 --- a/src/blue_phase.c +++ b/src/blue_phase.c @@ -716,6 +716,66 @@ __host__ __device__ int fe_lc_mol_field(fe_lc_t * fe, int index, return 0; } +/***************************************************************************** + * + * fe_lc_bulk_mol_field + * + * Return the bulk terms of the molcular field h[3][3] at lattice site index. + * + * Note this is only valid in the one-constant approximation at + * the moment (kappa0 = kappa1 = kappa). + * + *****************************************************************************/ + +__host__ __device__ int fe_lc_bulk_mol_field(fe_lc_t * fe, int index, + double h[3][3]) { + + double q[3][3]; + double dq[3][3][3]; + double dsq[3][3]; + + assert(fe); + assert(fe->param->kappa0 == fe->param->kappa1); /* Exactly */ + + field_tensor(fe->q, index, q); + field_grad_tensor_grad(fe->dq, index, dq); + field_grad_tensor_delsq(fe->dq, index, dsq); + + fe_lc_compute_bulk_h(fe, fe->param->gamma, q, h); + + return 0; +} + +/***************************************************************************** + * + * fe_lc_grad_mol_field + * + * Return the gradient terms of molcular field h[3][3] at lattice site index. + * + * Note this is only valid in the one-constant approximation at + * the moment (kappa0 = kappa1 = kappa). + * + *****************************************************************************/ + +__host__ __device__ int fe_lc_grad_mol_field(fe_lc_t * fe, int index, + double h[3][3]) { + + double q[3][3]; + double dq[3][3][3]; + double dsq[3][3]; + + assert(fe); + assert(fe->param->kappa0 == fe->param->kappa1); /* Exactly */ + + field_tensor(fe->q, index, q); + field_grad_tensor_grad(fe->dq, index, dq); + field_grad_tensor_delsq(fe->dq, index, dsq); + + fe_lc_compute_grad_h(fe, fe->param->gamma, q, dq, dsq, h); + + return 0; +} + /***************************************************************************** * * fe_lc_compute_h @@ -818,6 +878,129 @@ int fe_lc_compute_h(fe_lc_t * fe, double gamma, double q[3][3], return 0; } +/***************************************************************************** + * + * fe_lc_compute_bulk_h + * + * Compute the bulk terms of the molcular field h from q, + * the q gradient tensor dq, and the del^2 q tensor. + * + * NOTE: gamma is potentially gamma(r) so does not come from the + * fe->param + * + *****************************************************************************/ + +__host__ __device__ +int fe_lc_compute_bulk_h(fe_lc_t * fe, double gamma, double q[3][3], + double h[3][3]) { + + int ia, ib, ic, id; + + double q0; /* Redshifted value */ + double kappa1; /* Redshifted value */ + double q2; + double e2; + double eq; + double sum; + const double r3 = (1.0/3.0); + KRONECKER_DELTA_CHAR(d); + LEVI_CIVITA_CHAR(e); + + assert(fe); + + q0 = fe->param->q0*fe->param->rredshift; + kappa1 = fe->param->kappa1*fe->param->redshift*fe->param->redshift; + + /* From the bulk terms in the free energy... */ + + q2 = 0.0; + + for (ia = 0; ia < 3; ia++) { + for (ib = 0; ib < 3; ib++) { + q2 += q[ia][ib]*q[ia][ib]; + } + } + + for (ia = 0; ia < 3; ia++) { + for (ib = 0; ib < 3; ib++) { + sum = 0.0; + for (ic = 0; ic < 3; ic++) { + sum += q[ia][ic]*q[ib][ic]; + } + h[ia][ib] = -fe->param->a0*(1.0 - r3*gamma)*q[ia][ib] + + fe->param->a0*gamma*(sum - r3*q2*d[ia][ib]) + - fe->param->a0*gamma*q2*q[ia][ib] + - 4.0*kappa1*q0*q0*q[ia][ib]; + } + } + + return 0; +} +/***************************************************************************** + * + * fe_lc_compute_grad_h + * + * Compute the gradient terms of the molcular field h from q, + * the q gradient tensor dq, and the del^2 q tensor. + * + * NOTE: gamma is potentially gamma(r) so does not come from the + * fe->param + * + *****************************************************************************/ + +__host__ __device__ +int fe_lc_compute_grad_h(fe_lc_t * fe, double gamma, double q[3][3], + double dq[3][3][3], double dsq[3][3], double h[3][3]) { + + int ia, ib, ic, id; + + double q0; /* Redshifted value */ + double kappa0, kappa1; /* Redshifted values */ + double q2; + double e2; + double eq; + double sum; + const double r3 = (1.0/3.0); + KRONECKER_DELTA_CHAR(d); + LEVI_CIVITA_CHAR(e); + + assert(fe); + + q0 = fe->param->q0*fe->param->rredshift; + kappa0 = fe->param->kappa0*fe->param->redshift*fe->param->redshift; + kappa1 = fe->param->kappa1*fe->param->redshift*fe->param->redshift; + + /* From the gradient terms ... */ + /* First, the sum e_abc d_b Q_ca. With two permutations, we + * may rewrite this as e_bca d_b Q_ca */ + + eq = 0.0; + for (ib = 0; ib < 3; ib++) { + for (ic = 0; ic < 3; ic++) { + for (ia = 0; ia < 3; ia++) { + eq += e[ib][ic][ia]*dq[ib][ic][ia]; + } + } + } + + /* d_c Q_db written as d_c Q_bd etc */ + for (ia = 0; ia < 3; ia++) { + for (ib = 0; ib < 3; ib++) { + sum = 0.0; + for (ic = 0; ic < 3; ic++) { + for (id = 0; id < 3; id++) { + sum += + (e[ia][ic][id]*dq[ic][ib][id] + e[ib][ic][id]*dq[ic][ia][id]); + } + } + h[ia][ib] = kappa0*dsq[ia][ib] + - 2.0*kappa1*q0*sum + 4.0*r3*kappa1*q0*eq*d[ia][ib]; + + } + } + + return 0; +} /***************************************************************************** * diff --git a/src/blue_phase.h b/src/blue_phase.h index 2d47a23ad..888b65bea 100644 --- a/src/blue_phase.h +++ b/src/blue_phase.h @@ -103,6 +103,12 @@ int fe_lc_fed(fe_lc_t * fe, int index, double * fed); __host__ __device__ int fe_lc_mol_field(fe_lc_t * fe, int index, double h[3][3]); +__host__ __device__ +int fe_lc_bulk_mol_field(fe_lc_t * fe, int index, double h[3][3]); + +__host__ __device__ +int fe_lc_grad_mol_field(fe_lc_t * fe, int index, double h[3][3]); + __host__ __device__ int fe_lc_stress(fe_lc_t * fe, int index, double s[3][3]); @@ -120,6 +126,14 @@ __host__ __device__ int fe_lc_compute_h(fe_lc_t * fe, double gaama, double q[3][3], double dq[3][3][3], double dsq[3][3], double h[3][3]); +__host__ __device__ +int fe_lc_compute_bulk_h(fe_lc_t * fe, double gaama, double q[3][3], + double h[3][3]); + +__host__ __device__ +int fe_lc_compute_grad_h(fe_lc_t * fe, double gaama, double q[3][3], + double dq[3][3][3], double dsq[3][3], double h[3][3]); + __host__ __device__ int fe_lc_compute_stress(fe_lc_t * fe, double q[3][3], double dq[3][3][3], double h[3][3], double sth[3][3]); From a87597173b420ed9a765d102d97fd88aa2d54413 Mon Sep 17 00:00:00 2001 From: Oliver Henrich Date: Thu, 28 Oct 2021 19:30:00 +0100 Subject: [PATCH 008/117] Removed unused variables for check --- src/blue_phase.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/blue_phase.c b/src/blue_phase.c index c37ed3e14..468838caa 100644 --- a/src/blue_phase.c +++ b/src/blue_phase.c @@ -894,17 +894,14 @@ __host__ __device__ int fe_lc_compute_bulk_h(fe_lc_t * fe, double gamma, double q[3][3], double h[3][3]) { - int ia, ib, ic, id; + int ia, ib, ic; double q0; /* Redshifted value */ double kappa1; /* Redshifted value */ double q2; - double e2; - double eq; double sum; const double r3 = (1.0/3.0); KRONECKER_DELTA_CHAR(d); - LEVI_CIVITA_CHAR(e); assert(fe); @@ -956,8 +953,6 @@ int fe_lc_compute_grad_h(fe_lc_t * fe, double gamma, double q[3][3], double q0; /* Redshifted value */ double kappa0, kappa1; /* Redshifted values */ - double q2; - double e2; double eq; double sum; const double r3 = (1.0/3.0); From 58e89ce08c31e728571529ae6db8a7ebb6ef7104 Mon Sep 17 00:00:00 2001 From: Oliver Henrich Date: Fri, 29 Oct 2021 12:56:44 +0100 Subject: [PATCH 009/117] Inlined functions for bulk and gradient stress --- src/blue_phase.c | 765 +++++++++++++++++++++++++---------------------- src/blue_phase.h | 15 +- 2 files changed, 405 insertions(+), 375 deletions(-) diff --git a/src/blue_phase.c b/src/blue_phase.c index 468838caa..e443adad5 100644 --- a/src/blue_phase.c +++ b/src/blue_phase.c @@ -443,138 +443,276 @@ __host__ __device__ int fe_lc_stress(fe_lc_t * fe, int index, /***************************************************************************** * - * fe_lc_str_symm + * fe_lc_bulk_stress * - * Symmetric stress. Easier to compute the total, and take off - * the antisymmtric part. + * Return the bulk contribution to the stress sth[3][3] at lattice site index. + * First we determine the bulk contributions to the molecular field and FE. * *****************************************************************************/ -__host__ __device__ int fe_lc_str_symm(fe_lc_t * fe, int index, - double s[3][3]) { +__host__ __device__ int fe_lc_bulk_stress(fe_lc_t * fe, int index, + double sth[3][3]) { + double q[3][3]; double h[3][3]; - double dq[3][3][3]; - double dsq[3][3]; + double qh; + double fed; + double p0; + + double a0, gamma; + double q0; /* Redshifted value */ + double kappa0, kappa1; /* Redshifted value */ + + double q2, q3; + double dq1; + double sum; + const double r3 = (1.0/3.0); + + int ia, ib, ic; + + KRONECKER_DELTA_CHAR(d); assert(fe); + assert(fed); assert(fe->q); - assert(fe->dq); field_tensor(fe->q, index, q); - field_grad_tensor_grad(fe->dq, index, dq); - field_grad_tensor_delsq(fe->dq, index, dsq); - fe_lc_compute_h(fe, fe->param->gamma, q, dq, dsq, h); - fe_lc_compute_stress(fe, q, dq, h, s); + a0 = fe->param->a0; + gamma = fe->param->gamma; + q0 = fe->param->q0*fe->param->rredshift; + kappa0 = fe->param->kappa0*fe->param->redshift*fe->param->redshift; + kappa1 = fe->param->kappa1*fe->param->redshift*fe->param->redshift; - if (fe->param->is_active) { - double dp[3][3]; - double sa[3][3]; - field_grad_vector_grad(fe->dp, index, dp); - fe_lc_compute_stress_active(fe, q, dp, sa); - for (int ia = 0; ia < 3; ia++) { - for (int ib = 0; ib < 3; ib++) { - s[ia][ib] += sa[ia][ib]; + /* bulk contribution to molecular field */ + + q2 = 0.0; + + for (ia = 0; ia < 3; ia++) { + for (ib = 0; ib < 3; ib++) { + q2 += q[ia][ib]*q[ia][ib]; + } + } + + for (ia = 0; ia < 3; ia++) { + for (ib = 0; ib < 3; ib++) { + sum = 0.0; + for (ic = 0; ic < 3; ic++) { + sum += q[ia][ic]*q[ib][ic]; } + h[ia][ib] = -fe->param->a0*(1.0 - r3*gamma)*q[ia][ib] + + fe->param->a0*gamma*(sum - r3*q2*d[ia][ib]) + - fe->param->a0*gamma*q2*q[ia][ib] + - 4.0*kappa1*q0*q0*q[ia][ib]; } } - /* Antisymmetric part is subtracted (added, with the -ve sign) */ + /* bulk contribution to free energy */ - for (int ia = 0; ia < 3; ia++) { - for (int ib = 0; ib < 3; ib++) { - for (int ic = 0; ic < 3; ic++) { - s[ia][ib] += q[ia][ic]*h[ib][ic] - h[ia][ic]*q[ib][ic]; + q2 = 0.0; + + /* Q_ab^2 */ + + for (ia = 0; ia < 3; ia++) { + for (ib = 0; ib < 3; ib++) { + q2 += q[ia][ib]*q[ia][ib]; + } + } + + /* Q_ab Q_bc Q_ca */ + + q3 = 0.0; + + for (ia = 0; ia < 3; ia++) { + for (ib = 0; ib < 3; ib++) { + for (ic = 0; ic < 3; ic++) { + /* We use here the fact that q[ic][ia] = q[ia][ic] */ + q3 += q[ia][ib]*q[ib][ic]*q[ia][ic]; } } } - return 0; -} + /* (2q_0 Q_ab)^2 */ + /* With symmetric Q_db write Q_bd */ -/***************************************************************************** - * - * fe_lc_str_anti - * - * Antisymmetric part of the stress. - * - *****************************************************************************/ + dq1 = 0.0; -__host__ __device__ int fe_lc_str_anti(fe_lc_t * fe, int index, - double s[3][3]) { + for (ia = 0; ia < 3; ia++) { + for (ib = 0; ib < 3; ib++) { + sum = 2.0*q0*q[ia][ib]; + dq1 += sum*sum; + } + } - int ia, ib, ic; - double q[3][3]; - double h[3][3]; - double dq[3][3][3]; - double dsq[3][3]; - assert(fe); - field_tensor(fe->q, index, q); - field_grad_tensor_grad(fe->dq, index, dq); - field_grad_tensor_delsq(fe->dq, index, dsq); + fed = 0.5*a0*(1.0 - r3*gamma)*q2 - r3*a0*gamma*q3 + 0.25*a0*gamma*q2*q2 + + 0.5*kappa1*dq1; - fe_lc_compute_h(fe, fe->param->gamma, q, dq, dsq, h); + /* bulk contribtion to stress using the above contributions */ + + p0 = 0.0 - fed; + + /* The contraction Q_ab H_ab */ + + qh = 0.0; + + for (ia = 0; ia < 3; ia++) { + for (ib = 0; ib < 3; ib++) { + qh += q[ia][ib]*h[ia][ib]; + } + } + + /* The term in the isotropic pressure, plus that in qh */ + + for (ia = 0; ia < 3; ia++) { + for (ib = 0; ib < 3; ib++) { + sth[ia][ib] = -p0*d[ia][ib] + + 2.0*fe->param->xi*(q[ia][ib] + r3*d[ia][ib])*qh; + } + } + + /* Remaining two terms in xi and molecular field */ + + for (ia = 0; ia < 3; ia++) { + for (ib = 0; ib < 3; ib++) { + for (ic = 0; ic < 3; ic++) { + sth[ia][ib] += + -fe->param->xi*h[ia][ic]*(q[ib][ic] + r3*d[ib][ic]) + -fe->param->xi*(q[ia][ic] + r3*d[ia][ic])*h[ib][ic]; + } + } + } /* The antisymmetric piece q_ac h_cb - h_ac q_cb. We can * rewrite it as q_ac h_bc - h_ac q_bc. */ - /* With minus sign */ for (ia = 0; ia < 3; ia++) { for (ib = 0; ib < 3; ib++) { - s[ia][ib] = 0.0; for (ic = 0; ic < 3; ic++) { - s[ia][ib] -= (q[ia][ic]*h[ib][ic] - h[ia][ic]*q[ib][ic]); + sth[ia][ib] += q[ia][ic]*h[ib][ic] - h[ia][ic]*q[ib][ic]; } } } + /* This is the minus sign. */ + + for (ia = 0; ia < 3; ia++) { + for (ib = 0; ib < 3; ib++) { + sth[ia][ib] = -sth[ia][ib]; + } + } + return 0; } /***************************************************************************** * - * fe_lc_compute_stress - * - * Compute the stress as a function of the q tensor, the q tensor - * gradient and the molecular field. + * fe_lc_grad_stress * - * Note the definition here has a minus sign included to allow - * computation of the force as minus the divergence (which often - * appears as plus in the liquid crystal literature). This is a - * separate operation at the end to avoid confusion. + * Return the gradient contribution to the stress sth[3][3] at lattice site index. * *****************************************************************************/ -__host__ __device__ int fe_lc_compute_stress(fe_lc_t * fe, double q[3][3], - double dq[3][3][3], - double h[3][3], - double sth[3][3]) { - int ia, ib, ic, id, ie; - double fed; - double q0; - double kappa0; - double kappa1; +__host__ __device__ int fe_lc_grad_stress(fe_lc_t * fe, int index, + double sth[3][3]) { + double q[3][3]; + double h[3][3]; double qh; + double dq[3][3][3]; + double dsq[3][3]; + double fed; double p0; + + double q0; /* Redshifted value */ + double kappa0, kappa1; /* Redshifted values */ + + double eq; + double dq0, dq1, sum; const double r3 = (1.0/3.0); + + int ia, ib, ic, id, ie; + KRONECKER_DELTA_CHAR(d); LEVI_CIVITA_CHAR(e); assert(fe); + assert(fe->q); + assert(fe->dq); + + field_tensor(fe->q, index, q); + field_grad_tensor_grad(fe->dq, index, dq); + field_grad_tensor_delsq(fe->dq, index, dsq); q0 = fe->param->q0*fe->param->rredshift; kappa0 = fe->param->kappa0*fe->param->redshift*fe->param->redshift; kappa1 = fe->param->kappa1*fe->param->redshift*fe->param->redshift; - /* We have ignored the rho T term at the moment, assumed to be zero - * (in particular, it has no divergence if rho = const). */ + /* gradient contribution to molecular field */ + + eq = 0.0; + for (ib = 0; ib < 3; ib++) { + for (ic = 0; ic < 3; ic++) { + for (ia = 0; ia < 3; ia++) { + eq += e[ib][ic][ia]*dq[ib][ic][ia]; + } + } + } + + /* d_c Q_db written as d_c Q_bd etc */ + for (ia = 0; ia < 3; ia++) { + for (ib = 0; ib < 3; ib++) { + sum = 0.0; + for (ic = 0; ic < 3; ic++) { + for (id = 0; id < 3; id++) { + sum += + (e[ia][ic][id]*dq[ic][ib][id] + e[ib][ic][id]*dq[ic][ia][id]); + } + } + h[ia][ib] = kappa0*dsq[ia][ib] + - 2.0*kappa1*q0*sum + 4.0*r3*kappa1*q0*eq*d[ia][ib]; + + } + } + + /* gradient contribution to free energy */ + + /* (d_b Q_ab)^2 */ + + dq0 = 0.0; + + for (ia = 0; ia < 3; ia++) { + sum = 0.0; + for (ib = 0; ib < 3; ib++) { + sum += dq[ib][ia][ib]; + } + dq0 += sum*sum; + } + + /* (e_acd d_c Q_db + 2q_0 Q_ab)^2 */ + /* With symmetric Q_db write Q_bd */ + + dq1 = 0.0; + + for (ia = 0; ia < 3; ia++) { + for (ib = 0; ib < 3; ib++) { + sum = 0.0; + for (ic = 0; ic < 3; ic++) { + for (id = 0; id < 3; id++) { + sum += e[ia][ic][id]*dq[ic][ib][id]; + } + } + dq1 += sum*sum; + } + } + + fed = 0.5*kappa0*dq0 + 0.5*kappa1*dq1; - fe_lc_compute_fed(fe, fe->param->gamma, q, dq, &fed); p0 = 0.0 - fed; + + /* gradient contribtion to stress using the above contributions */ + /* The contraction Q_ab H_ab */ qh = 0.0; @@ -651,156 +789,122 @@ __host__ __device__ int fe_lc_compute_stress(fe_lc_t * fe, double q[3][3], /***************************************************************************** * - * fe_lc_compute_stress_active + * fe_lc_str_symm * - *****************************************************************************/ - -__host__ __device__ int fe_lc_compute_stress_active(fe_lc_t * fe, - double q[3][3], - double dp[3][3], - double s[3][3]) { - int ia, ib; - KRONECKER_DELTA_CHAR(d); - - /* Previously comment said: -zeta*(q_ab - 1/3 d_ab) - * while code was -zeta*(q[ia][ib] + r3*d[ia][ib]) - * for zeta = zeta1 */ - /* The sign of zeta0 needs to be clarified cf Eq. 36 of notes */ - /* For "backwards compatability" use zeta0 = +1/3 at the moment */ - - for (ia = 0; ia < 3; ia++) { - for (ib = 0; ib < 3; ib++) { - s[ia][ib] = -fe->param->zeta1*(q[ia][ib] + fe->param->zeta0*d[ia][ib]) - - fe->param->zeta2*(dp[ia][ib] + dp[ib][ia]); - } - } - - /* This is an extra minus sign for the divergance. */ - - for (ia = 0; ia < 3; ia++) { - for (ib = 0; ib < 3; ib++) { - s[ia][ib] = -s[ia][ib]; - } - } - - return 0; -} - -/***************************************************************************** - * - * fe_lc_mol_field - * - * Return the molcular field h[3][3] at lattice site index. - * - * Note this is only valid in the one-constant approximation at - * the moment (kappa0 = kappa1 = kappa). + * Symmetric stress. Easier to compute the total, and take off + * the antisymmtric part. * *****************************************************************************/ -__host__ __device__ int fe_lc_mol_field(fe_lc_t * fe, int index, - double h[3][3]) { - +__host__ __device__ int fe_lc_str_symm(fe_lc_t * fe, int index, + double s[3][3]) { double q[3][3]; + double h[3][3]; double dq[3][3][3]; double dsq[3][3]; assert(fe); - assert(fe->param->kappa0 == fe->param->kappa1); /* Exactly */ + assert(fe->q); + assert(fe->dq); field_tensor(fe->q, index, q); field_grad_tensor_grad(fe->dq, index, dq); field_grad_tensor_delsq(fe->dq, index, dsq); fe_lc_compute_h(fe, fe->param->gamma, q, dq, dsq, h); + fe_lc_compute_stress(fe, q, dq, h, s); - return 0; -} - -/***************************************************************************** - * - * fe_lc_bulk_mol_field - * - * Return the bulk terms of the molcular field h[3][3] at lattice site index. - * - * Note this is only valid in the one-constant approximation at - * the moment (kappa0 = kappa1 = kappa). - * - *****************************************************************************/ - -__host__ __device__ int fe_lc_bulk_mol_field(fe_lc_t * fe, int index, - double h[3][3]) { - - double q[3][3]; - double dq[3][3][3]; - double dsq[3][3]; - - assert(fe); - assert(fe->param->kappa0 == fe->param->kappa1); /* Exactly */ + if (fe->param->is_active) { + double dp[3][3]; + double sa[3][3]; + field_grad_vector_grad(fe->dp, index, dp); + fe_lc_compute_stress_active(fe, q, dp, sa); + for (int ia = 0; ia < 3; ia++) { + for (int ib = 0; ib < 3; ib++) { + s[ia][ib] += sa[ia][ib]; + } + } + } - field_tensor(fe->q, index, q); - field_grad_tensor_grad(fe->dq, index, dq); - field_grad_tensor_delsq(fe->dq, index, dsq); + /* Antisymmetric part is subtracted (added, with the -ve sign) */ - fe_lc_compute_bulk_h(fe, fe->param->gamma, q, h); + for (int ia = 0; ia < 3; ia++) { + for (int ib = 0; ib < 3; ib++) { + for (int ic = 0; ic < 3; ic++) { + s[ia][ib] += q[ia][ic]*h[ib][ic] - h[ia][ic]*q[ib][ic]; + } + } + } return 0; } /***************************************************************************** * - * fe_lc_grad_mol_field - * - * Return the gradient terms of molcular field h[3][3] at lattice site index. + * fe_lc_str_anti * - * Note this is only valid in the one-constant approximation at - * the moment (kappa0 = kappa1 = kappa). + * Antisymmetric part of the stress. * *****************************************************************************/ -__host__ __device__ int fe_lc_grad_mol_field(fe_lc_t * fe, int index, - double h[3][3]) { +__host__ __device__ int fe_lc_str_anti(fe_lc_t * fe, int index, + double s[3][3]) { + int ia, ib, ic; double q[3][3]; + double h[3][3]; double dq[3][3][3]; double dsq[3][3]; assert(fe); - assert(fe->param->kappa0 == fe->param->kappa1); /* Exactly */ field_tensor(fe->q, index, q); field_grad_tensor_grad(fe->dq, index, dq); field_grad_tensor_delsq(fe->dq, index, dsq); - fe_lc_compute_grad_h(fe, fe->param->gamma, q, dq, dsq, h); + fe_lc_compute_h(fe, fe->param->gamma, q, dq, dsq, h); + + /* The antisymmetric piece q_ac h_cb - h_ac q_cb. We can + * rewrite it as q_ac h_bc - h_ac q_bc. */ + /* With minus sign */ + + for (ia = 0; ia < 3; ia++) { + for (ib = 0; ib < 3; ib++) { + s[ia][ib] = 0.0; + for (ic = 0; ic < 3; ic++) { + s[ia][ib] -= (q[ia][ic]*h[ib][ic] - h[ia][ic]*q[ib][ic]); + } + } + } return 0; } /***************************************************************************** * - * fe_lc_compute_h + * fe_lc_compute_stress * - * Compute the molcular field h from q, the q gradient tensor dq, and - * the del^2 q tensor. + * Compute the stress as a function of the q tensor, the q tensor + * gradient and the molecular field. * - * NOTE: gamma is potentially gamma(r) so does not come from the - * fe->param + * Note the definition here has a minus sign included to allow + * computation of the force as minus the divergence (which often + * appears as plus in the liquid crystal literature). This is a + * separate operation at the end to avoid confusion. * *****************************************************************************/ -__host__ __device__ -int fe_lc_compute_h(fe_lc_t * fe, double gamma, double q[3][3], - double dq[3][3][3], - double dsq[3][3], double h[3][3]) { - - int ia, ib, ic, id; - - double q0; /* Redshifted value */ - double kappa0, kappa1; /* Redshifted values */ - double q2; - double e2; - double eq; - double sum; +__host__ __device__ int fe_lc_compute_stress(fe_lc_t * fe, double q[3][3], + double dq[3][3][3], + double h[3][3], + double sth[3][3]) { + int ia, ib, ic, id, ie; + double fed; + double q0; + double kappa0; + double kappa1; + double qh; + double p0; const double r3 = (1.0/3.0); KRONECKER_DELTA_CHAR(d); LEVI_CIVITA_CHAR(e); @@ -811,220 +915,191 @@ int fe_lc_compute_h(fe_lc_t * fe, double gamma, double q[3][3], kappa0 = fe->param->kappa0*fe->param->redshift*fe->param->redshift; kappa1 = fe->param->kappa1*fe->param->redshift*fe->param->redshift; - /* From the bulk terms in the free energy... */ + /* We have ignored the rho T term at the moment, assumed to be zero + * (in particular, it has no divergence if rho = const). */ - q2 = 0.0; + fe_lc_compute_fed(fe, fe->param->gamma, q, dq, &fed); + p0 = 0.0 - fed; + + /* The contraction Q_ab H_ab */ + + qh = 0.0; for (ia = 0; ia < 3; ia++) { for (ib = 0; ib < 3; ib++) { - q2 += q[ia][ib]*q[ia][ib]; + qh += q[ia][ib]*h[ia][ib]; } } + /* The term in the isotropic pressure, plus that in qh */ + for (ia = 0; ia < 3; ia++) { for (ib = 0; ib < 3; ib++) { - sum = 0.0; - for (ic = 0; ic < 3; ic++) { - sum += q[ia][ic]*q[ib][ic]; - } - h[ia][ib] = -fe->param->a0*(1.0 - r3*gamma)*q[ia][ib] - + fe->param->a0*gamma*(sum - r3*q2*d[ia][ib]) - - fe->param->a0*gamma*q2*q[ia][ib]; + sth[ia][ib] = -p0*d[ia][ib] + + 2.0*fe->param->xi*(q[ia][ib] + r3*d[ia][ib])*qh; } } - /* From the gradient terms ... */ - /* First, the sum e_abc d_b Q_ca. With two permutations, we - * may rewrite this as e_bca d_b Q_ca */ + /* Remaining two terms in xi and molecular field */ - eq = 0.0; - for (ib = 0; ib < 3; ib++) { - for (ic = 0; ic < 3; ic++) { - for (ia = 0; ia < 3; ia++) { - eq += e[ib][ic][ia]*dq[ib][ic][ia]; + for (ia = 0; ia < 3; ia++) { + for (ib = 0; ib < 3; ib++) { + for (ic = 0; ic < 3; ic++) { + sth[ia][ib] += + -fe->param->xi*h[ia][ic]*(q[ib][ic] + r3*d[ib][ic]) + -fe->param->xi*(q[ia][ic] + r3*d[ia][ic])*h[ib][ic]; } } } - /* d_c Q_db written as d_c Q_bd etc */ + /* Dot product term d_a Q_cd . dF/dQ_cd,b */ + for (ia = 0; ia < 3; ia++) { for (ib = 0; ib < 3; ib++) { - sum = 0.0; + for (ic = 0; ic < 3; ic++) { for (id = 0; id < 3; id++) { - sum += - (e[ia][ic][id]*dq[ic][ib][id] + e[ib][ic][id]*dq[ic][ia][id]); + sth[ia][ib] += + - kappa0*dq[ia][ib][ic]*dq[id][ic][id] + - kappa1*dq[ia][ic][id]*dq[ib][ic][id] + + kappa1*dq[ia][ic][id]*dq[ic][ib][id]; + + for (ie = 0; ie < 3; ie++) { + sth[ia][ib] += + -2.0*kappa1*q0*dq[ia][ic][id]*e[ib][ic][ie]*q[id][ie]; + } } } - h[ia][ib] += kappa0*dsq[ia][ib] - - 2.0*kappa1*q0*sum + 4.0*r3*kappa1*q0*eq*d[ia][ib] - - 4.0*kappa1*q0*q0*q[ia][ib]; } } - /* Electric field term */ + /* The antisymmetric piece q_ac h_cb - h_ac q_cb. We can + * rewrite it as q_ac h_bc - h_ac q_bc. */ - e2 = 0.0; for (ia = 0; ia < 3; ia++) { - e2 += fe->param->e0coswt[ia]*fe->param->e0coswt[ia]; + for (ib = 0; ib < 3; ib++) { + for (ic = 0; ic < 3; ic++) { + sth[ia][ib] += q[ia][ic]*h[ib][ic] - h[ia][ic]*q[ib][ic]; + } + } } + /* This is the minus sign. */ + for (ia = 0; ia < 3; ia++) { for (ib = 0; ib < 3; ib++) { - h[ia][ib] += fe->param->epsilon - *(fe->param->e0coswt[ia]*fe->param->e0coswt[ib] - r3*d[ia][ib]*e2); + sth[ia][ib] = -sth[ia][ib]; } } return 0; } + /***************************************************************************** * - * fe_lc_compute_bulk_h - * - * Compute the bulk terms of the molcular field h from q, - * the q gradient tensor dq, and the del^2 q tensor. - * - * NOTE: gamma is potentially gamma(r) so does not come from the - * fe->param + * fe_lc_compute_stress_active * *****************************************************************************/ -__host__ __device__ -int fe_lc_compute_bulk_h(fe_lc_t * fe, double gamma, double q[3][3], - double h[3][3]) { - - int ia, ib, ic; - - double q0; /* Redshifted value */ - double kappa1; /* Redshifted value */ - double q2; - double sum; - const double r3 = (1.0/3.0); +__host__ __device__ int fe_lc_compute_stress_active(fe_lc_t * fe, + double q[3][3], + double dp[3][3], + double s[3][3]) { + int ia, ib; KRONECKER_DELTA_CHAR(d); - assert(fe); - - q0 = fe->param->q0*fe->param->rredshift; - kappa1 = fe->param->kappa1*fe->param->redshift*fe->param->redshift; - - /* From the bulk terms in the free energy... */ - - q2 = 0.0; + /* Previously comment said: -zeta*(q_ab - 1/3 d_ab) + * while code was -zeta*(q[ia][ib] + r3*d[ia][ib]) + * for zeta = zeta1 */ + /* The sign of zeta0 needs to be clarified cf Eq. 36 of notes */ + /* For "backwards compatability" use zeta0 = +1/3 at the moment */ for (ia = 0; ia < 3; ia++) { for (ib = 0; ib < 3; ib++) { - q2 += q[ia][ib]*q[ia][ib]; + s[ia][ib] = -fe->param->zeta1*(q[ia][ib] + fe->param->zeta0*d[ia][ib]) + - fe->param->zeta2*(dp[ia][ib] + dp[ib][ia]); } } + /* This is an extra minus sign for the divergance. */ + for (ia = 0; ia < 3; ia++) { for (ib = 0; ib < 3; ib++) { - sum = 0.0; - for (ic = 0; ic < 3; ic++) { - sum += q[ia][ic]*q[ib][ic]; - } - h[ia][ib] = -fe->param->a0*(1.0 - r3*gamma)*q[ia][ib] - + fe->param->a0*gamma*(sum - r3*q2*d[ia][ib]) - - fe->param->a0*gamma*q2*q[ia][ib] - - 4.0*kappa1*q0*q0*q[ia][ib]; + s[ia][ib] = -s[ia][ib]; } } return 0; } + /***************************************************************************** * - * fe_lc_compute_grad_h + * fe_lc_mol_field * - * Compute the gradient terms of the molcular field h from q, - * the q gradient tensor dq, and the del^2 q tensor. + * Return the molcular field h[3][3] at lattice site index. * - * NOTE: gamma is potentially gamma(r) so does not come from the - * fe->param + * Note this is only valid in the one-constant approximation at + * the moment (kappa0 = kappa1 = kappa). * *****************************************************************************/ -__host__ __device__ -int fe_lc_compute_grad_h(fe_lc_t * fe, double gamma, double q[3][3], - double dq[3][3][3], double dsq[3][3], double h[3][3]) { - - int ia, ib, ic, id; +__host__ __device__ int fe_lc_mol_field(fe_lc_t * fe, int index, + double h[3][3]) { - double q0; /* Redshifted value */ - double kappa0, kappa1; /* Redshifted values */ - double eq; - double sum; - const double r3 = (1.0/3.0); - KRONECKER_DELTA_CHAR(d); - LEVI_CIVITA_CHAR(e); + double q[3][3]; + double dq[3][3][3]; + double dsq[3][3]; assert(fe); + assert(fe->param->kappa0 == fe->param->kappa1); /* Exactly */ - q0 = fe->param->q0*fe->param->rredshift; - kappa0 = fe->param->kappa0*fe->param->redshift*fe->param->redshift; - kappa1 = fe->param->kappa1*fe->param->redshift*fe->param->redshift; - - /* From the gradient terms ... */ - /* First, the sum e_abc d_b Q_ca. With two permutations, we - * may rewrite this as e_bca d_b Q_ca */ - - eq = 0.0; - for (ib = 0; ib < 3; ib++) { - for (ic = 0; ic < 3; ic++) { - for (ia = 0; ia < 3; ia++) { - eq += e[ib][ic][ia]*dq[ib][ic][ia]; - } - } - } - - /* d_c Q_db written as d_c Q_bd etc */ - for (ia = 0; ia < 3; ia++) { - for (ib = 0; ib < 3; ib++) { - sum = 0.0; - for (ic = 0; ic < 3; ic++) { - for (id = 0; id < 3; id++) { - sum += - (e[ia][ic][id]*dq[ic][ib][id] + e[ib][ic][id]*dq[ic][ia][id]); - } - } - h[ia][ib] = kappa0*dsq[ia][ib] - - 2.0*kappa1*q0*sum + 4.0*r3*kappa1*q0*eq*d[ia][ib]; + field_tensor(fe->q, index, q); + field_grad_tensor_grad(fe->dq, index, dq); + field_grad_tensor_delsq(fe->dq, index, dsq); - } - } + fe_lc_compute_h(fe, fe->param->gamma, q, dq, dsq, h); return 0; } /***************************************************************************** * - * fe_lc_compute_bulk_fed + * fe_lc_compute_h * - * Compute the bulk free energy density as a function of q. + * Compute the molcular field h from q, the q gradient tensor dq, and + * the del^2 q tensor. * - * Note: This function contains also the part quadratic in q - * which is normally part of the gradient free energy. + * NOTE: gamma is potentially gamma(r) so does not come from the + * fe->param * *****************************************************************************/ __host__ __device__ -int fe_lc_compute_bulk_fed(fe_lc_t * fe, double q[3][3], double * fed) { +int fe_lc_compute_h(fe_lc_t * fe, double gamma, double q[3][3], + double dq[3][3][3], + double dsq[3][3], double h[3][3]) { - int ia, ib, ic; - double q0; - double kappa1; - double q2, q3; - const double r3 = 1.0/3.0; + int ia, ib, ic, id; + + double q0; /* Redshifted value */ + double kappa0, kappa1; /* Redshifted values */ + double q2; + double e2; + double eq; + double sum; + const double r3 = (1.0/3.0); + KRONECKER_DELTA_CHAR(d); + LEVI_CIVITA_CHAR(e); assert(fe); q0 = fe->param->q0*fe->param->rredshift; + kappa0 = fe->param->kappa0*fe->param->redshift*fe->param->redshift; kappa1 = fe->param->kappa1*fe->param->redshift*fe->param->redshift; - q2 = 0.0; + /* From the bulk terms in the free energy... */ - /* Q_ab^2 */ + q2 = 0.0; for (ia = 0; ia < 3; ia++) { for (ib = 0; ib < 3; ib++) { @@ -1032,98 +1107,60 @@ int fe_lc_compute_bulk_fed(fe_lc_t * fe, double q[3][3], double * fed) { } } - /* Q_ab Q_bc Q_ca */ - - q3 = 0.0; - for (ia = 0; ia < 3; ia++) { for (ib = 0; ib < 3; ib++) { + sum = 0.0; for (ic = 0; ic < 3; ic++) { - /* We use here the fact that q[ic][ia] = q[ia][ic] */ - q3 += q[ia][ib]*q[ib][ic]*q[ia][ic]; + sum += q[ia][ic]*q[ib][ic]; } + h[ia][ib] = -fe->param->a0*(1.0 - r3*gamma)*q[ia][ib] + + fe->param->a0*gamma*(sum - r3*q2*d[ia][ib]) + - fe->param->a0*gamma*q2*q[ia][ib]; } } - *fed = 0.5*fe->param->a0*(1.0 - r3*fe->param->gamma)*q2 - - r3*fe->param->a0*fe->param->gamma*q3 - + 0.25*fe->param->a0*fe->param->gamma*q2*q2; - - /* Add terms quadratic in q from gradient free energy */ - - *fed += 0.5*kappa1*4.0*q0*q0*q2; - - return 0; -} - -/***************************************************************************** - * - * fe_lc_compute_gradient_fed - * - * Compute the gradient contribution to the free energy density - * as a function of q and the q gradient tensor dq. - * - * Note: The part quadratic in q has been added to the bulk free energy. - * - *****************************************************************************/ - -__host__ __device__ -int fe_lc_compute_gradient_fed(fe_lc_t * fe, double q[3][3], - double dq[3][3][3], double * fed) { - - int ia, ib, ic, id; - double q0; - double kappa0, kappa1; - double dq0, dq1; - double q2; - double sum; - LEVI_CIVITA_CHAR(e); - - assert(fe); - - q0 = fe->param->q0*fe->param->rredshift; - kappa0 = fe->param->kappa0*fe->param->redshift*fe->param->redshift; - kappa1 = fe->param->kappa1*fe->param->redshift*fe->param->redshift; - - /* (d_b Q_ab)^2 */ - - dq0 = 0.0; + /* From the gradient terms ... */ + /* First, the sum e_abc d_b Q_ca. With two permutations, we + * may rewrite this as e_bca d_b Q_ca */ - for (ia = 0; ia < 3; ia++) { - sum = 0.0; - for (ib = 0; ib < 3; ib++) { - sum += dq[ib][ia][ib]; + eq = 0.0; + for (ib = 0; ib < 3; ib++) { + for (ic = 0; ic < 3; ic++) { + for (ia = 0; ia < 3; ia++) { + eq += e[ib][ic][ia]*dq[ib][ic][ia]; + } } - dq0 += sum*sum; } - /* (e_acd d_c Q_db + 2q_0 Q_ab)^2 */ - /* With symmetric Q_db write Q_bd */ - - dq1 = 0.0; - q2 = 0.0; - + /* d_c Q_db written as d_c Q_bd etc */ for (ia = 0; ia < 3; ia++) { for (ib = 0; ib < 3; ib++) { - sum = 0.0; - - q2 += q[ia][ib]*q[ia][ib]; - for (ic = 0; ic < 3; ic++) { for (id = 0; id < 3; id++) { - sum += e[ia][ic][id]*dq[ic][ib][id]; + sum += + (e[ia][ic][id]*dq[ic][ib][id] + e[ib][ic][id]*dq[ic][ia][id]); } } - sum += 2.0*q0*q[ia][ib]; - dq1 += sum*sum; + h[ia][ib] += kappa0*dsq[ia][ib] + - 2.0*kappa1*q0*sum + 4.0*r3*kappa1*q0*eq*d[ia][ib] + - 4.0*kappa1*q0*q0*q[ia][ib]; } } - /* Subtract part that is quadratic in q */ - dq1 -= 4.0*q0*q0*q2; + /* Electric field term */ + + e2 = 0.0; + for (ia = 0; ia < 3; ia++) { + e2 += fe->param->e0coswt[ia]*fe->param->e0coswt[ia]; + } - *fed = 0.5*kappa0*dq0 + 0.5*kappa1*dq1; + for (ia = 0; ia < 3; ia++) { + for (ib = 0; ib < 3; ib++) { + h[ia][ib] += fe->param->epsilon + *(fe->param->e0coswt[ia]*fe->param->e0coswt[ib] - r3*d[ia][ib]*e2); + } + } return 0; } diff --git a/src/blue_phase.h b/src/blue_phase.h index 888b65bea..6c5454874 100644 --- a/src/blue_phase.h +++ b/src/blue_phase.h @@ -104,13 +104,13 @@ __host__ __device__ int fe_lc_mol_field(fe_lc_t * fe, int index, double h[3][3]); __host__ __device__ -int fe_lc_bulk_mol_field(fe_lc_t * fe, int index, double h[3][3]); +int fe_lc_stress(fe_lc_t * fe, int index, double s[3][3]); __host__ __device__ -int fe_lc_grad_mol_field(fe_lc_t * fe, int index, double h[3][3]); +int fe_lc_bulk_stress(fe_lc_t * fe, int index, double s[3][3]); __host__ __device__ -int fe_lc_stress(fe_lc_t * fe, int index, double s[3][3]); +int fe_lc_grad_stress(fe_lc_t * fe, int index, double s[3][3]); __host__ __device__ int fe_lc_str_symm(fe_lc_t * fe, int index, double s[3][3]); @@ -126,17 +126,10 @@ __host__ __device__ int fe_lc_compute_h(fe_lc_t * fe, double gaama, double q[3][3], double dq[3][3][3], double dsq[3][3], double h[3][3]); -__host__ __device__ -int fe_lc_compute_bulk_h(fe_lc_t * fe, double gaama, double q[3][3], - double h[3][3]); - -__host__ __device__ -int fe_lc_compute_grad_h(fe_lc_t * fe, double gaama, double q[3][3], - double dq[3][3][3], double dsq[3][3], double h[3][3]); - __host__ __device__ int fe_lc_compute_stress(fe_lc_t * fe, double q[3][3], double dq[3][3][3], double h[3][3], double sth[3][3]); + __host__ __device__ int fe_lc_compute_stress_active(fe_lc_t * fe, double q[3][3], double dp[3][3], double sa[3][3]); From ec9741350a0a83a0a7219577713392189ba8e4b3 Mon Sep 17 00:00:00 2001 From: Oliver Henrich Date: Fri, 29 Oct 2021 16:43:34 +0100 Subject: [PATCH 010/117] Reinstated accidentially deleted routines --- src/blue_phase.c | 138 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 134 insertions(+), 4 deletions(-) diff --git a/src/blue_phase.c b/src/blue_phase.c index e443adad5..dc8be82dc 100644 --- a/src/blue_phase.c +++ b/src/blue_phase.c @@ -461,7 +461,7 @@ __host__ __device__ int fe_lc_bulk_stress(fe_lc_t * fe, int index, double a0, gamma; double q0; /* Redshifted value */ - double kappa0, kappa1; /* Redshifted value */ + double kappa1; /* Redshifted value */ double q2, q3; double dq1; @@ -481,7 +481,6 @@ __host__ __device__ int fe_lc_bulk_stress(fe_lc_t * fe, int index, a0 = fe->param->a0; gamma = fe->param->gamma; q0 = fe->param->q0*fe->param->rredshift; - kappa0 = fe->param->kappa0*fe->param->redshift*fe->param->redshift; kappa1 = fe->param->kappa1*fe->param->redshift*fe->param->redshift; /* bulk contribution to molecular field */ @@ -544,8 +543,6 @@ __host__ __device__ int fe_lc_bulk_stress(fe_lc_t * fe, int index, } } - - fed = 0.5*a0*(1.0 - r3*gamma)*q2 - r3*a0*gamma*q3 + 0.25*a0*gamma*q2*q2 + 0.5*kappa1*dq1; @@ -650,6 +647,8 @@ __host__ __device__ int fe_lc_grad_stress(fe_lc_t * fe, int index, /* gradient contribution to molecular field */ + /* First, the sum e_abc d_b Q_ca. With two permutations, we + may rewrite this as e_bca d_b Q_ca */ eq = 0.0; for (ib = 0; ib < 3; ib++) { for (ic = 0; ic < 3; ic++) { @@ -1165,6 +1164,137 @@ int fe_lc_compute_h(fe_lc_t * fe, double gamma, double q[3][3], return 0; } +/***************************************************************************** + * + * fe_lc_compute_bulk_fed + * + * Compute the bulk free energy density as a function of q. + * + * Note: This function contains also the part quadratic in q + * which is normally part of the gradient free energy. + * + *****************************************************************************/ + +__host__ __device__ +int fe_lc_compute_bulk_fed(fe_lc_t * fe, double q[3][3], double * fed) { + + int ia, ib, ic; + double q0; + double kappa1; + double q2, q3; + const double r3 = 1.0/3.0; + + assert(fe); + + q0 = fe->param->q0*fe->param->rredshift; + kappa1 = fe->param->kappa1*fe->param->redshift*fe->param->redshift; + + q2 = 0.0; + + /* Q_ab^2 */ + + for (ia = 0; ia < 3; ia++) { + for (ib = 0; ib < 3; ib++) { + q2 += q[ia][ib]*q[ia][ib]; + } + } + + /* Q_ab Q_bc Q_ca */ + + q3 = 0.0; + + for (ia = 0; ia < 3; ia++) { + for (ib = 0; ib < 3; ib++) { + for (ic = 0; ic < 3; ic++) { + /* We use here the fact that q[ic][ia] = q[ia][ic] */ + q3 += q[ia][ib]*q[ib][ic]*q[ia][ic]; + } + } + } + + *fed = 0.5*fe->param->a0*(1.0 - r3*fe->param->gamma)*q2 + - r3*fe->param->a0*fe->param->gamma*q3 + + 0.25*fe->param->a0*fe->param->gamma*q2*q2; + + /* Add terms quadratic in q from gradient free energy */ + + *fed += 0.5*kappa1*4.0*q0*q0*q2; + + return 0; +} + +/***************************************************************************** + * + * fe_lc_compute_gradient_fed + * + * Compute the gradient contribution to the free energy density + * as a function of q and the q gradient tensor dq. + * + * Note: The part quadratic in q has been added to the bulk free energy. + * + *****************************************************************************/ + +__host__ __device__ +int fe_lc_compute_gradient_fed(fe_lc_t * fe, double q[3][3], + double dq[3][3][3], double * fed) { + + int ia, ib, ic, id; + double q0; + double kappa0, kappa1; + double dq0, dq1; + double q2; + double sum; + LEVI_CIVITA_CHAR(e); + + assert(fe); + + q0 = fe->param->q0*fe->param->rredshift; + kappa0 = fe->param->kappa0*fe->param->redshift*fe->param->redshift; + kappa1 = fe->param->kappa1*fe->param->redshift*fe->param->redshift; + + /* (d_b Q_ab)^2 */ + + dq0 = 0.0; + + for (ia = 0; ia < 3; ia++) { + sum = 0.0; + for (ib = 0; ib < 3; ib++) { + sum += dq[ib][ia][ib]; + } + dq0 += sum*sum; + } + + /* (e_acd d_c Q_db + 2q_0 Q_ab)^2 */ + /* With symmetric Q_db write Q_bd */ + + dq1 = 0.0; + q2 = 0.0; + + for (ia = 0; ia < 3; ia++) { + for (ib = 0; ib < 3; ib++) { + + sum = 0.0; + + q2 += q[ia][ib]*q[ia][ib]; + + for (ic = 0; ic < 3; ic++) { + for (id = 0; id < 3; id++) { + sum += e[ia][ic][id]*dq[ic][ib][id]; + } + } + sum += 2.0*q0*q[ia][ib]; + dq1 += sum*sum; + } + } + + /* Subtract part that is quadratic in q */ + dq1 -= 4.0*q0*q0*q2; + + *fed = 0.5*kappa0*dq0 + 0.5*kappa1*dq1; + + return 0; +} + /***************************************************************************** * * fe_lc_chirality From 14a3bc06cd45c649ac3094375d9677280c51d47c Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Mon, 1 Nov 2021 14:26:00 +0000 Subject: [PATCH 011/117] Update to allow default rotation in O8m O2 --- src/blue_phase_init.c | 430 ++++++++++++++++++------------------------ src/blue_phase_init.h | 12 +- src/blue_phase_rt.c | 42 +++-- 3 files changed, 212 insertions(+), 272 deletions(-) diff --git a/src/blue_phase_init.c b/src/blue_phase_init.c index 02ef785bb..c533080d4 100644 --- a/src/blue_phase_init.c +++ b/src/blue_phase_init.c @@ -35,105 +35,37 @@ #define DEFAULT_SEED 13 -void blue_phase_M_rot(double M[3][3], int dim, double alpha); - -/***************************************************************************** - * - * blue_phase_O8M_init - * - * BP I using the current free energy parameter q0 - * - *****************************************************************************/ - -int blue_phase_O8M_init(cs_t * cs, fe_lc_param_t * param, field_t * fq) { - - int ic, jc, kc; - int nlocal[3]; - int noffset[3]; - int index; - - double q[3][3]; - double x, y, z; - double r2; - double cosx, cosy, cosz, sinx, siny, sinz; - double q0; - double amplitude0; - - assert(cs); - assert(fq); - - cs_nlocal(cs, nlocal); - cs_nlocal_offset(cs, noffset); +typedef struct rotation_s { + double m0[3][3]; + double m1[3][3]; + double m2[3][3]; +} rotation_t; - r2 = sqrt(2.0); - q0 = param->q0; - amplitude0 = param->amplitude0; +static int rotation_create(rotation_t * rot, int, int, int, const double a[3]); +static int rotate_inplace(const rotation_t * rot, double r[3]); - for (ic = 1; ic <= nlocal[X]; ic++) { - x = noffset[X] + ic; - for (jc = 1; jc <= nlocal[Y]; jc++) { - y = noffset[Y] + jc; - for (kc = 1; kc <= nlocal[Z]; kc++) { - z = noffset[Z] + kc; - - index = cs_index(cs, ic, jc, kc); - - cosx = cos(r2*q0*x); - cosy = cos(r2*q0*y); - cosz = cos(r2*q0*z); - sinx = sin(r2*q0*x); - siny = sin(r2*q0*y); - sinz = sin(r2*q0*z); - - q[X][X] = amplitude0*(-2.0*cosy*sinz + sinx*cosz + cosx*siny); - q[X][Y] = amplitude0*( r2*cosy*cosz + r2*sinx*sinz - sinx*cosy); - q[X][Z] = amplitude0*( r2*cosx*cosy + r2*sinz*siny - cosx*sinz); - q[Y][X] = q[X][Y]; - q[Y][Y] = amplitude0*(-2.0*sinx*cosz + siny*cosx + cosy*sinz); - q[Y][Z] = amplitude0*( r2*cosz*cosx + r2*siny*sinx - siny*cosz); - q[Z][X] = q[X][Z]; - q[Z][Y] = q[Y][Z]; - q[Z][Z] = - q[X][X] - q[Y][Y]; - - field_tensor_set(fq, index, q); - - } - } - } - - return 0; -} +void blue_phase_M_rot(double M[3][3], int dim, double alpha); /***************************************************************************** * - * blue_phase_O8M_rot_init + * blue_phase_O8M_init * - * Initialisation of a rotated BP I + * Initialisation of BP I * - * The sequence of rotations follows the standard Euler angles: - * 1) rotation around z-axis obtaining frame x'-y'-z - * 2) rotation around x'-axis obtaining frame x'-y''-z' - * 3) rotation around z'-axis obtaining final frame + * An Euler rotation is allowed (a default {0, 0, 0} is 'no action'). + * Input angles are in degrees. * *****************************************************************************/ -int blue_phase_O8M_rot_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, const double euler_angles[3]) { +int blue_phase_O8M_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, + const double euler_angles[3]) { - int ic, jc, kc; int ntotal[3], nlocal[3], noffset[3]; - int index; - double q[3][3]; - double x, y, z; - double r2; - double cosx, cosy, cosz, sinx, siny, sinz; + double root2; double q0; double amplitude0; - - double MZ[3][3], MXp[3][3], MZp[3][3]; - double r[3], r_rot[3]; - int ik, il, im, in; - PI_DOUBLE(pi); + rotation_t rot = {}; assert(cs); assert(fq); @@ -142,62 +74,67 @@ int blue_phase_O8M_rot_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, cons cs_nlocal(cs, nlocal); cs_nlocal_offset(cs, noffset); - r2 = sqrt(2.0); - q0 = param->q0; + root2 = sqrt(2.0); + q0 = param->q0; amplitude0 = param->amplitude0; /* Set up rotation matrices with negative angles. Clockwise rotation */ /* of arguments leads to counterclockwise rotation of the Q-tensor. */ - blue_phase_M_rot(MZ, 2,-1.0*pi*euler_angles[0]/180.0); - blue_phase_M_rot(MXp,0,-1.0*pi*euler_angles[1]/180.0); - blue_phase_M_rot(MZp,2,-1.0*pi*euler_angles[2]/180.0); - - for (ic = 1; ic <= nlocal[X]; ic++) { - x = noffset[X] + ic; - for (jc = 1; jc <= nlocal[Y]; jc++) { - y = noffset[Y] + jc; - for (kc = 1; kc <= nlocal[Z]; kc++) { - z = noffset[Z] + kc; - - r[X] = x - ntotal[X]/2.0; - r[Y] = y - ntotal[Y]/2.0; - r[Z] = z - ntotal[Z]/2.0; - - for(ik=0; ik<3; ik++){ - r_rot[ik] = 0.0; - for(il=0; il<3; il++){ - for(im=0; im<3; im++){ - for(in=0; in<3; in++){ - r_rot[ik] += MZp[ik][il] * MXp[il][im] * MZ[im][in] * r[in]; - } - } - } - } + /* So we add a sign here. */ - r_rot[X] += ntotal[X]/2.0; - r_rot[Y] += ntotal[Y]/2.0; - r_rot[Z] += ntotal[Z]/2.0; + { + double angles[3] = {}; /* radians */ + PI_DOUBLE(pi); - cosx = cos(r2*q0*r_rot[X]); - cosy = cos(r2*q0*r_rot[Y]); - cosz = cos(r2*q0*r_rot[Z]); - sinx = sin(r2*q0*r_rot[X]); - siny = sin(r2*q0*r_rot[Y]); - sinz = sin(r2*q0*r_rot[Z]); + angles[0] = -1.0*pi*euler_angles[0]/180.0; + angles[1] = -1.0*pi*euler_angles[1]/180.0; + angles[2] = -1.0*pi*euler_angles[2]/180.0; - q[X][X] = amplitude0*(-2.0*cosy*sinz + sinx*cosz + cosx*siny); - q[X][Y] = amplitude0*( r2*cosy*cosz + r2*sinx*sinz - sinx*cosy); - q[X][Z] = amplitude0*( r2*cosx*cosy + r2*sinz*siny - cosx*sinz); - q[Y][X] = q[X][Y]; - q[Y][Y] = amplitude0*(-2.0*sinx*cosz + siny*cosx + cosy*sinz); - q[Y][Z] = amplitude0*( r2*cosz*cosx + r2*siny*sinx - siny*cosz); - q[Z][X] = q[X][Z]; - q[Z][Y] = q[Y][Z]; - q[Z][Z] = - q[X][X] - q[Y][Y]; - - index = cs_index(cs, ic, jc, kc); - field_tensor_set(fq, index, q); + rotation_create(&rot, Z, X, Z, angles); + } + for (int ic = 1; ic <= nlocal[X]; ic++) { + double x = noffset[X] + ic; + for (int jc = 1; jc <= nlocal[Y]; jc++) { + double y = noffset[Y] + jc; + for (int kc = 1; kc <= nlocal[Z]; kc++) { + double z = noffset[Z] + kc; + double r[3] = {}; + + /* Rotate around the centre */ + r[X] = x - 0.5*ntotal[X]; + r[Y] = y - 0.5*ntotal[Y]; + r[Z] = z - 0.5*ntotal[Z]; + + rotate_inplace(&rot, r); + + r[X] += 0.5*ntotal[X]; + r[Y] += 0.5*ntotal[Y]; + r[Z] += 0.5*ntotal[Z]; + + { + int index = cs_index(cs, ic, jc, kc); + double cosx = cos(root2*q0*r[X]); + double cosy = cos(root2*q0*r[Y]); + double cosz = cos(root2*q0*r[Z]); + double sinx = sin(root2*q0*r[X]); + double siny = sin(root2*q0*r[Y]); + double sinz = sin(root2*q0*r[Z]); + double q[3][3] = {}; + + q[X][X] = amplitude0*( -2.0*cosy*sinz + sinx*cosz + cosx*siny); + q[X][Y] = amplitude0*(root2*cosy*cosz + root2*sinx*sinz - sinx*cosy); + q[X][Z] = amplitude0*(root2*cosx*cosy + root2*sinz*siny - cosx*sinz); + q[Y][X] = q[X][Y]; + q[Y][Y] = amplitude0*( -2.0*sinx*cosz + siny*cosx + cosy*sinz); + q[Y][Z] = amplitude0*(root2*cosz*cosx + root2*siny*sinx - siny*cosz); + q[Z][X] = q[X][Z]; + q[Z][Y] = q[Y][Z]; + q[Z][Z] = - q[X][X] - q[Y][Y]; + + field_tensor_set(fq, index, q); + } + /* Next site */ } } } @@ -211,85 +148,19 @@ int blue_phase_O8M_rot_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, cons * * This initialisation is for BP II. * - *****************************************************************************/ - -int blue_phase_O2_init(cs_t * cs, fe_lc_param_t * param, field_t * fq) { - - int ic, jc, kc; - int nlocal[3]; - int noffset[3]; - int index; - - double q[3][3]; - double x, y, z; - double q0; - double amplitude0; - - assert(cs); - assert(fq); - - cs_nlocal(cs, nlocal); - cs_nlocal_offset(cs, noffset); - - q0 = param->q0; - amplitude0 = param->amplitude0; - - for (ic = 1; ic <= nlocal[X]; ic++) { - x = noffset[X] + ic; - for (jc = 1; jc <= nlocal[Y]; jc++) { - y = noffset[Y] + jc; - for (kc = 1; kc <= nlocal[Z]; kc++) { - z = noffset[Z] + kc; - - index = cs_index(cs, ic, jc, kc); - - q[X][X] = amplitude0*(cos(2.0*q0*z) - cos(2.0*q0*y)); - q[X][Y] = amplitude0*sin(2.0*q0*z); - q[X][Z] = amplitude0*sin(2.0*q0*y); - q[Y][X] = q[X][Y]; - q[Y][Y] = amplitude0*(cos(2.0*q0*x) - cos(2.0*q0*z)); - q[Y][Z] = amplitude0*sin(2.0*q0*x); - q[Z][X] = q[X][Z]; - q[Z][Y] = q[Y][Z]; - q[Z][Z] = - q[X][X] - q[Y][Y]; - - field_tensor_set(fq, index, q); - } - } - } - - return 0; -} - -/***************************************************************************** - * - * blue_phase_O2_rot_init - * - * This initialisation is for a rotated BP II. - * - * The sequence of rotations follows the standard Euler angles: - * 1) rotation around z-axis obtaining frame x'-y'-z - * 2) rotation around x'-axis obtaining frame x'-y''-z' - * 3) rotation around z'-axis obtaining final frame + * An Euler rotation is allowed (a default {0, 0, 0} is 'no action'). + * Input angles are in degrees. * *****************************************************************************/ -int blue_phase_O2_rot_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, const double euler_angles[3]) { +int blue_phase_O2_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, + const double euler_angles[3]) { - int ic, jc, kc; int ntotal[3], nlocal[3], noffset[3]; - int index; - double q[3][3]; - double x, y, z; - double cosx, cosy, cosz, sinx, siny, sinz; double q0; double amplitude0; - - double MZ[3][3], MXp[3][3], MZp[3][3]; - double r[3], r_rot[3]; - int ik, il, im, in; - PI_DOUBLE(pi); + rotation_t rot = {}; assert(cs); assert(fq); @@ -303,55 +174,60 @@ int blue_phase_O2_rot_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, const /* Set up rotation matrices with negative angles. Clockwise rotation */ /* of arguments leads to counterclockwise rotation of the Q-tensor. */ - blue_phase_M_rot(MZ, 2,-1.0*pi*euler_angles[0]/180.0); - blue_phase_M_rot(MXp,0,-1.0*pi*euler_angles[1]/180.0); - blue_phase_M_rot(MZp,2,-1.0*pi*euler_angles[2]/180.0); - - for (ic = 1; ic <= nlocal[X]; ic++) { - x = noffset[X] + ic; - for (jc = 1; jc <= nlocal[Y]; jc++) { - y = noffset[Y] + jc; - for (kc = 1; kc <= nlocal[Z]; kc++) { - z = noffset[Z] + kc; + /* Hence the factor of -1.0 below. */ - r[X] = x - ntotal[X]/2.0; - r[Y] = y - ntotal[Y]/2.0; - r[Z] = z - ntotal[Z]/2.0; + { + double angles[3] = {}; /* radians */ + PI_DOUBLE(pi); - for(ik=0; ik<3; ik++){ - r_rot[ik] = 0.0; - for(il=0; il<3; il++){ - for(im=0; im<3; im++){ - for(in=0; in<3; in++){ - r_rot[ik] += MZp[ik][il] * MXp[il][im] * MZ[im][in] * r[in]; - } - } - } - } + angles[0] = -1.0*pi*euler_angles[0]/180.0; + angles[1] = -1.0*pi*euler_angles[1]/180.0; + angles[2] = -1.0*pi*euler_angles[2]/180.0; - r_rot[X] += ntotal[X]/2.0; - r_rot[Y] += ntotal[Y]/2.0; - r_rot[Z] += ntotal[Z]/2.0; - - cosx = cos(2.0*q0*r_rot[X]); - cosy = cos(2.0*q0*r_rot[Y]); - cosz = cos(2.0*q0*r_rot[Z]); - sinx = sin(2.0*q0*r_rot[X]); - siny = sin(2.0*q0*r_rot[Y]); - sinz = sin(2.0*q0*r_rot[Z]); - - q[X][X] = amplitude0*(cosz - cosy); - q[X][Y] = amplitude0*sinz; - q[X][Z] = amplitude0*siny; - q[Y][X] = q[X][Y]; - q[Y][Y] = amplitude0*(cosx - cosz); - q[Y][Z] = amplitude0*sinx; - q[Z][X] = q[X][Z]; - q[Z][Y] = q[Y][Z]; - q[Z][Z] = - q[X][X] - q[Y][Y]; + rotation_create(&rot, Z, X, Z, angles); + } - index = cs_index(cs, ic, jc, kc); - field_tensor_set(fq, index, q); + for (int ic = 1; ic <= nlocal[X]; ic++) { + double x = noffset[X] + ic; + for (int jc = 1; jc <= nlocal[Y]; jc++) { + double y = noffset[Y] + jc; + for (int kc = 1; kc <= nlocal[Z]; kc++) { + double z = noffset[Z] + kc; + double r[3] = {}; + + r[X] = x - 0.5*ntotal[X]; + r[Y] = y - 0.5*ntotal[Y]; + r[Z] = z - 0.5*ntotal[Z]; + + rotate_inplace(&rot, r); + + r[X] += 0.5*ntotal[X]; + r[Y] += 0.5*ntotal[Y]; + r[Z] += 0.5*ntotal[Z]; + + { + int index = cs_index(cs, ic, jc, kc); + double cosx = cos(2.0*q0*r[X]); + double cosy = cos(2.0*q0*r[Y]); + double cosz = cos(2.0*q0*r[Z]); + double sinx = sin(2.0*q0*r[X]); + double siny = sin(2.0*q0*r[Y]); + double sinz = sin(2.0*q0*r[Z]); + double q[3][3] = {}; + + q[X][X] = amplitude0*(cosz - cosy); + q[X][Y] = amplitude0*sinz; + q[X][Z] = amplitude0*siny; + q[Y][X] = q[X][Y]; + q[Y][Y] = amplitude0*(cosx - cosz); + q[Y][Z] = amplitude0*sinx; + q[Z][X] = q[X][Z]; + q[Z][Y] = q[Y][Z]; + q[Z][Z] = - q[X][X] - q[Y][Y]; + + field_tensor_set(fq, index, q); + } + /* Next site */ } } } @@ -1436,6 +1312,8 @@ int blue_phase_random_q_rectangle(cs_t * cs, fe_lc_param_t * param, void blue_phase_M_rot(double M[3][3], int dim, double alpha){ + assert(dim == X || dim == Y || dim == Z); + if(dim==0){ M[0][0] = 1.0; M[0][1] = 0.0; @@ -1475,6 +1353,62 @@ void blue_phase_M_rot(double M[3][3], int dim, double alpha){ return; } +/***************************************************************************** + * + * rotation_create + * + * A convenience to help compute a standard Euler-style rotation. + * + * (d0, d1, d2) is a set of coordinate axes e.g., (Z, X, Z), and + * theta are the Euler angles in radians. + * + * The sequence of rotations (Z,X,Z) follows the standard Euler angles: + * 1) rotation around z-axis obtaining frame x'-y'-z + * 2) rotation around x'-axis obtaining frame x'-y''-z' + * 3) rotation around z'-axis obtaining final frame + * + *****************************************************************************/ + +static int rotation_create(rotation_t * rot, int d0, int d1, int d2, + const double theta[3]) { + + assert(rot); + + blue_phase_M_rot(rot->m0, d0, theta[0]); + blue_phase_M_rot(rot->m1, d1, theta[1]); + blue_phase_M_rot(rot->m2, d2, theta[2]); + + return 0; +} + +/***************************************************************************** + * + * rotate_inplace + * + *****************************************************************************/ + +static int rotate_inplace(const rotation_t * rot, double r[3]) { + + double r0[3] = {r[X], r[Y], r[Z]}; + + assert(rot); + + for (int ik = 0; ik < 3; ik++) { + double rrot = 0.0; + for (int il = 0; il < 3; il++) { + for (int im = 0; im < 3; im++) { + for (int in = 0; in < 3; in++) { + rrot += rot->m2[ik][il]*rot->m1[il][im]*rot->m0[im][in]*r0[in]; + } + } + } + r[ik] = rrot; + } + + return 0; +} + + /***************************************************************************** * * blue_phase_cf1_init diff --git a/src/blue_phase_init.h b/src/blue_phase_init.h index 6a1d8d921..a13b71257 100644 --- a/src/blue_phase_init.h +++ b/src/blue_phase_init.h @@ -2,12 +2,10 @@ * * blue_phase_init.h * - * $Id$ - * * Edinburgh Soft Matter and Statistical Physics Group and * Edinburgh Parallel Computing Centre * - * (c) 2010-2017 The University of Edinburgh + * (c) 2010-2021 The University of Edinburgh * * Contributing authors: * Oliver Henrich (o.henrich@ucl.ac.uk) wrote most of these. @@ -21,11 +19,9 @@ #include "blue_phase.h" int blue_phase_twist_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, int helical_axis); -int blue_phase_O8M_init(cs_t * cs, fe_lc_param_t * param, field_t * fq); -int blue_phase_O8M_rot_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, - const double euler_angles[3]); -int blue_phase_O2_init(cs_t * cs, fe_lc_param_t * param, field_t * fq); -int blue_phase_O2_rot_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, +int blue_phase_O8M_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, + const double euler_angle[3]); +int blue_phase_O2_init(cs_t * cs, fe_lc_param_t * param, field_t * fq, const double euler_angles[3]); int blue_phase_O5_init(cs_t * cs, fe_lc_param_t * param, field_t * fq); int blue_phase_H2D_init(cs_t * cs, fe_lc_param_t * param, field_t * fq); diff --git a/src/blue_phase_rt.c b/src/blue_phase_rt.c index 89e0f757d..9c91ebde1 100644 --- a/src/blue_phase_rt.c +++ b/src/blue_phase_rt.c @@ -344,8 +344,6 @@ __host__ int blue_phase_rt_initial_conditions(pe_t * pe, rt_t * rt, cs_t * cs, double nhat[3] = {1.0, 0.0, 0.0}; double nhat2[3] = {64.0, 3.0, 1.0}; - double euler_angles[3] = {0.0, 0.0, 0.0}; - fe_lc_param_t param; fe_lc_param_t * feparam = ¶m; @@ -413,27 +411,39 @@ __host__ int blue_phase_rt_initial_conditions(pe_t * pe, rt_t * rt, cs_t * cs, } if (strcmp(key1, "o8m") == 0) { + + int is_rot = 0; /* Default no rotation. */ + double angles[3] = {0.0, 0.0, 0.0}; /* Default Euler rotation (degrees) */ + pe_info(pe, "Initialising Q_ab using O8M (BPI)\n"); - blue_phase_O8M_init(cs, feparam, q); - } + is_rot = rt_double_parameter_vector(rt, "lc_q_init_euler_angles", angles); + + if (is_rot) { + pe_info(pe, "... initial conidition to be rotated ...\n"); + pe_info(pe, "Euler angle (deg): alpha_z = %14.7e\n", angles[0]); + pe_info(pe, "Euler angle (deg): beta_x' = %14.7e\n", angles[1]); + pe_info(pe, "Euler angle (deg): gamma_z'= %14.7e\n", angles[2]); + } - if (strcmp(key1, "o8m_rot") == 0) { - pe_info(pe, "Initialising Q_ab using rotated O8M (BPI)\n"); - rt_double_parameter_vector(rt, "lc_q_euler_angles", euler_angles); - pe_info(pe, "Euler angles alpha_z=%g, beta_x'=%g, gamma_z'=%g\n", euler_angles[0], euler_angles[1], euler_angles[2]); - blue_phase_O8M_rot_init(cs, feparam, q, euler_angles); + blue_phase_O8M_init(cs, feparam, q, angles); } if (strcmp(key1, "o2") == 0) { + + int is_rot = 0; /* Default no rotation. */ + double angles[3] = {0.0, 0.0, 0.0}; /* Default Euler rotation (degrees) */ + pe_info(pe, "Initialising Q_ab using O2 (BPII)\n"); - blue_phase_O2_init(cs, feparam, q); - } + is_rot = rt_double_parameter_vector(rt, "lc_q_init_euler_angles", angles); + + if (is_rot) { + pe_info(pe, "... initial conidition to be rotated ...\n"); + pe_info(pe, "Euler angle (deg): alpha_z = %14.7e\n", angles[0]); + pe_info(pe, "Euler angle (deg): beta_x' = %14.7e\n", angles[1]); + pe_info(pe, "Euler angle (deg): gamma_z'= %14.7e\n", angles[2]); + } - if (strcmp(key1, "o2_rot") == 0) { - pe_info(pe, "Initialising Q_ab using rotated O2 (BPII)\n"); - rt_double_parameter_vector(rt, "lc_q_euler_angles", euler_angles); - pe_info(pe, "Euler angles alpha_z=%g, beta_x'=%g, gamma_z'=%g\n", euler_angles[0], euler_angles[1], euler_angles[2]); - blue_phase_O2_rot_init(cs, feparam, q, euler_angles); + blue_phase_O2_init(cs, feparam, q, angles); } if (strcmp(key1, "o5") == 0) { From bd879811059c894d8c3a2a97b01be7252b725c27 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Mon, 1 Nov 2021 14:26:58 +0000 Subject: [PATCH 012/117] Add default rotation in O8m test --- tests/unit/test_blue_phase.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/unit/test_blue_phase.c b/tests/unit/test_blue_phase.c index 7482ca5e4..2854a73d7 100644 --- a/tests/unit/test_blue_phase.c +++ b/tests/unit/test_blue_phase.c @@ -243,7 +243,10 @@ int test_o8m_struct(pe_t * pe, cs_t * cs, lees_edw_t * le, fe_lc_t * fe, * Note there are a limited number of unique order parameter values, * so an exhaustive test is probably not worth while. */ - blue_phase_O8M_init(cs, ¶m, fq); + { + double angles[3] = {}; /* No rotation. */ + blue_phase_O8M_init(cs, ¶m, fq, angles); + } ic = 1; jc = 1; From 60e83aabba7ce44cd54085290816c2f0d36e8ab9 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Mon, 1 Nov 2021 14:27:44 +0000 Subject: [PATCH 013/117] Add default rotation in O8m and O2 --- CHANGES.md | 3 + .../serial-init-br1.inp} | 23 +-- .../d3q19-short/serial-init-br1.log | 160 ++++++++++++++++++ .../serial-init-br2.inp} | 21 +-- .../d3q19-short/serial-init-br2.log | 160 ++++++++++++++++++ tests/regression/d3q19/long64-chol-bp1rot.log | 109 ------------ tests/regression/d3q19/long64-chol-bp2rot.log | 160 ------------------ 7 files changed, 346 insertions(+), 290 deletions(-) rename tests/regression/{d3q19/long64-chol-bp1rot.inp => d3q19-short/serial-init-br1.inp} (84%) create mode 100644 tests/regression/d3q19-short/serial-init-br1.log rename tests/regression/{d3q19/long64-chol-bp2rot.inp => d3q19-short/serial-init-br2.inp} (85%) create mode 100644 tests/regression/d3q19-short/serial-init-br2.log delete mode 100644 tests/regression/d3q19/long64-chol-bp1rot.log delete mode 100644 tests/regression/d3q19/long64-chol-bp2rot.log diff --git a/CHANGES.md b/CHANGES.md index 6c885a6a3..04b787224 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,9 @@ ### Changes +version 0.15.0 +- Add ability to rotate BPI and BPII liquid crystal initial conditions + Thanks to Oliver H. for this. See Section 3 of web documentation. version 0.14.0 diff --git a/tests/regression/d3q19/long64-chol-bp1rot.inp b/tests/regression/d3q19-short/serial-init-br1.inp similarity index 84% rename from tests/regression/d3q19/long64-chol-bp1rot.inp rename to tests/regression/d3q19-short/serial-init-br1.inp index 88b066fc3..11f240eb1 100644 --- a/tests/regression/d3q19/long64-chol-bp1rot.inp +++ b/tests/regression/d3q19-short/serial-init-br1.inp @@ -1,11 +1,11 @@ ############################################################################## # -# BPI test. -# Following initialisation in serial-init-bp1.inp with different orientation +# BPI initialisation smoke test cf. serial-init-bp1.inp. +# This one has a rotation of the initial conditions. # ############################################################################## -N_cycles 20000 +N_cycles 1 ############################################################################## # @@ -45,14 +45,14 @@ lc_q0 0.27768018 lc_kappa0 0.01 lc_kappa1 0.01 -lc_xi 0.7 +lc_xi 0.7 lc_Gamma 0.1 -lc_q_initialisation o8m_rot -lc_q_euler_angles 90_0_0 -lc_q_init_amplitude -0.2 -lc_init_redshift 0.83 -lc_anchoring_method none +lc_q_initialisation o8m +lc_q_init_euler_angles 90_0_0 +lc_q_init_amplitude -0.2 +lc_init_redshift 0.83 +lc_anchoring_method none ############################################################################### # @@ -68,7 +68,6 @@ colloid_init no_colloids # ############################################################################### -boundary_walls_on no periodicity 1_1_1 ############################################################################### @@ -77,13 +76,15 @@ periodicity 1_1_1 # ############################################################################### -freq_statistics 20000 +freq_statistics 1 config_at_end no ############################################################################### # # Miscellaneous # +# random_seed +ve integer is the random number generator seed +# ############################################################################### random_seed 8361235 diff --git a/tests/regression/d3q19-short/serial-init-br1.log b/tests/regression/d3q19-short/serial-init-br1.log new file mode 100644 index 000000000..d604da5d3 --- /dev/null +++ b/tests/regression/d3q19-short/serial-init-br1.log @@ -0,0 +1,160 @@ +Welcome to Ludwig v0.14.0 (Serial version running on 1 process) +Start time: Fri Oct 29 12:10:32 2021 + +Compiler: + name: Gnu 8.3.0 + version-string: 8.3.0 + +Note assertions via standard C assert() are on. + +Target thread model: None. + +Read 23 user parameters from serial-init-br1.inp + +System details +-------------- +System size: 32 32 32 +Decomposition: 1 1 1 +Local domain: 32 32 32 +Periodic: 1 1 1 +Halo nhalo: 2 +Reorder: true +Initialised: 1 + +Free energy details +------------------- + +Blue phase free energy selected. + +Liquid crystal blue phase free energy +Bulk parameter A0: = 1.4384711e-02 +Magnitude of order gamma = 3.1764706e+00 +Pitch wavevector q0 = 2.7768018e-01 +... gives pitch length = 2.2627417e+01 +Elastic constant kappa0 = 1.0000000e-02 +Elastic constant kappa1 = 1.0000000e-02 +Amplitude (uniaxial) order = -2.0000000e-01 +Effective aspect ratio xi = 7.0000000e-01 +Chirality = 1.3500000e+00 +Reduced temperature = -5.0000003e-01 +Initial redshift = 8.3000000e-01 +Dynamic redshift update = no +Liquid crystal activity No + +Using Beris-Edwards solver: +Rotational diffusion const = 1.0000000e-01 +LC fluctuations: = off + +System properties +---------------- +Mean fluid density: 1.00000e+00 +Shear viscosity 1.66667e+00 +Bulk viscosity 1.66667e+00 +Temperature 0.00000e+00 +External body force density 0.00000e+00 0.00000e+00 0.00000e+00 +External E-field amplitude 0.00000e+00 0.00000e+00 0.00000e+00 +External E-field frequency 0.00000e+00 +External magnetic field 0.00000e+00 0.00000e+00 0.00000e+00 + +Lattice Boltzmann distributions +------------------------------- +Model: d3q19 +SIMD vector len: 1 +Number of sets: 1 +Halo type: full +Input format: binary +Output format: binary +I/O grid: 1 1 1 + +Lattice Boltzmann collision +--------------------------- +Relaxation time scheme: M10 +Hydrodynamic modes: on +Ghost modes: on +Isothermal fluctuations: off +Shear relaxation time: 5.50000e+00 +Bulk relaxation time: 5.50000e+00 +Ghost relaxation time: 1.00000e+00 +[User ] Random number seed: 8361235 + +Hydrodynamics +------------- +Hydrodynamics: on + +Order parameter I/O +------------------- +Order parameter I/O format: +I/O decomposition: 1 1 1 + +Advection scheme order: 1 (default) +Gradient calculation: 3d_7pt_fluid + + +Initialising Q_ab using O8M (BPI) +... initial conidition to be rotated ... +Euler angle (deg): alpha_z = 9.0000000e+01 +Euler angle (deg): beta_x' = 0.0000000e+00 +Euler angle (deg): gamma_z'= 0.0000000e+00 +Initial conditions. + +Scalars - total mean variance min max +[rho] 32768.00 1.00000000000 2.2204460e-16 1.00000000000 1.00000000000 +[phi] 3.8245084e-13 1.1671473e-17 6.0000000e-02 -4.4966058e-01 4.4966058e-01 +[phi] -1.2562174e-12 -3.8336711e-17 5.0000000e-02 -6.0000000e-01 6.0000000e-01 +[phi] -1.2730927e-12 -3.8851707e-17 5.0000000e-02 -6.0000000e-01 6.0000000e-01 +[phi] 4.1466119e-13 1.2654455e-17 6.0000000e-02 -4.4966058e-01 4.4966058e-01 +[phi] -1.5174528e-12 -4.6308985e-17 5.0000000e-02 -6.0000000e-01 6.0000000e-01 + +Momentum - x y z +[total ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 +[fluid ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 + +Starting time step loop. + +Scalars - total mean variance min max +[rho] 32768.00 1.00000000000 1.9600713e-05 0.98788823843 1.01290514128 +[phi] 4.5462961e-13 1.3874195e-17 5.9669179e-02 -4.4806490e-01 4.4918683e-01 +[phi] 6.9706253e-08 2.1272660e-12 4.9602643e-02 -5.9681120e-01 5.9681120e-01 +[phi] -6.9708854e-08 -2.1273454e-12 4.9582755e-02 -5.9673636e-01 5.9673636e-01 +[phi] 2.5597693e-13 7.8117961e-18 5.9669179e-02 -4.4806490e-01 4.4918683e-01 +[phi] 6.9705961e-08 2.1272571e-12 4.9582755e-02 -5.9673636e-01 5.9673636e-01 + +Free energies - timestep f v f/v f_bulk/v f_grad/v redshift +[fe] 1 1.6108165051e+02 3.2768000000e+04 4.9158218539e-03 4.0945666196e-03 8.2125523425e-04 8.3000000000e-01 + +Momentum - x y z +[total ] 4.5535797e-13 5.3429483e-16 -3.4659775e-15 +[fluid ] 4.5535797e-13 5.3429483e-16 -3.4659775e-15 + +Velocity - x y z +[minimum ] -1.3350321e-02 -1.3350321e-02 -9.6833791e-03 +[maximum ] 1.3350322e-02 1.3350321e-02 7.4198427e-03 + +Completed cycle 1 + +Timer resolution: 1e-06 second + +Timer statistics + Section: tmin tmax total + Total: 0.219 0.219 0.219 0.219361 (1 call) + Time step loop: 0.136 0.136 0.136 0.135960 (1 call) + Propagation: 0.009 0.009 0.009 0.009391 (1 call) + Propagtn (krnl) : 0.009 0.009 0.009 0.009379 (1 call) + Collision: 0.023 0.023 0.023 0.022603 (1 call) + Collision (krnl) : 0.023 0.023 0.023 0.022579 (1 call) + Lattice halos: 0.003 0.003 0.003 0.003306 (1 call) + phi gradients: 0.019 0.019 0.019 0.018722 (1 call) + phi grad (krnl) : 0.017 0.017 0.017 0.016848 (1 call) + phi halos: 0.002 0.002 0.002 0.001858 (1 call) + BBL: 0.000 0.000 0.000 0.000007 (1 call) + Force calculation: 0.039 0.039 0.039 0.038621 (1 call) + Phi force (krnl) : 0.016 0.016 0.016 0.015754 (1 call) + phi update: 0.042 0.042 0.042 0.042371 (1 call) + Velocity Halo : 0.001 0.001 0.001 0.000631 (1 call) +BE mol field (krnl) : 0.010 0.010 0.010 0.009797 (1 call) +BP BE update (krnl) : 0.017 0.017 0.017 0.017342 (1 call) + Advectn (krnl) : 0.011 0.011 0.011 0.010812 (1 call) + Advectn BCS (krnl) : 0.003 0.003 0.003 0.002966 (1 call) + Free1: 0.043 0.043 0.043 0.042553 (1 call) +End time: Fri Oct 29 12:10:32 2021 +Ludwig finished normally. diff --git a/tests/regression/d3q19/long64-chol-bp2rot.inp b/tests/regression/d3q19-short/serial-init-br2.inp similarity index 85% rename from tests/regression/d3q19/long64-chol-bp2rot.inp rename to tests/regression/d3q19-short/serial-init-br2.inp index eaee7e54e..09f7816eb 100644 --- a/tests/regression/d3q19/long64-chol-bp2rot.inp +++ b/tests/regression/d3q19-short/serial-init-br2.inp @@ -1,11 +1,11 @@ ############################################################################## # -# BPII test -# Following initialisation of serial-init-bp2.inp with different orientation +# BPII initialisation smoke test cf serial-init-bp2.inp. +# This one has a rotation. # ############################################################################## -N_cycles 20000 +N_cycles 1 ############################################################################## # @@ -48,11 +48,11 @@ lc_kappa1 0.02 lc_xi 0.7 lc_Gamma 0.1 -lc_q_initialisation o2_rot -lc_q_euler_angles 45_45_0 -lc_q_init_amplitude 0.3 -lc_init_redshift 0.91 -lc_anchoring_method none +lc_q_initialisation o2 +lc_q_init_euler_angles 45_45_0 +lc_q_init_amplitude 0.3 +lc_init_redshift 0.91 +lc_anchoring_method none ############################################################################### # @@ -68,7 +68,6 @@ colloid_init no_colloids # ############################################################################### -boundary_walls_on no periodicity 1_1_1 ############################################################################### @@ -77,13 +76,15 @@ periodicity 1_1_1 # ############################################################################### -freq_statistics 20000 +freq_statistics 1 config_at_end no ############################################################################### # # Miscellaneous # +# random_seed +ve integer is the random number generator seed +# ############################################################################### random_seed 8361235 diff --git a/tests/regression/d3q19-short/serial-init-br2.log b/tests/regression/d3q19-short/serial-init-br2.log new file mode 100644 index 000000000..ad1ea27fc --- /dev/null +++ b/tests/regression/d3q19-short/serial-init-br2.log @@ -0,0 +1,160 @@ +Welcome to Ludwig v0.14.0 (Serial version running on 1 process) +Start time: Fri Oct 29 12:10:43 2021 + +Compiler: + name: Gnu 8.3.0 + version-string: 8.3.0 + +Note assertions via standard C assert() are on. + +Target thread model: None. + +Read 23 user parameters from serial-init-br2.inp + +System details +-------------- +System size: 32 32 32 +Decomposition: 1 1 1 +Local domain: 32 32 32 +Periodic: 1 1 1 +Halo nhalo: 2 +Reorder: true +Initialised: 1 + +Free energy details +------------------- + +Blue phase free energy selected. + +Liquid crystal blue phase free energy +Bulk parameter A0: = 6.9000000e-03 +Magnitude of order gamma = 3.0000000e+00 +Pitch wavevector q0 = 1.9634950e-01 +... gives pitch length = 3.2000007e+01 +Elastic constant kappa0 = 2.0000000e-02 +Elastic constant kappa1 = 2.0000000e-02 +Amplitude (uniaxial) order = 3.0000000e-01 +Effective aspect ratio xi = 7.0000000e-01 +Chirality = 2.0057255e+00 +Reduced temperature = 0.0000000e+00 +Initial redshift = 9.1000000e-01 +Dynamic redshift update = no +Liquid crystal activity No + +Using Beris-Edwards solver: +Rotational diffusion const = 1.0000000e-01 +LC fluctuations: = off + +System properties +---------------- +Mean fluid density: 1.00000e+00 +Shear viscosity 1.66667e+00 +Bulk viscosity 1.66667e+00 +Temperature 0.00000e+00 +External body force density 0.00000e+00 0.00000e+00 0.00000e+00 +External E-field amplitude 0.00000e+00 0.00000e+00 0.00000e+00 +External E-field frequency 0.00000e+00 +External magnetic field 0.00000e+00 0.00000e+00 0.00000e+00 + +Lattice Boltzmann distributions +------------------------------- +Model: d3q19 +SIMD vector len: 1 +Number of sets: 1 +Halo type: full +Input format: binary +Output format: binary +I/O grid: 1 1 1 + +Lattice Boltzmann collision +--------------------------- +Relaxation time scheme: M10 +Hydrodynamic modes: on +Ghost modes: on +Isothermal fluctuations: off +Shear relaxation time: 5.50000e+00 +Bulk relaxation time: 5.50000e+00 +Ghost relaxation time: 1.00000e+00 +[User ] Random number seed: 8361235 + +Hydrodynamics +------------- +Hydrodynamics: on + +Order parameter I/O +------------------- +Order parameter I/O format: +I/O decomposition: 1 1 1 + +Advection scheme order: 1 (default) +Gradient calculation: 3d_7pt_fluid + + +Initialising Q_ab using O2 (BPII) +... initial conidition to be rotated ... +Euler angle (deg): alpha_z = 4.5000000e+01 +Euler angle (deg): beta_x' = 4.5000000e+01 +Euler angle (deg): gamma_z'= 0.0000000e+00 +Initial conditions. + +Scalars - total mean variance min max +[rho] 32768.00 1.00000000000 2.2204460e-16 1.00000000000 1.00000000000 +[phi] -1.3851975e-13 -4.2272873e-18 8.4935422e-02 -5.9727840e-01 5.9727840e-01 +[phi] -1.3067714e-11 -3.9879497e-16 4.5000000e-02 -3.0000000e-01 3.0000000e-01 +[phi] -1.2947032e-11 -3.9511207e-16 4.5000000e-02 -3.0000000e-01 3.0000000e-01 +[phi] 4.4785463e+02 1.3667439e-02 9.3490906e-02 -5.9885749e-01 6.0000000e-01 +[phi] 1.2765777e+02 3.8958061e-03 4.4853901e-02 -2.9998998e-01 2.9998998e-01 + +Momentum - x y z +[total ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 +[fluid ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 + +Starting time step loop. + +Scalars - total mean variance min max +[rho] 32768.00 1.00000000000 3.8979679e-06 0.98299322236 1.01391118276 +[phi] -3.8940439e-01 -1.1883679e-05 8.4610481e-02 -5.9600835e-01 5.9650065e-01 +[phi] -7.0577555e-02 -2.1538561e-06 4.4866057e-02 -2.9998132e-01 3.0012729e-01 +[phi] 6.0960252e-02 1.8603593e-06 4.4854191e-02 -3.0000642e-01 3.0002493e-01 +[phi] 4.4732927e+02 1.3651406e-02 9.3163565e-02 -5.9761655e-01 5.9925183e-01 +[phi] 1.2727955e+02 3.8842637e-03 4.4701851e-02 -2.9999229e-01 2.9998792e-01 + +Free energies - timestep f v f/v f_bulk/v f_grad/v redshift +[fe] 1 8.3793580224e+01 3.2768000000e+04 2.5571771309e-03 1.6391228183e-03 9.1805431254e-04 9.1000000000e-01 + +Momentum - x y z +[total ] 4.5769985e-13 -7.8409501e-16 4.2084392e-15 +[fluid ] 4.5769985e-13 -7.8409501e-16 4.2084392e-15 + +Velocity - x y z +[minimum ] -8.3905474e-03 -9.0143097e-03 -9.0558638e-03 +[maximum ] 6.4092900e-03 7.7405287e-03 9.1606798e-03 + +Completed cycle 1 + +Timer resolution: 1e-06 second + +Timer statistics + Section: tmin tmax total + Total: 0.221 0.221 0.221 0.221410 (1 call) + Time step loop: 0.137 0.137 0.137 0.137002 (1 call) + Propagation: 0.010 0.010 0.010 0.009819 (1 call) + Propagtn (krnl) : 0.010 0.010 0.010 0.009808 (1 call) + Collision: 0.023 0.023 0.023 0.022891 (1 call) + Collision (krnl) : 0.023 0.023 0.023 0.022867 (1 call) + Lattice halos: 0.004 0.004 0.004 0.003701 (1 call) + phi gradients: 0.019 0.019 0.019 0.018515 (1 call) + phi grad (krnl) : 0.017 0.017 0.017 0.016805 (1 call) + phi halos: 0.002 0.002 0.002 0.001697 (1 call) + BBL: 0.000 0.000 0.000 0.000006 (1 call) + Force calculation: 0.039 0.039 0.039 0.038795 (1 call) + Phi force (krnl) : 0.016 0.016 0.016 0.015750 (1 call) + phi update: 0.042 0.042 0.042 0.042330 (1 call) + Velocity Halo : 0.001 0.001 0.001 0.000590 (1 call) +BE mol field (krnl) : 0.010 0.010 0.010 0.010011 (1 call) +BP BE update (krnl) : 0.017 0.017 0.017 0.017237 (1 call) + Advectn (krnl) : 0.011 0.011 0.011 0.010605 (1 call) + Advectn BCS (krnl) : 0.003 0.003 0.003 0.003061 (1 call) + Free1: 0.042 0.042 0.042 0.042415 (1 call) +End time: Fri Oct 29 12:10:43 2021 +Ludwig finished normally. diff --git a/tests/regression/d3q19/long64-chol-bp1rot.log b/tests/regression/d3q19/long64-chol-bp1rot.log deleted file mode 100644 index 9a6a20cee..000000000 --- a/tests/regression/d3q19/long64-chol-bp1rot.log +++ /dev/null @@ -1,109 +0,0 @@ -Welcome to Ludwig v0.14.0 (MPI version running on 8 processes) -Start time: Wed Oct 27 16:36:54 2021 - -Compiler: - name: Gnu 11.2.0 - version-string: 11.2.0 - -Note assertions via standard C assert() are on. - -Target thread model: None. - -Read 24 user parameters from long64-chol-bp1rot.inp - -System details --------------- -System size: 32 32 32 -Decomposition: 2 2 2 -Local domain: 16 16 16 -Periodic: 1 1 1 -Halo nhalo: 2 -Reorder: true -Initialised: 1 - -Free energy details -------------------- - -Blue phase free energy selected. - -Liquid crystal blue phase free energy -Bulk parameter A0: = 1.4384711e-02 -Magnitude of order gamma = 3.1764706e+00 -Pitch wavevector q0 = 2.7768018e-01 -... gives pitch length = 2.2627417e+01 -Elastic constant kappa0 = 1.0000000e-02 -Elastic constant kappa1 = 1.0000000e-02 -Amplitude (uniaxial) order = -2.0000000e-01 -Effective aspect ratio xi = 7.0000000e-01 -Chirality = 1.3500000e+00 -Reduced temperature = -5.0000003e-01 -Initial redshift = 8.3000000e-01 -Dynamic redshift update = no -Liquid crystal activity No - -Using Beris-Edwards solver: -Rotational diffusion const = 1.0000000e-01 -LC fluctuations: = off - -System properties ----------------- -Mean fluid density: 1.00000e+00 -Shear viscosity 1.66667e+00 -Bulk viscosity 1.66667e+00 -Temperature 0.00000e+00 -External body force density 0.00000e+00 0.00000e+00 0.00000e+00 -External E-field amplitude 0.00000e+00 0.00000e+00 0.00000e+00 -External E-field frequency 0.00000e+00 -External magnetic field 0.00000e+00 0.00000e+00 0.00000e+00 - -Lattice Boltzmann distributions -------------------------------- -Model: d3q19 -SIMD vector len: 1 -Number of sets: 1 -Halo type: full -Input format: binary -Output format: binary -I/O grid: 1 1 1 - -Lattice Boltzmann collision ---------------------------- -Relaxation time scheme: M10 -Hydrodynamic modes: on -Ghost modes: on -Isothermal fluctuations: off -Shear relaxation time: 5.50000e+00 -Bulk relaxation time: 5.50000e+00 -Ghost relaxation time: 1.00000e+00 -[User ] Random number seed: 8361235 - -Hydrodynamics -------------- -Hydrodynamics: on - -Order parameter I/O -------------------- -Order parameter I/O format: -I/O decomposition: 1 1 1 - -Advection scheme order: 1 (default) -Gradient calculation: 3d_7pt_fluid - - -Initialising Q_ab using rotated O8M (BPI) -Euler angles alpha_z=90, beta_x'=0, gamma_z'=0 -Initial conditions. - -Scalars - total mean variance min max -[rho] 32768.00 1.00000000000 2.2204460e-16 1.00000000000 1.00000000000 -[phi] 4.1905445e-13 1.2788527e-17 6.0000000e-02 -4.4966058e-01 4.4966058e-01 -[phi] -1.3582468e-12 -4.1450404e-17 5.0000000e-02 -6.0000000e-01 6.0000000e-01 -[phi] -1.1957657e-12 -3.6491873e-17 5.0000000e-02 -6.0000000e-01 6.0000000e-01 -[phi] 3.9868186e-13 1.2166805e-17 6.0000000e-02 -4.4966058e-01 4.4966058e-01 -[phi] -1.7553736e-12 -5.3569752e-17 5.0000000e-02 -6.0000000e-01 6.0000000e-01 - -Momentum - x y z -[total ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 -[fluid ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 - -Starting time step loop. diff --git a/tests/regression/d3q19/long64-chol-bp2rot.log b/tests/regression/d3q19/long64-chol-bp2rot.log deleted file mode 100644 index 8baae6c66..000000000 --- a/tests/regression/d3q19/long64-chol-bp2rot.log +++ /dev/null @@ -1,160 +0,0 @@ -Welcome to Ludwig v0.14.0 (MPI version running on 8 processes) -Start time: Wed Oct 27 16:43:26 2021 - -Compiler: - name: Gnu 11.2.0 - version-string: 11.2.0 - -Note assertions via standard C assert() are on. - -Target thread model: None. - -Read 24 user parameters from long64-chol-bp2rot.inp - -System details --------------- -System size: 32 32 32 -Decomposition: 2 2 2 -Local domain: 16 16 16 -Periodic: 1 1 1 -Halo nhalo: 2 -Reorder: true -Initialised: 1 - -Free energy details -------------------- - -Blue phase free energy selected. - -Liquid crystal blue phase free energy -Bulk parameter A0: = 6.9000000e-03 -Magnitude of order gamma = 3.0000000e+00 -Pitch wavevector q0 = 1.9634950e-01 -... gives pitch length = 3.2000007e+01 -Elastic constant kappa0 = 2.0000000e-02 -Elastic constant kappa1 = 2.0000000e-02 -Amplitude (uniaxial) order = 3.0000000e-01 -Effective aspect ratio xi = 7.0000000e-01 -Chirality = 2.0057255e+00 -Reduced temperature = 0.0000000e+00 -Initial redshift = 9.1000000e-01 -Dynamic redshift update = no -Liquid crystal activity No - -Using Beris-Edwards solver: -Rotational diffusion const = 1.0000000e-01 -LC fluctuations: = off - -System properties ----------------- -Mean fluid density: 1.00000e+00 -Shear viscosity 1.66667e+00 -Bulk viscosity 1.66667e+00 -Temperature 0.00000e+00 -External body force density 0.00000e+00 0.00000e+00 0.00000e+00 -External E-field amplitude 0.00000e+00 0.00000e+00 0.00000e+00 -External E-field frequency 0.00000e+00 -External magnetic field 0.00000e+00 0.00000e+00 0.00000e+00 - -Lattice Boltzmann distributions -------------------------------- -Model: d3q19 -SIMD vector len: 1 -Number of sets: 1 -Halo type: full -Input format: binary -Output format: binary -I/O grid: 1 1 1 - -Lattice Boltzmann collision ---------------------------- -Relaxation time scheme: M10 -Hydrodynamic modes: on -Ghost modes: on -Isothermal fluctuations: off -Shear relaxation time: 5.50000e+00 -Bulk relaxation time: 5.50000e+00 -Ghost relaxation time: 1.00000e+00 -[User ] Random number seed: 8361235 - -Hydrodynamics -------------- -Hydrodynamics: on - -Order parameter I/O -------------------- -Order parameter I/O format: -I/O decomposition: 1 1 1 - -Advection scheme order: 1 (default) -Gradient calculation: 3d_7pt_fluid - - -Initialising Q_ab using rotated O2 (BPII) -Euler angles alpha_z=45, beta_x'=45, gamma_z'=0 -Initial conditions. - -Scalars - total mean variance min max -[rho] 32768.00 1.00000000000 2.2204460e-16 1.00000000000 1.00000000000 -[phi] -1.0206918e-12 -3.1149042e-17 8.4935422e-02 -5.9727840e-01 5.9727840e-01 -[phi] -7.8728135e-12 -2.4025920e-16 4.5000000e-02 -3.0000000e-01 3.0000000e-01 -[phi] -1.4608759e-11 -4.4582393e-16 4.5000000e-02 -3.0000000e-01 3.0000000e-01 -[phi] 4.4785463e+02 1.3667439e-02 9.3490906e-02 -5.9885749e-01 6.0000000e-01 -[phi] 1.2765777e+02 3.8958061e-03 4.4853901e-02 -2.9998998e-01 2.9998998e-01 - -Momentum - x y z -[total ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 -[fluid ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 - -Starting time step loop. - -Scalars - total mean variance min max -[rho] 32768.00 1.00000000000 2.3534397e-10 0.99994882568 1.00004618664 -[phi] -6.1782286e+01 -1.8854457e-03 1.1641226e-02 -1.7865819e-01 3.3310126e-01 -[phi] 1.6566248e+02 5.0556177e-03 1.0451679e-02 -2.4498503e-01 2.5672772e-01 -[phi] -1.2027857e+01 -3.6706108e-04 1.0174710e-02 -2.4772676e-01 2.5529376e-01 -[phi] 3.9270784e+01 1.1984492e-03 1.1978320e-02 -1.7294678e-01 3.4809866e-01 -[phi] 2.5982022e+00 7.9290839e-05 1.0810133e-02 -2.5451840e-01 2.6076295e-01 - -Free energies - timestep f v f/v f_bulk/v f_grad/v redshift -[fe] 20000 -7.0999051989e-01 3.2768000000e+04 -2.1667191159e-05 -3.1595817022e-05 9.9286258634e-06 9.1000000000e-01 - -Momentum - x y z -[total ] 4.6159604e-13 4.8495236e-13 7.4037998e-14 -[fluid ] 4.6159604e-13 4.8495236e-13 7.4037998e-14 - -Velocity - x y z -[minimum ] -1.5631767e-05 -1.5180160e-05 -1.6060168e-05 -[maximum ] 1.2889113e-05 2.0437814e-05 1.3411893e-05 - -Completed cycle 20000 - -Timer resolution: 1e-06 second - -Timer statistics - Section: tmin tmax total - Total: 602.078 602.078 602.078 602.078200 (1 call) - Time step loop: 0.023 0.121 602.025 0.030101 (20000 calls) - Propagation: 0.002 0.013 41.057 0.002053 (20000 calls) - Propagtn (krnl) : 0.002 0.013 40.951 0.002048 (20000 calls) - Collision: 0.004 0.020 95.821 0.004791 (20000 calls) - Collision (krnl) : 0.004 0.020 95.733 0.004787 (20000 calls) - Lattice halos: 0.001 0.032 32.279 0.001614 (20000 calls) - phi gradients: 0.003 0.024 85.017 0.004251 (20000 calls) - phi grad (krnl) : 0.003 0.017 69.708 0.003485 (20000 calls) - phi halos: 0.000 0.017 15.202 0.000760 (20000 calls) - BBL: 0.000 0.000 0.016 0.000001 (20000 calls) - Force calculation: 0.007 0.037 170.190 0.008509 (20000 calls) - Phi force (krnl) : 0.003 0.027 70.392 0.003520 (20000 calls) - phi update: 0.006 0.067 171.798 0.008590 (20000 calls) - Velocity Halo : 0.000 0.045 15.034 0.000752 (20000 calls) -BE mol field (krnl) : 0.002 0.014 42.845 0.002142 (20000 calls) -BP BE update (krnl) : 0.003 0.016 66.731 0.003337 (20000 calls) - Advectn (krnl) : 0.001 0.016 32.028 0.001601 (20000 calls) - Advectn BCS (krnl) : 0.000 0.011 12.049 0.000602 (20000 calls) - Free1: 0.000 0.015 0.027 0.000001 (20000 calls) -Warning: key/value present in input but not used: -(Line 71): boundary_walls_on no - -End time: Wed Oct 27 16:53:28 2021 -Ludwig finished normally. From a67c65afc16803c839b76ec64949cb9d8e9de609 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Mon, 1 Nov 2021 17:31:05 +0000 Subject: [PATCH 014/117] First attempt --- src/lb_inflow_rhou.c | 269 ++++++++++++++++++++++++++++++++++++++++ src/lb_inflow_rhou.h | 43 +++++++ src/lb_openbc_options.c | 149 ++++++++++++++++++++++ src/lb_openbc_options.h | 47 +++++++ 4 files changed, 508 insertions(+) create mode 100644 src/lb_inflow_rhou.c create mode 100644 src/lb_inflow_rhou.h create mode 100644 src/lb_openbc_options.c create mode 100644 src/lb_openbc_options.h diff --git a/src/lb_inflow_rhou.c b/src/lb_inflow_rhou.c new file mode 100644 index 000000000..63b6e27a8 --- /dev/null +++ b/src/lb_inflow_rhou.c @@ -0,0 +1,269 @@ +/***************************************************************************** + * + * lb_inflow_rhou.c + * + * Concrete instance of lb_open_bc.h for inflow. + * + * Edinburgh Soft Matter and Statistical Phsyics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + *****************************************************************************/ + +#include +#include + +#include "lb_model.h" +#include "lb_inflow_rhou.h" + +typedef enum {LB_LINK_COUNT, LB_LINK_ASSIGN} lb_link_init_enum_t; + +__host__ int lb_inflow_rhou_init_internal(lb_inflow_rhou_t * inflow); +__host__ int lb_inflow_init_link(lb_inflow_rhou_t * inflow, + lb_link_init_enum_t flag, int id); + +static int int_max(int a, int b) {return (a > b) ?a :b;} + + +static const lb_open_bc_vtable_t vt_ = { + (lb_open_bc_free_ft) lb_inflow_rhou_free, + (lb_open_bc_update_ft) lb_inflow_rhou_update, + (lb_open_bc_stats_ft) lb_inflow_rhou_stats +}; + +/***************************************************************************** + * + * lb_inflow_rhou_create + * + *****************************************************************************/ + +__host__ int lb_inflow_rhou_create(pe_t * pe, cs_t * cs, + const lb_openbc_options_t * options, + lb_inflow_rhou_t ** inflow) { + lb_inflow_rhou_t * bc = NULL; + + assert(pe); + assert(cs); + assert(options); + assert(inflow); + + bc = (lb_inflow_rhou_t *) calloc(1, sizeof(lb_inflow_rhou_t)); + assert(bc); + if (bc == NULL) pe_fatal(pe, "Failed to allocate lb_inflow_rhou_t"); + + /* Pointers; superclass block */ + bc->pe = pe; + bc->cs = cs; + + bc->super.func = &vt_; + bc->super.id = LB_OPEN_BC_INFLOW_RHOU; + + if (!lb_openbc_options_valid(options)) { + /* Internal error if we reach this point. */ + pe_fatal(pe, "lb_inflow_rhou_create: lb_openbc_options_t invalid\n"); + } + bc->options = *options; + + lb_inflow_rhou_init_internal(bc); + + *inflow = bc; + + return 0; +} + +/***************************************************************************** + * + * lb_inflow_rhou_init_internal + * + *****************************************************************************/ + +__host__ int lb_inflow_rhou_init_internal(lb_inflow_rhou_t * inflow) { + + assert(inflow); + + if (inflow->options.flow[X]) lb_inflow_init_link(inflow, LB_LINK_COUNT, X); + if (inflow->options.flow[Y]) lb_inflow_init_link(inflow, LB_LINK_COUNT, Y); + if (inflow->options.flow[Z]) lb_inflow_init_link(inflow, LB_LINK_COUNT, Z); + + { + pe_t * pe = inflow->pe; + int nlink = int_max(1, inflow->nlink); /* No zero sized allocations. */ + + inflow->linkp = (int8_t *) calloc(nlink, sizeof(int8_t)); + inflow->linki = (int *) calloc(nlink, sizeof(int)); + inflow->linkj = (int *) calloc(nlink, sizeof(int)); + + assert(inflow->linkp); + assert(inflow->linki); + assert(inflow->linkj); + + if (inflow->linkp == NULL) pe_fatal(pe, "calloc(inflow->linkp) NULL\n"); + if (inflow->linki == NULL) pe_fatal(pe, "calloc(inflow->linki) NULL\n"); + if (inflow->linkj == NULL) pe_fatal(pe, "calloc(inflow->linkj) NULL\n"); + } + + if (inflow->options.flow[X]) lb_inflow_init_link(inflow, LB_LINK_ASSIGN, X); + if (inflow->options.flow[Y]) lb_inflow_init_link(inflow, LB_LINK_ASSIGN, Y); + if (inflow->options.flow[Z]) lb_inflow_init_link(inflow, LB_LINK_ASSIGN, Z); + + return 0; +} + +/***************************************************************************** + * + * lb_inflow_init_link + * + * Identify links representing incoming distributions at the inflow + * which are fluid to fluid in the coordinate direction "id". + * + * This assumes that the other two directions are walls, and so no + * duplicates of incoming solid-fluid (bbl) links are wanted. + * + * CHECK CHECK CHECK links are fluid (domain) to fluid (halo). The + * incoming distributions are then actually the complements -cv[p]. + * + *****************************************************************************/ + +__host__ int lb_inflow_init_link(lb_inflow_rhou_t * inflow, + lb_link_init_enum_t init, int id) { + + cs_t * cs = NULL; + int noffset[3] = {}; + int nlink = 0; + + assert(inflow); + assert(id == X || id == Y || id == Z); + + cs = inflow->cs; + cs_nlocal_offset(cs, noffset); + + if (noffset[id] == 0) { + int ntotal[3] = {}; + int nlocal[3] = {}; + + lb_model_t model = {}; + lb_model_create(inflow->options.nvel, &model); + + cs_ntotal(cs, ntotal); + cs_nlocal(cs, nlocal); + + nlocal[id] = 1; /* Only leftmost edge in the relevant direction */ + + for (int ic = 1; ic <= nlocal[X]; ic++) { + for (int jc = 1; jc <= nlocal[Y]; jc++) { + for (int kc = 1; kc <= nlocal[Z]; kc++) { + + for (int p = 1; p < model.nvel; p++) { + + if (model.cv[p][id] != -1) continue; + + int ic1 = ic + model.cv[p][X]; + int jc1 = jc + model.cv[p][Y]; + int kc1 = kc + model.cv[p][Z]; + + /* Some shuffling to get "other 2 directions" */ + int id1 = (id + 1) % 3; + int id2 = (id + 2) % 3; + + int ijk[3] = {ic1, jc1, kc1}; + + if (noffset[id1] + ijk[id1] < 1 ) continue; + if (noffset[id1] + ijk[id1] > ntotal[id1]) continue; + if (noffset[id2] + ijk[id2] < 1 ) continue; + if (noffset[id2] + ijk[id2] > ntotal[id2]) continue; + + if (init == LB_LINK_ASSIGN) { + inflow->linkp[nlink] = p; + inflow->linki[nlink] = cs_index(cs, ic, jc, kc); + inflow->linkj[nlink] = cs_index(cs, ic1, jc1, kc1); + } + nlink += 1; + } + } + } + } + + lb_model_free(&model); + } + + inflow->nlink = nlink; + + return 0; +} + +/***************************************************************************** + * + * lb_inflow_rhou_free + * + *****************************************************************************/ + +__host__ int lb_inflow_rhou_free(lb_inflow_rhou_t * inflow) { + + assert(inflow); + + free(inflow->linkj); + free(inflow->linki); + free(inflow->linkp); + free(inflow); + + return 0; +} + +/***************************************************************************** + * + * lb_inflow_rhou_update + * + * Drive the update of (i.e., apply) the boundary conditions. + * + * 1. We must update the rho u in the halo region post collision + * - Allows any relevant f_i(rho, u) to be computed. + * - Allows correct u to enter any flux calculation at edge of grid. + * 2. Update post collision distributions in halo region appropriately + * to enter propagation stage. + * + * After lattice halo swap; before propagation. + * + *****************************************************************************/ + +__host__ int lb_inflow_rhou_update(lb_inflow_rhou_t * inflow, hydro_t * hydro, + lb_t * lb) { + + assert(inflow); + assert(hydro); + assert(lb); + + /* Potentially both at the same time, as independent */ + + /* Inflow */ + /* Simple for each link: */ + /* compute relevant rho = rho(i); u0 fixed */ + /* set appropriate f^eq_p(rho, u0) at j */ + + /* Less simple for each link: */ + /* compute relevant rho = rho(i) post collision */ + /* compute reelvant u0 = u0(r_j) set by boundary position */ + /* set appropriate f^eq_p(rho, u0) */ + + /* Outflow */ + + /* Simple for each link: */ + /* compute relevant rho = rho0 */ + /* compute reelvant u0 = u0(r_i) */ + /* set appropriate f^eq_p(rho, u0) */ + + return 0; +} + +/***************************************************************************** + * + * lb_inflow_rhou_stats + * + * No operation at the moment. + * + *****************************************************************************/ + +__host__ int lb_inflow_rhou_stats(lb_inflow_rhou_t * inflow) { + + return 0; +} diff --git a/src/lb_inflow_rhou.h b/src/lb_inflow_rhou.h new file mode 100644 index 000000000..21b41caba --- /dev/null +++ b/src/lb_inflow_rhou.h @@ -0,0 +1,43 @@ +/***************************************************************************** + * + * lb_inflow_rhou.h + * + *****************************************************************************/ + +#ifndef LUDWIG_LB_INFLOW_RHOU_H +#define LUDWIG_LB_INFLOW_RHOU_H + +#include "lb_open_bc.h" +#include "lb_openbc_options.h" + +typedef struct lb_inflow_rhou_s lb_inflow_rhou_t; + +/* Inflow boundary condition. */ + +struct lb_inflow_rhou_s { + lb_open_bc_t super; /* Superclass block */ + pe_t * pe; /* Parallel environment */ + cs_t * cs; /* Coordinate system */ + lb_openbc_options_t options; /* Options/parameters */ + lb_inflow_rhou_t * target; /* Target pointer */ + + /* Boundary links */ + int nlink; /* Number of links (local) */ + int8_t * linkp; /* Velocity index in LB basis (i->j) */ + int * linki; /* Fluid site in system */ + int * linkj; /* Fluid site in inflow halo boundary */ +}; + +__host__ int lb_inflow_rhou_create(pe_t * pe, cs_t * cs, + const lb_openbc_options_t * options, + lb_inflow_rhou_t ** inflow); + +__host__ int lb_inflow_rhou_free(lb_inflow_rhou_t * inflow); +__host__ int lb_inflow_rhou_update(lb_inflow_rhou_t * inflow, + hydro_t * hydro, lb_t * lb); +__host__ int lb_inflow_rhou_stats(lb_inflow_rhou_t * inflow); + +__host__ int lb_inflow_rhou_info(lb_inflow_rhou_t * inflow); + +#endif + diff --git a/src/lb_openbc_options.c b/src/lb_openbc_options.c new file mode 100644 index 000000000..7b043817f --- /dev/null +++ b/src/lb_openbc_options.c @@ -0,0 +1,149 @@ +/***************************************************************************** + * + * lb_openbc_options.c + * + * Options container for fluid open boundary conditions. + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#include +#include + +#include "lb_openbc_options.h" + +/* Defaults */ + +#define LB_INFLOW_DEFAULT() LB_INFLOW_NONE +#define LB_OUTFLOW_DEFAULT() LB_OUTFLOW_NONE +#define LB_FLOW_DEFAULT() {0,0,0} + +/***************************************************************************** + * + * lb_openbc_options_inflow_default + * + *****************************************************************************/ + +__host__ lb_inflow_enum_t lb_openbc_options_inflow_default(void) { + + return LB_INFLOW_DEFAULT(); +} + +/***************************************************************************** + * + * lb_options_openbc_outflow_default + * + *****************************************************************************/ + +__host__ lb_outflow_enum_t lb_openbc_options_outflow_default(void) { + + return LB_OUTFLOW_DEFAULT(); +} + +/***************************************************************************** + * + * lb_openbc_options_default + * + *****************************************************************************/ + +__host__ lb_openbc_options_t lb_openbc_options_default(void) { + + lb_openbc_options_t options = {.bctype = 0, + .inflow = LB_INFLOW_DEFAULT(), + .outflow = LB_OUTFLOW_DEFAULT(), + .flow = LB_FLOW_DEFAULT()}; + + return options; +} + +/***************************************************************************** + * + * lb_openbc_options_valid + * + *****************************************************************************/ + +__host__ int lb_openbc_options_valid(const lb_openbc_options_t * options) { + + int valid = 0; /* 0 = invalid */ + + valid += lb_openbc_options_inflow_valid(options->inflow); + valid += lb_openbc_options_outflow_valid(options->outflow); + valid += lb_openbc_options_flow_valid(options->flow); + + return valid; +} + +/***************************************************************************** + * + * lb_openbc_options_inflow_valid + * + *****************************************************************************/ + +__host__ int lb_openbc_options_inflow_valid(lb_inflow_enum_t inflow) { + + int isvalid = 0; /* 0 = invalid */ + + isvalid += (inflow == LB_INFLOW_NONE); + + return isvalid; +} + +/***************************************************************************** + * + * lb_openbc_options_outflow_valid + * + *****************************************************************************/ + +__host__ int lb_openbc_options_outflow_valid(lb_outflow_enum_t outflow) { + + int isvalid = 0; /* 0 = invalid */ + + isvalid += (outflow == LB_OUTFLOW_NONE); + + return isvalid; +} + +/***************************************************************************** + * + * lb_openbc_options_flow_valid + * + *****************************************************************************/ + +__host__ int lb_openbc_options_flow_valid(const int flow[3]) { + + int isvalid = 0; + int sum = flow[0] + flow[1] + flow[2]; + + /* No flow is ok; otherwise only one direction. */ + isvalid = (sum == 0) || (sum == 1); + + return isvalid; +} + +/***************************************************************************** + * + * lb_openbc_options_info + * + *****************************************************************************/ + +__host__ int lb_openbc_options_info(pe_t * pe, + const lb_openbc_options_t * options) { + + assert(pe); + assert(options); + + pe_info(pe, "bctype: %d\n", options->bctype); + pe_info(pe, "inflow: %d\n", options->inflow); + pe_info(pe, "outflow: %d\n", options->outflow); + pe_info(pe, "flow: %1d %1d %1d\n", options->flow[0], options->flow[1], + options->flow[2]); + + return 0; +} diff --git a/src/lb_openbc_options.h b/src/lb_openbc_options.h new file mode 100644 index 000000000..0a0ac7056 --- /dev/null +++ b/src/lb_openbc_options.h @@ -0,0 +1,47 @@ +/***************************************************************************** + * + * lb_openbc_options.h + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Comuting Centre + * + * (c) 2021 The University of Edinburgh + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#ifndef LUDWIG_LB_OPENBC_OPTIONS_H +#define LUDWIG_LB_OPENBC_OPTIONS_H + +#include "pe.h" + +/* TYPES */ + +enum lb_inflow_enum {LB_INFLOW_INVALID = 0, LB_INFLOW_NONE, LB_INFLOW_MAX}; +enum lb_outflow_enum {LB_OUTFLOW_INVALID = 0, LB_OUTFLOW_NONE, LB_OUTFLOW_MAX}; + +typedef enum lb_inflow_enum lb_inflow_enum_t; +typedef enum lb_outflow_enum lb_outflow_enum_t; +typedef struct lb_openbc_options_s lb_openbc_options_t; + +struct lb_openbc_options_s { + int bctype; /* Combination of inflow/outflow? */ + int nvel; + lb_inflow_enum_t inflow; /* Inflow boundary condition type */ + lb_outflow_enum_t outflow; /* Outflow boundary condition type */ + int flow[3]; /* Flow coordinate direction (exactly 1) */ +}; + +__host__ lb_inflow_enum_t lb_openbc_options_inflow_default(void); +__host__ lb_outflow_enum_t lb_openbc_options_outflow_default(void); +__host__ lb_openbc_options_t lb_openbc_options_default(void); + +__host__ int lb_openbc_options_valid(const lb_openbc_options_t * options); +__host__ int lb_openbc_options_inflow_valid(lb_inflow_enum_t inflow); +__host__ int lb_openbc_options_outflow_valid(lb_outflow_enum_t outflow); +__host__ int lb_openbc_options_flow_valid(const int flow[3]); + +__host__ int lb_openbc_options_info(pe_t * pe, const lb_openbc_options_t *); + +#endif From e1637ab0a12c4e88adb2f0a94ce99aa122790287 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Mon, 1 Nov 2021 17:31:42 +0000 Subject: [PATCH 015/117] Introduce new model struct and remove global symbols --- src/cartesian.h | 22 +++++++ src/collision.c | 3 +- src/coords.h | 6 +- src/d2q9.c | 30 ++-------- src/d2q9.h | 17 +----- src/d3q15.c | 35 +----------- src/d3q15.h | 20 +------ src/d3q19.c | 18 ++---- src/d3q19.h | 24 +------- src/lb_d2q9.c | 130 ++++++++++++++++++++++++++++++++++++++++++ src/lb_d2q9.h | 44 ++++++++++++++ src/lb_d3q15.c | 138 ++++++++++++++++++++++++++++++++++++++++++++ src/lb_d3q15.h | 42 ++++++++++++++ src/lb_d3q19.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++ src/lb_d3q19.h | 50 ++++++++++++++++ src/lb_d3q27.c | 62 ++++++++++++++++++++ src/lb_d3q27.h | 47 +++++++++++++++ src/lb_model.c | 85 +++++++++++++++++++++++++++ src/lb_model.h | 40 +++++++++++++ src/lb_model_s.h | 3 +- src/model.c | 26 +++------ src/model.h | 1 - src/model_le.c | 4 +- src/wall.h | 3 +- 24 files changed, 842 insertions(+), 153 deletions(-) create mode 100644 src/cartesian.h create mode 100644 src/lb_d2q9.c create mode 100644 src/lb_d2q9.h create mode 100644 src/lb_d3q15.c create mode 100644 src/lb_d3q15.h create mode 100644 src/lb_d3q19.c create mode 100644 src/lb_d3q19.h create mode 100644 src/lb_d3q27.c create mode 100644 src/lb_d3q27.h create mode 100644 src/lb_model.c create mode 100644 src/lb_model.h diff --git a/src/cartesian.h b/src/cartesian.h new file mode 100644 index 000000000..2c8cf6fc3 --- /dev/null +++ b/src/cartesian.h @@ -0,0 +1,22 @@ +/***************************************************************************** + * + * cartesian.h + * + * Just some Cartesian directions without all the coords.h stuff. + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#ifndef LUDWIG_CARTESIAN_H +#define LUDWIG_CARTESIAN_H + +typedef enum cartesian_enum {X=0, Y, Z} cartesian_enum_t; + +#endif diff --git a/src/collision.c b/src/collision.c index 58962c401..77dd2a427 100644 --- a/src/collision.c +++ b/src/collision.c @@ -1571,6 +1571,7 @@ __host__ int lb_collision_noise_var_set(lb_t * lb, noise_t * noise) { double tau_b; double tau_g; LB_RCS2_DOUBLE(rcs2); + LB_NORMALISERS_DOUBLE(na); physics_t * phys = NULL; @@ -1602,7 +1603,7 @@ __host__ int lb_collision_noise_var_set(lb_t * lb, noise_t * noise) { for (p = NHYDRO; p < NVEL; p++) { tau_g = 1.0/lb->param->rtau[p]; lb->param->var_noise[p] = - sqrt(kt/norm_[p])*sqrt((tau_g + tau_g - 1.0)/(tau_g*tau_g)); + sqrt(kt/na[p])*sqrt((tau_g + tau_g - 1.0)/(tau_g*tau_g)); } } diff --git a/src/coords.h b/src/coords.h index 275d41236..16b1a7fbf 100644 --- a/src/coords.h +++ b/src/coords.h @@ -2,12 +2,10 @@ * * coords.h * - * $Id: coords.h,v 1.4 2010-10-15 12:40:02 kevin Exp $ - * * Edinburgh Soft Matter and Statistical Physics Group and * Edinburgh Parallel Computing Centre * - * (c) 2010-2017 The University of Edinburgh + * (c) 2010-2021 The University of Edinburgh * * Contributing authors: * Kevin Stratford (kevin@epcc.ed.ac.uk) @@ -18,12 +16,12 @@ #define LUDWIG_COORDS_H #include "pe.h" +#include "cartesian.h" typedef struct coords_s cs_t; #define NSYMM 6 /* Elements for general symmetric tensor */ -enum cartesian_directions {X, Y, Z}; enum cartesian_neighbours {FORWARD, BACKWARD}; enum cs_mpi_cart_neighbours {CS_FORW=0,CS_BACK=1}; enum upper_triangle {XX, XY, XZ, YY, YZ, ZZ}; diff --git a/src/d2q9.c b/src/d2q9.c index c73f5973d..3997bfebe 100644 --- a/src/d2q9.c +++ b/src/d2q9.c @@ -64,34 +64,12 @@ const char * model_name_d2q9 = "D2Q9"; * *****************************************************************************/ -const int cv[NVEL9][3] = {{ 0, 0, 0}, - { 1, 1, 0}, { 1, 0, 0}, - { 1, -1, 0}, { 0, 1, 0}, - { 0, -1, 0}, {-1, 1, 0}, - {-1, 0, 0}, {-1, -1, 0}}; - -/* Prefer to compute c_ia c_ib - cs2*d_ab. So remove global symbol. */ -/* -const double q_[NVEL9][3][3] = { - {{-1.0/3.0, 0.0, 0.0}, { 0.0,-1.0/3.0, 0.0}, { 0.0, 0.0, 0.0}}, - {{ 2.0/3.0, 1.0, 0.0}, { 1.0, 2.0/3.0, 0.0}, { 0.0, 0.0, 0.0}}, - {{ 2.0/3.0, 0.0, 0.0}, { 0.0,-1.0/3.0, 0.0}, { 0.0, 0.0, 0.0}}, - {{ 2.0/3.0,-1.0, 0.0}, {-1.0, 2.0/3.0, 0.0}, { 0.0, 0.0, 0.0}}, - {{-1.0/3.0, 0.0, 0.0}, { 0.0, 2.0/3.0, 0.0}, { 0.0, 0.0, 0.0}}, - {{-1.0/3.0, 0.0, 0.0}, { 0.0, 2.0/3.0, 0.0}, { 0.0, 0.0, 0.0}}, - {{ 2.0/3.0,-1.0, 0.0}, {-1.0, 2.0/3.0, 0.0}, { 0.0, 0.0, 0.0}}, - {{ 2.0/3.0, 0.0, 0.0}, { 0.0,-1.0/3.0, 0.0}, { 0.0, 0.0, 0.0}}, - {{ 2.0/3.0, 1.0, 0.0}, { 1.0, 2.0/3.0, 0.0}, { 0.0, 0.0, 0.0}}}; -*/ - #define w0 (16.0/36.0) #define w1 (4.0/36.0) #define w2 (1.0/36.0) -const double wv[NVEL9] = {w0, w2, w1, w2, w1, w1, w2, w1, w2}; - -const double norm_[NVEL9] = {1.0, 3.0, 3.0, 9.0/2.0, 9.0, 9.0/2.0, 1.0/4.0, - 3.0/8.0, 3.0/8.0}; +LB_CV_D2Q9(cv); +LB_WEIGHTS_D2Q9(wv); #define c0 0.0 #define c1 1.0 @@ -102,6 +80,7 @@ const double norm_[NVEL9] = {1.0, 3.0, 3.0, 9.0/2.0, 9.0, 9.0/2.0, 1.0/4.0, #define r4 (1.0/4.0) #define r6 (1.0/6.0) +/* const double ma_[NVEL9][NVEL9] = { { c1, c1, c1, c1, c1, c1, c1, c1, c1}, { c0, c1, c1, c1, c0, c0, -c1, -c1, -c1}, @@ -113,6 +92,7 @@ const double ma_[NVEL9][NVEL9] = { { c0, c4, -c2, c4, c0, c0, -c4, c2, -c4}, { c0, c4, c0, -c4, -c2, c2, c4, c0, -c4}}; + #define wa (6.0/72.0) #define wb (4.0/72.0) #define wc (3.0/72.0) @@ -127,7 +107,7 @@ const double mi_[NVEL9][NVEL9] = { {w2, -wa, wa, wa, -r4, wa, w2, -wc, wc}, {w1, -r3, c0, r3, c0, -r6, -wb, wa, c0}, {w2, -wa, -wa, wa, r4, wa, w2, -wc, -wc}}; - +*/ const int xblocklen_cv[CVXBLOCK9] = {3}; const int xdisp_fwd_cv[CVXBLOCK9] = {1}; diff --git a/src/d2q9.h b/src/d2q9.h index f093b3acb..9d7095193 100644 --- a/src/d2q9.h +++ b/src/d2q9.h @@ -22,13 +22,12 @@ enum {CVXBLOCK9 = 1}; enum {CVYBLOCK9 = 3}; enum {CVZBLOCK9 = 1}; +#include "lb_d2q9.h" + #ifdef _D2Q9_ -extern const int cv[NVEL9][3]; +extern const int8_t cv[NVEL9][3]; extern const double wv[NVEL9]; -extern const double norm_[NVEL9]; -extern const double ma_[NVEL9][NVEL9]; -extern const double mi_[NVEL9][NVEL9]; extern const int xblocklen_cv[CVXBLOCK9]; extern const int xdisp_fwd_cv[CVXBLOCK9]; @@ -42,16 +41,6 @@ extern const int zblocklen_cv[CVZBLOCK9]; extern const int zdisp_fwd_cv[CVZBLOCK9]; extern const int zdisp_bwd_cv[CVZBLOCK9]; -#define LB_CV_D2Q9(cv) const int8_t cv[NVEL9][3] = { \ - { 0, 0, 0}, \ - { 1, 1, 0}, { 1, 0, 0}, \ - { 1, -1, 0}, { 0, 1, 0}, \ - { 0, -1, 0}, {-1, 1, 0}, \ - {-1, 0, 0}, {-1, -1, 0}}; - -#define LB_NORMALISERS_D2Q9(norm) const double norm[NVEL9] = { \ - 1.0, 3.0, 3.0, 9.0/2.0, 9.0, 9.0/2.0, 1.0/4.0, 3.0/8.0, 3.0/8.0}; - #endif #endif diff --git a/src/d3q15.c b/src/d3q15.c index c6a285abc..ddde706fc 100644 --- a/src/d3q15.c +++ b/src/d3q15.c @@ -83,38 +83,9 @@ const char * model_name_d3q15 = "D3Q15"; #define wb ( 9.0/72.0) #define wc ( 4.0/72.0) -const int cv[NVEL15][3] = {{ 0, 0, 0}, - { 1, 1, 1}, { 1, 1, -1}, { 1, 0, 0}, - { 1, -1, 1}, { 1, -1, -1}, { 0, 1, 0}, - { 0, 0, 1}, { 0, 0, -1}, { 0, -1, 0}, - {-1, 1, 1}, {-1, 1, -1}, {-1, 0, 0}, - {-1, -1, 1}, {-1, -1, -1}}; - -const double wv[NVEL15] = {w0, - w3, w3, w1, w3, w3, w1, w1, - w1, w1, w3, w3, w1, w3, w3}; -const double norm_[NVEL15] = {1.0, 3.0, 3.0, 3.0, 9.0/2.0, 9.0, 9.0, - 9.0/2.0,9.0,9.0/2.0, 0.5, 1.5, 1.5, 1.5, 9.0}; - -/* Prefer to compute c_ia c_ib - cs2 d_ab. So remove global symbol. */ +LB_CV_D3Q15(cv); +LB_WEIGHTS_D3Q15(wv); /* -const double q_[NVEL15][3][3] = { - {{-r3, 0.0, 0.0},{ 0.0,-r3, 0.0},{ 0.0, 0.0,-r3}}, - {{ t3, 1.0, 1.0},{ 1.0, t3, 1.0},{ 1.0, 1.0, t3}}, - {{ t3, 1.0,-1.0},{ 1.0, t3,-1.0},{-1.0,-1.0, t3}}, - {{ t3, 0.0, 0.0},{ 0.0,-r3, 0.0},{ 0.0, 0.0,-r3}}, - {{ t3,-1.0, 1.0},{-1.0, t3,-1.0},{ 1.0,-1.0, t3}}, - {{ t3,-1.0,-1.0},{-1.0, t3, 1.0},{-1.0, 1.0, t3}}, - {{-r3, 0.0, 0.0},{ 0.0, t3, 0.0},{ 0.0, 0.0,-r3}}, - {{-r3, 0.0, 0.0},{ 0.0,-r3, 0.0},{ 0.0, 0.0, t3}}, - {{-r3, 0.0, 0.0},{ 0.0,-r3, 0.0},{ 0.0, 0.0, t3}}, - {{-r3, 0.0, 0.0},{ 0.0, t3, 0.0},{ 0.0, 0.0,-r3}}, - {{ t3,-1.0,-1.0},{-1.0, t3, 1.0},{-1.0, 1.0, t3}}, - {{ t3,-1.0, 1.0},{-1.0, t3,-1.0},{ 1.0,-1.0, t3}}, - {{ t3, 0.0, 0.0},{ 0.0,-r3, 0.0},{ 0.0, 0.0,-r3}}, - {{ t3, 1.0,-1.0},{ 1.0, t3,-1.0},{-1.0,-1.0, t3}}, - {{ t3, 1.0, 1.0},{ 1.0, t3, 1.0},{ 1.0, 1.0, t3}}}; -*/ const double ma_[NVEL15][NVEL15] = {{ c1, c1, c1, c1, c1, c1, c1, c1, c1, c1, c1, c1, c1, c1, c1}, { c0, c1, c1, c1, c1, c1, c0, c0, c0, c0,-c1,-c1,-c1,-c1,-c1}, @@ -148,7 +119,7 @@ const double mi_[NVEL15][NVEL15] = { w1,-r3, c0, c0, r3, c0, c0,-r6, c0,-r6, wc,-r6, c0, c0, c0}, { w3,-wa,-wa, wa, wa, wb,-wb, wa,-wb, wa,-w3, wa, wa,-wa, wb}, { w3,-wa,-wa,-wa, wa, wb, wb, wa, wb, wa,-w3, wa, wa, wa,-wb}}; - +*/ const int xblocklen_cv[CVXBLOCK15] = {5}; const int xdisp_fwd_cv[CVXBLOCK15] = {1}; diff --git a/src/d3q15.h b/src/d3q15.h index 40cdbc0ea..0eb8ae533 100644 --- a/src/d3q15.h +++ b/src/d3q15.h @@ -22,13 +22,12 @@ enum {CVXBLOCK15 = 1}; enum {CVYBLOCK15 = 3}; enum {CVZBLOCK15 = 5}; +#include "lb_d3q15.h" + #ifdef _D3Q15_ -extern const int cv[NVEL15][3]; +extern const int8_t cv[NVEL15][3]; extern const double wv[NVEL15]; -extern const double norm_[NVEL15]; -extern const double ma_[NVEL15][NVEL15]; -extern const double mi_[NVEL15][NVEL15]; extern const int xblocklen_cv[CVXBLOCK15]; extern const int xdisp_fwd_cv[CVXBLOCK15]; @@ -42,19 +41,6 @@ extern const int zblocklen_cv[CVZBLOCK15]; extern const int zdisp_fwd_cv[CVZBLOCK15]; extern const int zdisp_bwd_cv[CVZBLOCK15]; -#define LB_CV_D3Q15(cv) const int8_t cv[NVEL15][3] = { \ - { 0, 0, 0}, \ - { 1, 1, 1}, { 1, 1, -1}, { 1, 0, 0}, \ - { 1, -1, 1}, { 1, -1, -1}, { 0, 1, 0}, \ - { 0, 0, 1}, { 0, 0, -1}, { 0, -1, 0}, \ - {-1, 1, 1}, {-1, 1, -1}, {-1, 0, 0}, \ - {-1, -1, 1}, {-1, -1, -1}}; - - -#define LB_NORMALISERS_D3Q15(norm) const double norm[NVEL15] = { \ - 1.0, 3.0, 3.0, 3.0, 9.0/2.0, 9.0, 9.0, 9.0/2.0, 9.0, 9.0/2.0, \ - 0.5, 1.5, 1.5, 1.5, 9.0}; - #endif #endif diff --git a/src/d3q19.c b/src/d3q19.c index 1cf31bda2..50cda9b29 100644 --- a/src/d3q19.c +++ b/src/d3q19.c @@ -74,13 +74,7 @@ const char * model_name_d3q19 = "D3Q19"; * *****************************************************************************/ -const int cv[NVEL19][3] = {{ 0, 0, 0}, - { 1, 1, 0}, { 1, 0, 1}, { 1, 0, 0}, - { 1, 0, -1}, { 1, -1, 0}, { 0, 1, 1}, - { 0, 1, 0}, { 0, 1, -1}, { 0, 0, 1}, - { 0, 0, -1}, { 0, -1, 1}, { 0, -1, 0}, - { 0, -1, -1}, {-1, 1, 0}, {-1, 0, 1}, - {-1, 0, 0}, {-1, 0, -1}, {-1, -1, 0}}; +LB_CV_D3Q19(cv); #define w0 (12.0/36.0) #define w1 (2.0/36.0) @@ -103,13 +97,9 @@ const int cv[NVEL19][3] = {{ 0, 0, 0}, #define wd ( 1.0/48.0) #define we ( 3.0/48.0) -const double wv[NVEL19] = {w0, - w2, w2, w1, w2, w2, w2, w1, w2, w1, - w1, w2, w1, w2, w2, w2, w1, w2, w2}; -const double norm_[NVEL19] = {c1, - 3.0, 3.0, 3.0, 9.0/2.0, 9.0, 9.0, 9.0/2.0, 9.0, 9.0/2.0, - 3.0/4.0, 3.0/2.0,3.0/2.0,3.0/2.0, 9.0/4.0,9.0/2.0,9.0/2.0,9.0/2.0, 0.5}; +LB_WEIGHTS_D3Q19(wv); +/* Global symbols are replaced by lb_model_t ... const double ma_[NVEL19][NVEL19] = { { c1, c1, c1, c1, c1, c1, c1, c1, c1, c1, c1, c1, c1, c1, c1, c1, c1, c1, c1}, { c0, c1, c1, c1, c1, c1, c0, c0, c0, c0, c0, c0, c0, c0,-c1,-c1,-c1,-c1,-c1}, @@ -153,7 +143,7 @@ const double mi_[NVEL19][NVEL19] = { {w2,-wa, c0,-wa, wa, c0, r4,-wb, c0, wa, wd,-wb, c0,-wb,-we, r8, c0, r8, wc}, {w2,-wa,-wa, c0, wa, r4, c0, wa, c0,-wb,-wb, wa, wa, c0, c0, c0, c0, c0, wc} }; - +*/ const int xblocklen_cv[CVXBLOCK19] = {5}; const int xdisp_fwd_cv[CVXBLOCK19] = {1}; const int xdisp_bwd_cv[CVXBLOCK19] = {14}; diff --git a/src/d3q19.h b/src/d3q19.h index 4b1348b28..913d5a130 100644 --- a/src/d3q19.h +++ b/src/d3q19.h @@ -24,13 +24,12 @@ enum {CVXBLOCK19 = 1}; enum {CVYBLOCK19 = 3}; enum {CVZBLOCK19 = 5}; +#include "lb_d3q19.h" + #ifdef _D3Q19_ -extern const int cv[NVEL19][3]; +extern const int8_t cv[NVEL19][3]; extern const double wv[NVEL19]; -extern const double norm_[NVEL19]; -extern const double ma_[NVEL19][NVEL19]; -extern const double mi_[NVEL19][NVEL19]; extern const int xblocklen_cv[CVXBLOCK19]; extern const int xdisp_fwd_cv[CVXBLOCK19]; @@ -44,23 +43,6 @@ extern const int zblocklen_cv[CVZBLOCK19]; extern const int zdisp_fwd_cv[CVZBLOCK19]; extern const int zdisp_bwd_cv[CVZBLOCK19]; -#define LB_CV_D3Q19(cv) const int8_t cv[NVEL19][3] = { \ - { 0, 0, 0}, \ - { 1, 1, 0}, { 1, 0, 1}, { 1, 0, 0}, \ - { 1, 0, -1}, { 1, -1, 0}, { 0, 1, 1}, \ - { 0, 1, 0}, { 0, 1, -1}, { 0, 0, 1}, \ - { 0, 0, -1}, { 0, -1, 1}, { 0, -1, 0}, \ - { 0, -1, -1}, {-1, 1, 0}, {-1, 0, 1}, \ - {-1, 0, 0}, {-1, 0, -1}, {-1, -1, 0}}; - -#define LB_NORMALISERS_D3Q19(norm) const double norm[NVEL19] = { \ - 1.0, \ - 3.0, 3.0, 3.0, \ - 9.0/2.0, 9.0, 9.0, 9.0/2.0, 9.0, 9.0/2.0, \ - 3.0/4.0, 3.0/2.0, 3.0/2.0, 3.0/2.0, \ - 9.0/4.0, 9.0/2.0, 9.0/2.0, 9.0/2.0, \ - 1.0/2.0}; - #endif #endif diff --git a/src/lb_d2q9.c b/src/lb_d2q9.c new file mode 100644 index 000000000..241ec013d --- /dev/null +++ b/src/lb_d2q9.c @@ -0,0 +1,130 @@ +/***************************************************************************** + * + * lb_d2q9.c + * + * D2Q9 definition. + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#include +#include + +#include "lb_d2q9.h" + +static int lb_d2q9_matrix_ma(lb_model_t * model); + +/***************************************************************************** + * + * lb_d2q9_create + * + *****************************************************************************/ + +int lb_d2q9_create(lb_model_t * model) { + + assert(model); + + *model = (lb_model_t) {}; + + model->ndim = 2; + model->nvel = NVEL_D2Q9; + model->cv = (int8_t (*)[3]) calloc(NVEL_D2Q9, sizeof(int8_t[3])); + model->wv = (double *) calloc(NVEL_D2Q9, sizeof(double)); + model->na = (double *) calloc(NVEL_D2Q9, sizeof(double)); + model->ma = (double **) calloc(NVEL_D2Q9, sizeof(double *)); + model->cs2 = (1.0/3.0); + + if (model->cv == NULL) goto err; + if (model->wv == NULL) goto err; + if (model->na == NULL) goto err; + if (model->ma == NULL) goto err; + + { + LB_CV_D2Q9(cv); + LB_WEIGHTS_D2Q9(wv); + LB_NORMALISERS_D2Q9(na); + + for (int p = 0; p < model->nvel; p++) { + for (int ia = 0; ia < 3; ia++) { + model->cv[p][ia] = cv[p][ia]; + } + model->wv[p] = wv[p]; + model->na[p] = na[p]; + } + } + + /* Further allocate matrix elements */ + model->ma[0] = (double *) calloc(NVEL_D2Q9*NVEL_D2Q9, sizeof(double)); + if (model->ma[0] == NULL) goto err; + + for (int p = 1; p < model->nvel; p++) { + model->ma[p] = model->ma[p-1] + NVEL_D2Q9; + } + + lb_d2q9_matrix_ma(model); + + return 0; + + err: + + lb_model_free(model); + + return -1; +} + +/***************************************************************************** + * + * lb_d2q9_matrix_ma + * + * Hydrodynamic modes as usual 1 + NDIM + NDIM*(NDIM+1)/2. + * + * One scalar ghost mode, plus associated vector + * + * chi = 1/2 (9c^4 - 15c^2 + 2) eigenvector ma[6] + * jchi_x = chi c_x eigenvector ma[7] + * jchi_y = ch1 c_y eigenvector ma[8] + * + *****************************************************************************/ + +static int lb_d2q9_matrix_ma(lb_model_t * model) { + + assert(model); + assert(model->ma); + assert(model->ma[0]); + + /* It's convenient to assign the elements columnwise */ + + for (int p = 0; p < model->nvel; p++) { + + assert(model->cv[p][Z] == 0); + + double rho = 1.0; + double cx = rho*model->cv[p][X]; + double cy = rho*model->cv[p][Y]; + double sxx = cx*cx - model->cs2; + double sxy = cx*cy; + double syy = cy*cy - model->cs2; + + double cs2 = cx*cx + cy*cy; + double chi = 0.5*(9.0*cs2*cs2 - 15.0*cs2 + 2); + + model->ma[0][p] = rho; + model->ma[1][p] = cx; + model->ma[2][p] = cy; + model->ma[3][p] = sxx; + model->ma[4][p] = sxy; + model->ma[5][p] = syy; + model->ma[6][p] = chi; + model->ma[7][p] = chi*cx; + model->ma[8][p] = chi*cy; + } + + return 0; +} diff --git a/src/lb_d2q9.h b/src/lb_d2q9.h new file mode 100644 index 000000000..b993ad9b8 --- /dev/null +++ b/src/lb_d2q9.h @@ -0,0 +1,44 @@ +/***************************************************************************** + * + * lb_d2q9.h + * + * D2Q9 definition. See lb_d2q9.c for details. + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#ifndef LUDWIG_LB_D2Q9_H +#define LUDWIG_LB_D2Q9_H + +#include "lb_model.h" + +/* Velocity set, weights, and normalisers. */ + +enum {NVEL_D2Q9 = 9}; + +#define LB_CV_D2Q9(cv) const int8_t cv[NVEL_D2Q9][3] = { \ + { 0, 0, 0}, \ + { 1, 1, 0}, { 1, 0, 0}, \ + { 1, -1, 0}, { 0, 1, 0}, \ + { 0, -1, 0}, {-1, 1, 0}, \ + {-1, 0, 0}, {-1, -1, 0}}; + +#define LB_WEIGHTS_D2Q9(wv) const double wv[NVEL_D2Q9] = { \ + 16.0/36.0, \ + 1.0/36.0, 4.0/36.0, 1.0/36.0, 4.0/36.0, \ + 4.0/36.0, 1.0/36.0, 4.0/36.0, 1.0/36.0}; + +#define LB_NORMALISERS_D2Q9(norm) const double norm[NVEL_D2Q9] = { \ + 1.0, 3.0, 3.0, 9.0/2.0, 9.0, 9.0/2.0, 1.0/4.0, 3.0/8.0, 3.0/8.0}; + + +int lb_d2q9_create(lb_model_t * model); + +#endif diff --git a/src/lb_d3q15.c b/src/lb_d3q15.c new file mode 100644 index 000000000..e29c239b5 --- /dev/null +++ b/src/lb_d3q15.c @@ -0,0 +1,138 @@ +/***************************************************************************** + * + * lb_d3q15.c + * + * D3Q15 model. + * + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#include +#include + +#include "lb_d3q15.h" + +static int lb_d3q15_matrix_ma(lb_model_t * model); + +/***************************************************************************** + * + * lb_d3q15_create + * + *****************************************************************************/ + +int lb_d3q15_create(lb_model_t * model) { + + assert(model); + + *model = (lb_model_t) {}; + + model->ndim = 3; + model->nvel = NVEL_D3Q15; + model->cv = (int8_t (*)[3]) calloc(NVEL_D3Q15, sizeof(int8_t[3])); + model->wv = (double *) calloc(NVEL_D3Q15, sizeof(double)); + model->na = (double *) calloc(NVEL_D3Q15, sizeof(double)); + model->ma = (double **) calloc(NVEL_D3Q15, sizeof(double *)); + model->cs2 = (1.0/3.0); + + if (model->cv == NULL) goto err; + if (model->wv == NULL) goto err; + if (model->na == NULL) goto err; + if (model->ma == NULL) goto err; + + { + LB_CV_D3Q15(cv); + LB_WEIGHTS_D3Q15(wv); + LB_NORMALISERS_D3Q15(na); + + for (int p = 0; p < model->nvel; p++) { + for (int ia = 0; ia < 3; ia++) { + model->cv[p][ia] = cv[p][ia]; + } + model->wv[p] = wv[p]; + model->na[p] = na[p]; + } + } + + /* Further allocate matrix elements */ + model->ma[0] = (double *) calloc(NVEL_D3Q15*NVEL_D3Q15, sizeof(double)); + if (model->ma[0] == NULL) goto err; + + for (int p = 1; p < model->nvel; p++) { + model->ma[p] = model->ma[p-1] + NVEL_D3Q15; + } + + lb_d3q15_matrix_ma(model); + + return 0; + + err: + + lb_model_free(model); + + return -1; +} + +/***************************************************************************** + * + * lb_d3q15_matrix_ma + * + * Hydrodynamic modes as usual 1 + NDIM + NDIM*(NDIM+1)/2 + * + * Two scalar ghost modes chi1 mnd chi2 and one vector jchi1: + * + * chi1 = 0.5*(-3.0*cs^2*cs^2 + 9.0*cs^2 - 4.0) mode[10] + * chi2 = cx*cy*cz mode[14] + * + *****************************************************************************/ + +static int lb_d3q15_matrix_ma(lb_model_t * model) { + + assert(model); + assert(model->ma); + assert(model->ma[0]); + + for (int p = 0; p < model->nvel; p++) { + + double rho = 1.0; + double cx = rho*model->cv[p][X]; + double cy = rho*model->cv[p][Y]; + double cz = rho*model->cv[p][Z]; + + double sxx = cx*cx - model->cs2; + double sxy = cx*cy; + double sxz = cx*cz; + double syy = cy*cy - model->cs2; + double syz = cy*cz; + double szz = cz*cz - model->cs2; + + double cs2 = cx*cx + cy*cy + cz*cz; + double chi1 = 0.5*(-3.0*cs2*cs2 + 9.0*cs2 - 4.0); + double chi2 = cx*cy*cz; + + model->ma[ 0][p] = rho; + model->ma[ 1][p] = cx; + model->ma[ 2][p] = cy; + model->ma[ 3][p] = cz; + model->ma[ 4][p] = sxx; + model->ma[ 5][p] = sxy; + model->ma[ 6][p] = sxz; + model->ma[ 7][p] = syy; + model->ma[ 8][p] = syz; + model->ma[ 9][p] = szz; + model->ma[10][p] = chi1; + model->ma[11][p] = chi1*cx; + model->ma[12][p] = chi1*cy; + model->ma[13][p] = chi1*cz; + model->ma[14][p] = chi2; + } + + return 0; +} diff --git a/src/lb_d3q15.h b/src/lb_d3q15.h new file mode 100644 index 000000000..c1374fca7 --- /dev/null +++ b/src/lb_d3q15.h @@ -0,0 +1,42 @@ +/***************************************************************************** + * + * lb_d3q15.h + * + * D3Q15 definition. See lb_d3q15.c for details. + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + *****************************************************************************/ + +#ifndef LUDWIG_LB_D3Q15_H +#define LUDWIG_LB_D3Q15_H + +#include "lb_model.h" + +/* Velocity set, weights, and normalisers */ + +enum {NVEL_D3Q15 = 15}; + +#define LB_CV_D3Q15(cv) const int8_t cv[NVEL_D3Q15][3] = { \ + { 0, 0, 0}, \ + { 1, 1, 1}, { 1, 1, -1}, { 1, 0, 0}, \ + { 1, -1, 1}, { 1, -1, -1}, { 0, 1, 0}, \ + { 0, 0, 1}, { 0, 0, -1}, { 0, -1, 0}, \ + {-1, 1, 1}, {-1, 1, -1}, {-1, 0, 0}, \ + {-1, -1, 1}, {-1, -1, -1}}; + +#define LB_WEIGHTS_D3Q15(wv) const double wv[NVEL_D3Q15] = { 16.0/72.0, \ + 1.0/72.0, 1.0/72.0, 8.0/72.0, 1.0/72.0, 1.0/72.0, 8.0/72.0, 8.0/72.0, \ + 8.0/72.0, 8.0/72.0, 1.0/72.0, 1.0/72.0, 8.0/72.0, 1.0/72.0, 1.0/72.0 }; + +#define LB_NORMALISERS_D3Q15(norm) const double norm[NVEL_D3Q15] = { \ + 1.0, 3.0, 3.0, 3.0, 9.0/2.0, 9.0, 9.0, 9.0/2.0, 9.0, 9.0/2.0, \ + 0.5, 1.5, 1.5, 1.5, 9.0}; + + +int lb_d3q15_create(lb_model_t * model); + +#endif diff --git a/src/lb_d3q19.c b/src/lb_d3q19.c new file mode 100644 index 000000000..8fafea132 --- /dev/null +++ b/src/lb_d3q19.c @@ -0,0 +1,145 @@ +/***************************************************************************** + * + * lb_d3q19.c + * + * D3Q19 model + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#include +#include + +#include "lb_d3q19.h" + +static int lb_d3q19_matrix_ma(lb_model_t * model); + +/***************************************************************************** + * + * lb_d3q19_create + * + *****************************************************************************/ + +int lb_d3q19_create(lb_model_t * model) { + + assert(model); + + *model = (lb_model_t) {}; + + model->ndim = 3; + model->nvel = NVEL_D3Q19; + model->cv = (int8_t (*)[3]) calloc(NVEL_D3Q19, sizeof(int8_t[3])); + model->wv = (double *) calloc(NVEL_D3Q19, sizeof(double)); + model->na = (double *) calloc(NVEL_D3Q19, sizeof(double)); + model->ma = (double **) calloc(NVEL_D3Q19, sizeof(double *)); + model->cs2 = (1.0/3.0); + + if (model->cv == NULL) goto err; + if (model->wv == NULL) goto err; + if (model->na == NULL) goto err; + if (model->ma == NULL) goto err; + + { + LB_CV_D3Q19(cv); + LB_WEIGHTS_D3Q19(wv); + LB_NORMALISERS_D3Q19(na); + + for (int p = 0; p < model->nvel; p++) { + for (int ia = 0; ia < 3; ia++) { + model->cv[p][ia] = cv[p][ia]; + } + model->wv[p] = wv[p]; + model->na[p] = na[p]; + } + } + + /* Further allocate matrix elements */ + + model->ma[0] = (double *) calloc(NVEL_D3Q19*NVEL_D3Q19, sizeof(double)); + if (model->ma[0] == NULL) goto err; + + for (int p = 1; p < model->nvel; p++) { + model->ma[p] = model->ma[p-1] + NVEL_D3Q19; + } + + lb_d3q19_matrix_ma(model); + + return 0; + + err: + + lb_model_free(model); + + return -1; +} + +/***************************************************************************** + * + * lb_d3q19_matrix_ma + * + * Hydrodynamic modes as usual: 1 + ndim + ndim*(ndim+1)/2 + * + * There are three scalar ghost modes: + * + * chi1 (2cs^2 - 3)(3c_z^2 - cs^2) mode[10] + * chi2 (2cs^2 - 3)(c_y^2 - c_x^2) mode[14] + * chi3 3cs^4 - 6cs^2 + 1 mode[18] + * + * and two associated vectors jchi1 and jchi2. + * + *****************************************************************************/ + +static int lb_d3q19_matrix_ma(lb_model_t * model) { + + assert(model); + assert(model->ma); + assert(model->ma[0]); + + for (int p = 0; p < model->nvel; p++) { + + double rho = 1.0; + double cx = rho*model->cv[p][X]; + double cy = rho*model->cv[p][Y]; + double cz = rho*model->cv[p][Z]; + double sxx = cx*cx - model->cs2; + double sxy = cx*cy; + double sxz = cx*cz; + double syy = cy*cy - model->cs2; + double syz = cy*cz; + double szz = cz*cz - model->cs2; + + double cs2 = cx*cx + cy*cy + cz*cz; + double chi1 = (2.0*cs2 - 3.0)*(3.0*cz*cz - cs2); + double chi2 = (2.0*cs2 - 3.0)*(cy*cy - cx*cx); + double chi3 = 3.0*cs2*cs2 - 6.0*cs2 + 1; + + model->ma[ 0][p] = rho; + model->ma[ 1][p] = cx; + model->ma[ 2][p] = cy; + model->ma[ 3][p] = cz; + model->ma[ 4][p] = sxx; + model->ma[ 5][p] = sxy; + model->ma[ 6][p] = sxz; + model->ma[ 7][p] = syy; + model->ma[ 8][p] = syz; + model->ma[ 9][p] = szz; + model->ma[10][p] = chi1; + model->ma[11][p] = chi1*cx; + model->ma[12][p] = chi1*cy; + model->ma[13][p] = chi1*cz; + model->ma[14][p] = chi2; + model->ma[15][p] = chi2*cx; + model->ma[16][p] = chi2*cy; + model->ma[17][p] = chi2*cz; + model->ma[18][p] = chi3; + } + + return 0; +} diff --git a/src/lb_d3q19.h b/src/lb_d3q19.h new file mode 100644 index 000000000..dd0c89b5d --- /dev/null +++ b/src/lb_d3q19.h @@ -0,0 +1,50 @@ +/***************************************************************************** + * + * lb_d3q19.h + * + * D3Q19 model definition. See lb_d3q19.c for details. + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#ifndef LUDWIG_LB_D3Q19_H +#define LUDWIG_LB_D3Q19_H + +#include "lb_model.h" + +/* Velocity set, weights, and normalisers. */ + +enum {NVEL_D3Q19 = 19}; + +#define LB_CV_D3Q19(cv) const int8_t cv[NVEL_D3Q19][3] = { \ + { 0, 0, 0}, \ + { 1, 1, 0}, { 1, 0, 1}, { 1, 0, 0}, \ + { 1, 0, -1}, { 1, -1, 0}, { 0, 1, 1}, \ + { 0, 1, 0}, { 0, 1, -1}, { 0, 0, 1}, \ + { 0, 0, -1}, { 0, -1, 1}, { 0, -1, 0}, \ + { 0, -1, -1}, {-1, 1, 0}, {-1, 0, 1}, \ + {-1, 0, 0}, {-1, 0, -1}, {-1, -1, 0}}; + +#define LB_WEIGHTS_D3Q19(wv) const double wv[NVEL_D3Q19] = { 12.0/36.0, \ + 1.0/36.0, 1.0/36.0, 2.0/36.0, 1.0/36.0, 1.0/36.0, 1.0/36.0, 2.0/36.0, \ + 1.0/36.0, 2.0/36.0, 2.0/36.0, 1.0/36.0, 2.0/36.0, 1.0/36.0, 1.0/36.0, \ + 1.0/36.0, 2.0/36.0, 1.0/36.0, 1.0/36.0}; + +#define LB_NORMALISERS_D3Q19(na) const double na[NVEL_D3Q19] = { \ + 1.0, \ + 3.0, 3.0, 3.0, \ + 9.0/2.0, 9.0, 9.0, 9.0/2.0, 9.0, 9.0/2.0, \ + 3.0/4.0, 3.0/2.0, 3.0/2.0, 3.0/2.0, \ + 9.0/4.0, 9.0/2.0, 9.0/2.0, 9.0/2.0, \ + 1.0/2.0}; + +int lb_d3q19_create(lb_model_t * model); + +#endif diff --git a/src/lb_d3q27.c b/src/lb_d3q27.c new file mode 100644 index 000000000..ded3328c5 --- /dev/null +++ b/src/lb_d3q27.c @@ -0,0 +1,62 @@ +/***************************************************************************** + * + * lb_d3q27.c + * + * D3Q27 definition. Not yet complete. + * + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#include +#include + +#include "lb_d3q27.h" + +/***************************************************************************** + * + * lb_d3q27_create + * + *****************************************************************************/ + +int lb_d3q27_create(lb_model_t * model) { + + assert(model); + + *model = (lb_model_t) {}; + + model->nvel = NVEL_D3Q27; + model->cv = (int8_t (*)[3]) calloc(NVEL_D3Q27, sizeof(int8_t[3])); + model->wv = (double *) calloc(NVEL_D3Q27, sizeof(double)); + model->cs2 = 1.0/3.0; + + if (model->cv == NULL) goto err; + if (model->wv == NULL) goto err; + + { + LB_CV_D3Q27(cv); + LB_WEIGHTS_D3Q27(wv); + + for (int p = 0; p < model->nvel; p++) { + for (int ia = 0; ia < 3; ia++) { + model->cv[p][ia] = cv[p][ia]; + } + model->wv[p] = wv[p]; + } + } + + return 0; + + err: + + lb_model_free(model); + + return -1; +} diff --git a/src/lb_d3q27.h b/src/lb_d3q27.h new file mode 100644 index 000000000..387040af7 --- /dev/null +++ b/src/lb_d3q27.h @@ -0,0 +1,47 @@ +/***************************************************************************** + * + * lb_d3q27.h + * + * D3Q27 model definition. See lb_d3q27.c for details. + * + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Comuting Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#ifndef LUDWIG_LB_D3Q27_H +#define LUDWIG_LB_D3Q27_H + +#include "lb_model.h" + +/* Velocity set, weights. */ + +enum {NVEL_D3Q27 = 27}; + +#define LB_CV_D3Q27(cv) const int8_t cv[NVEL_D3Q27][3] = { { 0, 0, 0}, \ + {-1,-1,-1}, {-1,-1, 0}, {-1,-1, 1}, {-1, 0,-1}, {-1, 0, 0}, {-1, 0, 1}, \ + {-1, 1,-1}, {-1, 1, 0}, {-1, 1, 1}, { 0,-1,-1}, { 0,-1, 0}, { 0,-1, 1}, \ + { 0, 0,-1}, { 0, 0, 1}, \ + { 0, 1,-1}, { 0, 1, 0}, { 0, 1, 1}, { 1,-1,-1}, { 1,-1, 0}, { 1,-1, 1}, \ + { 1, 0,-1}, { 1, 0, 0}, { 1, 0, 1}, { 1, 1,-1}, { 1, 1, 0}, { 1, 1, 1}}; + +/* Weights: |0| = 64 |1| = 16 |2| = 1 |3| = 4. All / 216 */ + +#define LB_WEIGHTS_D3Q27(wv) const double wv[NVEL_D3Q27] = { 64.0/216.0, \ + 4.0/216.0, 1.0/216.0, 4.0/216.0, 1.0/216.0, 16.0/216.0, 1.0/216.0, \ + 4.0/216.0, 1.0/216.0, 4.0/216.0, 1.0/216.0, 16.0/216.0, 1.0/216.0, \ + 16.0/216.0, 16.0/216.0, \ + 1.0/216.0, 16.0/216.0, 1.0/216.0, 4.0/216.0, 1.0/216.0, 4.0/216.0, \ + 1.0/216.0, 16.0/216.0, 1.0/216.0, 4.0/216.0, 1.0/216.0, 4.0/216.0}; + +/* Normalisers TBC */ + +int lb_d3q27_create(lb_model_t * model); + +#endif diff --git a/src/lb_model.c b/src/lb_model.c new file mode 100644 index 000000000..3a0018afc --- /dev/null +++ b/src/lb_model.c @@ -0,0 +1,85 @@ +/***************************************************************************** + * + * lb_model.c + * + * Appropriate model details at run time. + * + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#include +#include + +#include "lb_d2q9.h" +#include "lb_d3q15.h" +#include "lb_d3q19.h" +#include "lb_d3q27.h" + +/* #include "lb_model.h"*/ + +/***************************************************************************** + * + * lb_model_create + * + * Really just a factory method as f(nvel) + * + *****************************************************************************/ + +int lb_model_create(int nvel, lb_model_t * model) { + + int ierr = 0; + + assert(model); + + switch (nvel) { + case (NVEL_D2Q9): + lb_d2q9_create(model); + break; + case (NVEL_D3Q15): + lb_d3q15_create(model); + break; + case (NVEL_D3Q19): + lb_d3q19_create(model); + break; + case (NVEL_D3Q27): + lb_d3q27_create(model); + break; + default: + /* Error */ + ierr = -1; + } + + return ierr; +} + +/***************************************************************************** + * + * lb_model_free + * + *****************************************************************************/ + +int lb_model_free(lb_model_t * model) { + + assert(model); + + if (model->ma) { + if (model->ma[0]) free(model->ma[0]); + free(model->ma); + } + + if (model->na) free(model->na); + if (model->cv) free(model->cv); + if (model->wv) free(model->wv); + + *model = (lb_model_t) {}; + + return 0; +} diff --git a/src/lb_model.h b/src/lb_model.h new file mode 100644 index 000000000..37fe2be69 --- /dev/null +++ b/src/lb_model.h @@ -0,0 +1,40 @@ +/***************************************************************************** + * + * lb_model.h + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#ifndef LUDWIG_LB_MODEL_H +#define LUDWIG_LB_MODEL_H + +/* This file is scheduled to replace lb_model_s.h and model.h */ +/* and will only describe general fixed model parameters. */ + +#include + +#include "cartesian.h" /* Not used here explicitly but required elsewhere */ + +typedef struct lb_model_s lb_model_t; + +struct lb_model_s { + int8_t ndim; /* Usually 2 or 3 */ + int8_t nvel; /* 0 <= p < NVEL */ + int8_t (* cv)[3]; /* cv[p][3] always 3d */ + double * wv; /* weights wv[p] */ + double * na; /* normalisers na[p] */ + double ** ma; /* Matrix M^a eigenvctors of collision matrix */ + double cs2; /* (speed of sound)^2 */ +}; + +int lb_model_create(int nvel, lb_model_t * model); +int lb_model_free(lb_model_t * model); + +#endif diff --git a/src/lb_model_s.h b/src/lb_model_s.h index bd0dc96f7..a4bf9f20c 100644 --- a/src/lb_model_s.h +++ b/src/lb_model_s.h @@ -46,10 +46,11 @@ struct lb_data_s { int ndist; /* Number of distributions (default one) */ int nsite; /* Number of lattice sites (local) */ - int model; /* MODEL or MODEL_R */ pe_t * pe; /* parallel environment */ cs_t * cs; /* coordinate system */ + + lb_model_t model; /* Current model information */ halo_swap_t * halo; /* halo swap driver */ io_info_t * io_info; /* Distributions */ io_info_t * io_rho; /* Fluid density (here; could be hydrodynamics...) */ diff --git a/src/model.c b/src/model.c index cff447f3d..c43503bf9 100644 --- a/src/model.c +++ b/src/model.c @@ -74,9 +74,11 @@ __host__ int lb_create_ndist(pe_t * pe, cs_t * cs, int ndist, lb_t ** plb) { lb->pe = pe; lb->cs = cs; lb->ndist = ndist; - lb->model = DATA_MODEL; lb->nrelax = LB_RELAXATION_M10; + /* Compile time via NVEL at the moment. */ + lb_model_create(NVEL, &lb->model); + *plb = lb; return 0; @@ -149,6 +151,8 @@ __host__ int lb_free(lb_t * lb) { MPI_Type_free(&lb->site_z[0]); MPI_Type_free(&lb->site_z[1]); + lb_model_free(&lb->model); + free(lb->param); free(lb); @@ -186,7 +190,6 @@ __host__ int lb_memcpy(lb_t * lb, tdpMemcpyKind flag) { case tdpMemcpyHostToDevice: tdpMemcpy(&lb->target->ndist, &lb->ndist, sizeof(int), flag); tdpMemcpy(&lb->target->nsite, &lb->nsite, sizeof(int), flag); - tdpMemcpy(&lb->target->model, &lb->model, sizeof(int), flag); tdpMemcpy(tmpf, lb->f, nsz, flag); break; case tdpMemcpyDeviceToHost: @@ -353,8 +356,8 @@ static int lb_model_param_init(lb_t * lb) { for (ia = 0; ia < NVEL; ia++) { for (ib = 0; ib < NVEL; ib++) { - lb->param->ma[ia][ib] = ma_[ia][ib]; - lb->param->mi[ia][ib] = mi_[ia][ib]; + lb->param->ma[ia][ib] = lb->model.ma[ia][ib]; + lb->param->mi[ia][ib] = lb->model.wv[ia]*lb->model.na[ib]*lb->model.ma[ib][ia]; } } @@ -1604,21 +1607,6 @@ int lb_f_multi_index_set_part(lb_t * lb, int index, int n, return 0; } -/***************************************************************************** - * - * lb_order - * - * Model data ordering - * - *****************************************************************************/ - -__host__ int lb_order(lb_t * lb) { - - assert(lb); - - return lb->model; -} - /***************************************************************************** * * lb_halo_via_copy diff --git a/src/model.h b/src/model.h index b963eab9a..7c9570d2a 100644 --- a/src/model.h +++ b/src/model.h @@ -134,7 +134,6 @@ __host__ __device__ int lb_f_multi_index_set(lb_t * lb, int index, int n, __host__ int lb_nblock(lb_t * lb, int dim, int * nblock); __host__ int lb_init_rest_f(lb_t * lb, double rho0); -__host__ int lb_order(lb_t * lb); __host__ int lb_ndist_set(lb_t * lb, int ndist); __host__ int lb_1st_moment(lb_t * lb, int index, lb_dist_enum_t nd, double g[3]); __host__ int lb_2nd_moment(lb_t * lb, int index, lb_dist_enum_t nd, double s[3][3]); diff --git a/src/model_le.c b/src/model_le.c index 70459c4e4..5ba41dc04 100644 --- a/src/model_le.c +++ b/src/model_le.c @@ -287,7 +287,7 @@ static int le_reproject_all(lb_t * lb, lees_edw_t * le) { for (m = 0; m < NVEL; m++) { mode[m] = 0.0; for (p = 0; p < NVEL; p++) { - mode[m] += lb->f[ndist*NVEL*index + 0 + p]*ma_[m][p]; + mode[m] += lb->f[ndist*NVEL*index + 0 + p]*lb->param->ma[m][p]; } } @@ -311,7 +311,7 @@ static int le_reproject_all(lb_t * lb, lees_edw_t * le) { p = poffset + np; lb->f[ndist*NVEL*index + 0 + p] = 0.0; for (m = 0; m < NVEL; m++) { - lb->f[ndist*NVEL*index + 0 + p] += mode[m]*mi_[p][m]; + lb->f[ndist*NVEL*index + 0 + p] += mode[m]*lb->param->mi[p][m]; } } diff --git a/src/wall.h b/src/wall.h index 7d585d156..b04bd364d 100644 --- a/src/wall.h +++ b/src/wall.h @@ -5,7 +5,7 @@ * Edinburgh Soft Matter and Statistical Physics Group and * Edinburgh Parallel Computing Centre * - * (c) 2011-2020 The University of Edinburgh + * (c) 2011-2021 The University of Edinburgh * * Contributing authors: * Kevin Stratford (kevin@epcc.ed.ac.uk) @@ -19,7 +19,6 @@ #include "pe.h" #include "coords.h" -#include "runtime.h" #include "model.h" #include "map.h" From 730d2e4c8215fd372b7bef3024c7199857d59be6 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Mon, 1 Nov 2021 17:32:41 +0000 Subject: [PATCH 016/117] Remove unused keys --- tests/regression/d2q9/serial-surf-t01.inp | 1 - tests/regression/d2q9/serial-surf-t02.inp | 1 - 2 files changed, 2 deletions(-) diff --git a/tests/regression/d2q9/serial-surf-t01.inp b/tests/regression/d2q9/serial-surf-t01.inp index 8208bf4cb..051510223 100644 --- a/tests/regression/d2q9/serial-surf-t01.inp +++ b/tests/regression/d2q9/serial-surf-t01.inp @@ -91,7 +91,6 @@ colloid_init no_colloids # ############################################################################### -boundary_walls_on no periodicity 1_1_1 ############################################################################### diff --git a/tests/regression/d2q9/serial-surf-t02.inp b/tests/regression/d2q9/serial-surf-t02.inp index bc88ae721..fecc1efbe 100644 --- a/tests/regression/d2q9/serial-surf-t02.inp +++ b/tests/regression/d2q9/serial-surf-t02.inp @@ -85,7 +85,6 @@ colloid_init no_colloids # ############################################################################### -boundary_walls_on no periodicity 1_1_1 ############################################################################### From ee9128c4f4ad2fe528562470ab87642e6f643149 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Mon, 1 Nov 2021 17:33:33 +0000 Subject: [PATCH 017/117] New model type --- tests/unit/test_lb_d2q9.c | 79 +++++++++++++ tests/unit/test_lb_d3q15.c | 75 +++++++++++++ tests/unit/test_lb_d3q19.c | 81 ++++++++++++++ tests/unit/test_lb_model.c | 220 +++++++++++++++++++++++++++++++++++++ tests/unit/test_model.c | 97 +--------------- tests/unit/tests.c | 6 + tests/unit/tests.h | 6 + 7 files changed, 469 insertions(+), 95 deletions(-) create mode 100644 tests/unit/test_lb_d2q9.c create mode 100644 tests/unit/test_lb_d3q15.c create mode 100644 tests/unit/test_lb_d3q19.c create mode 100644 tests/unit/test_lb_model.c diff --git a/tests/unit/test_lb_d2q9.c b/tests/unit/test_lb_d2q9.c new file mode 100644 index 000000000..5c78a2994 --- /dev/null +++ b/tests/unit/test_lb_d2q9.c @@ -0,0 +1,79 @@ +/***************************************************************************** + * + * test_lb_d2q9.c + * + * For general tests, see test_lb_model.c + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#include +#include +#include + +#include "pe.h" +#include "lb_d2q9.h" + +__host__ int test_lb_d2q9_create(void); + +/***************************************************************************** + * + * test_lb_d2q9_suite + * + *****************************************************************************/ + +__host__ int test_lb_d2q9_suite(void) { + + pe_t * pe = NULL; + + pe_create(MPI_COMM_WORLD, PE_QUIET, &pe); + + test_lb_d2q9_create(); + + pe_info(pe, "PASS ./unit/test_lb_d2q9\n"); + + pe_free(pe); + + return 0; +} + +/***************************************************************************** + * + * test_lb_d2q9_create + * + *****************************************************************************/ + +__host__ int test_lb_d2q9_create(void) { + + lb_model_t model = {}; + + lb_d2q9_create(&model); + + assert(model.ndim == 2); + assert(model.nvel == 9); + assert(model.cv); + assert(model.wv); + assert(model.na); + assert(model.ma); + + for (int p = 0; p < model.nvel; p++) { + assert(model.cv[p][Z] == 0); + } + + lb_model_free(&model); + + assert(model.nvel == 0); + assert(model.cv == NULL); + assert(model.wv == NULL); + assert(model.na == NULL); + assert(model.ma == NULL); + + return 0; +} diff --git a/tests/unit/test_lb_d3q15.c b/tests/unit/test_lb_d3q15.c new file mode 100644 index 000000000..8a9861abf --- /dev/null +++ b/tests/unit/test_lb_d3q15.c @@ -0,0 +1,75 @@ +/***************************************************************************** + * + * lb_d3q15.c + * + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#include +#include +#include + +#include "pe.h" +#include "lb_d3q15.h" + +__host__ int test_lb_d3q15_create(void); + +/***************************************************************************** + * + * test_lb_d3q15_suite + * + *****************************************************************************/ + +__host__ int test_lb_d3q15_suite(void) { + + pe_t * pe = NULL; + + pe_create(MPI_COMM_WORLD, PE_QUIET, &pe); + + test_lb_d3q15_create(); + + pe_info(pe, "PASS ./unit/test_lb_d3q15\n"); + + pe_free(pe); + + return 0; +} + +/***************************************************************************** + * + * test_lb_d3q15_create + * + *****************************************************************************/ + +__host__ int test_lb_d3q15_create(void) { + + lb_model_t model = {}; + + lb_d3q15_create(&model); + + assert(model.ndim == 3); + assert(model.nvel == 15); + assert(model.cv); + assert(model.wv); + assert(model.na); + assert(model.ma); + + lb_model_free(&model); + + assert(model.ndim == 0); + assert(model.nvel == 0); + assert(model.cv == NULL); + assert(model.wv == NULL); + assert(model.na == NULL); + assert(model.ma == NULL); + + return 0; +} diff --git a/tests/unit/test_lb_d3q19.c b/tests/unit/test_lb_d3q19.c new file mode 100644 index 000000000..4f5a39727 --- /dev/null +++ b/tests/unit/test_lb_d3q19.c @@ -0,0 +1,81 @@ +/***************************************************************************** + * + * lb_d3q19.c + * + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#include +#include +#include + +#include "pe.h" +#include "lb_d3q19.h" + +__host__ int test_lb_d3q19_create(void); + +/***************************************************************************** + * + * test_lb_d3q19_suite + * + *****************************************************************************/ + +__host__ int test_lb_d3q19_suite(void) { + + pe_t * pe = NULL; + + pe_create(MPI_COMM_WORLD, PE_QUIET, &pe); + + test_lb_d3q19_create(); + + pe_info(pe, "PASS ./unit/test_lb_d3q19\n"); + + pe_free(pe); + + return 0; +} + +/***************************************************************************** + * + * test_lb_d3q19_create + * + * Note. + * The expressions for the ghost currents appearing in Chun and Ladd (2007) + * are not quite consistent; the reason for this is unclear, as I thought + * they used the same set provided by Ronojoy. + * Note that c_x and c_z are transposed in chi1 and chi2 cf Chun and Ladd. + * Could be just typo. + * + *****************************************************************************/ + +__host__ int test_lb_d3q19_create(void) { + + lb_model_t model = {}; + + lb_d3q19_create(&model); + + assert(model.ndim == 3); + assert(model.nvel == 19); + assert(model.cv); + assert(model.wv); + assert(model.na); + assert(model.ma); + + lb_model_free(&model); + + assert(model.nvel == 0); + assert(model.cv == NULL); + assert(model.wv == NULL); + assert(model.na == NULL); + assert(model.ma == NULL); + + return 0; +} diff --git a/tests/unit/test_lb_model.c b/tests/unit/test_lb_model.c new file mode 100644 index 000000000..3188c7539 --- /dev/null +++ b/tests/unit/test_lb_model.c @@ -0,0 +1,220 @@ +/***************************************************************************** + * + * test_lb_model.c + * + * Tests that all model should pass. + * + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#include +#include +#include + +#include "pe.h" +#include "util.h" +#include "lb_model.h" + + +int test_lb_model_create(int nvel); +int test_lb_model_cv(const lb_model_t * model); +int test_lb_model_wv(const lb_model_t * model); +int test_lb_model_ma(const lb_model_t * model); + +/***************************************************************************** + * + * test_lb_model_suite + * + *****************************************************************************/ + +int test_lb_model_suite(void) { + + pe_t * pe = NULL; + + pe_create(MPI_COMM_WORLD, PE_QUIET, &pe); + + test_lb_model_create(9); + test_lb_model_create(15); + test_lb_model_create(19); + + pe_info(pe, "PASS ./unit/test_lb_model\n"); + + pe_free(pe); + + return 0; +} + +/***************************************************************************** + * + * test_lb_model_create + * + *****************************************************************************/ + +int test_lb_model_create(int nvel) { + + lb_model_t model = {}; + + lb_model_create(nvel, &model); + + test_lb_model_cv(&model); + test_lb_model_wv(&model); + test_lb_model_ma(&model); + + lb_model_free(&model); + + return 0; +} + +/***************************************************************************** + * + * test_lb_model_cv + * + *****************************************************************************/ + +int test_lb_model_cv(const lb_model_t * model) { + + int ifail = 0; + + assert(model); + + /* Zero is first */ + assert(model->cv[0][X] == 0); + assert(model->cv[0][Y] == 0); + assert(model->cv[0][Z] == 0); + + /* Check \sum_p cv_pa = 0 */ + + { + int8_t sum[3] = {}; + + for (int p = 0; p < model->nvel; p++) { + sum[X] += model->cv[p][X]; + sum[Y] += model->cv[p][Y]; + sum[Z] += model->cv[p][Z]; + } + assert(sum[X] == 0); + assert(sum[Y] == 0); + assert(sum[Z] == 0); + ifail += (sum[X] + sum[Y] + sum[Z]); + } + + /* Check cv[p][] = -cv[NVEL-p][] (p != 0) */ + + for (int p = 1; p < model->nvel; p++) { + assert(model->cv[p][X] == -model->cv[model->nvel-p][X]); + assert(model->cv[p][Y] == -model->cv[model->nvel-p][Y]); + assert(model->cv[p][Z] == -model->cv[model->nvel-p][Z]); + } + + return ifail; +} + +/***************************************************************************** + * + * test_lb_model_wv + * + *****************************************************************************/ + +int test_lb_model_wv(const lb_model_t * model) { + + assert(model); + + /* Sum of quadrature weights, velocities */ + + { + double sumwv = 0.0; + double sumcv[3] = {}; + + for (int p = 0; p < model->nvel; p++) { + sumwv += model->wv[p]; + sumcv[X] += model->cv[p][X]; + sumcv[Y] += model->cv[p][Y]; + sumcv[Z] += model->cv[p][Z]; + } + /* This can be close... may require 2*epsilon */ + assert(fabs(sumwv - 1.0) <= DBL_EPSILON); + assert(fabs(sumcv[X] - 0.0) <= DBL_EPSILON); + assert(fabs(sumcv[Y] - 0.0) <= DBL_EPSILON); + assert(fabs(sumcv[Z] - 0.0) <= DBL_EPSILON); + } + + /* Quadratic terms \sum_p wv[p] c_pi c_pj = cs2 d_ij */ + + { + for (int ia = 0; ia < model->ndim; ia++) { + for (int ib = 0; ib < model->ndim; ib++) { + double dij = (ia == ib); + double sum = 0.0; + for (int p = 0; p < model->nvel; p++) { + sum += model->wv[p]*model->cv[p][ia]*model->cv[p][ib]; + } + assert(fabs(sum - dij*model->cs2) < DBL_EPSILON); + } + } + } + + return 0; +} + +/***************************************************************************** + * + * test_lb_model_ma + * + *****************************************************************************/ + +int test_lb_model_ma(const lb_model_t * model) { + + assert(model); + + /* Check normalisers \sum_p na[i]*wv[p]*ma[i][p]*ma[j][p] = dij. */ + + for (int i = 0; i < model->nvel; i++) { + for (int j = 0; j < model->nvel; j++) { + double dij = (i == j); + double sum = 0.0; + for (int p = 0; p < model->nvel; p++) { + double ** ma = model->ma; + sum += model->na[i]*model->wv[p]*ma[i][p]*ma[j][p]; + } + /* Just too tight to make DBL_EPSILON ... */ + assert(fabs(sum - dij) < 2*DBL_EPSILON); + } + } + + /* Inverse independent check. */ + + { + int nvel = model->nvel; + double ** mi = NULL; + + util_matrix_create(nvel, nvel, &mi); + + for (int p = 0; p < nvel; p++) { + for (int q = 0; q < nvel; q++) { + mi[p][q] = model->ma[p][q]; + } + } + + util_matrix_invert(nvel, mi); + + for (int p = 0; p < nvel; p++) { + for (int q = 0; q < nvel; q++) { + /* This element of the inverse should be ... */ + double mipq = model->wv[p]*model->na[q]*model->ma[q][p]; + assert(fabs(mipq - mi[p][q]) < DBL_EPSILON); + } + } + + util_matrix_free(nvel, &mi); + } + + return 0; +} diff --git a/tests/unit/test_model.c b/tests/unit/test_model.c index 78de32069..ac4f497f1 100644 --- a/tests/unit/test_model.c +++ b/tests/unit/test_model.c @@ -32,7 +32,6 @@ int do_test_model_distributions(pe_t * pe, cs_t * cs); int do_test_model_halo_swap(pe_t * pe, cs_t * cs); int do_test_model_reduced_halo_swap(pe_t * pe, cs_t * cs); int do_test_lb_model_io(pe_t * pe, cs_t * cs); -int do_test_d3q19_ghosts(void); static int test_model_is_domain(cs_t * cs, int ic, int jc, int kc); /***************************************************************************** @@ -63,7 +62,6 @@ int test_model_suite(void) { do_test_model_reduced_halo_swap(pe, cs); } do_test_lb_model_io(pe, cs); - do_test_d3q19_ghosts(); pe_info(pe, "PASS ./unit/test_model\n"); cs_free(cs); @@ -132,7 +130,6 @@ static void test_model_constants(void) { static void test_model_velocity_set(void) { int i, j, k, p; - double dij; double sum, sumx, sumy, sumz; LB_CS2_DOUBLE(cs2); @@ -230,6 +227,7 @@ static void test_model_velocity_set(void) { } } +#ifdef NEED_TO_BE_MOVED /* Check ma_ against rho, cv conserved quantities */ for (p = 0; p < NVEL; p++) { @@ -251,32 +249,7 @@ static void test_model_velocity_set(void) { } } } - - /* Checking normalisers norm_[i]*wv[p]*ma_[i][p]*ma_[j][p] = dij. */ - - for (i = 0; i < NVEL; i++) { - for (j = 0; j < NVEL; j++) { - dij = (double) (i == j); - sum = 0.0; - for (p = 0; p < NVEL; p++) { - sum += norm_[i]*wv[p]*ma_[i][p]*ma_[j][p]; - } - test_assert(fabs(sum - dij) < TEST_DOUBLE_TOLERANCE); - } - } - - /* Checking ma_[i][p]*mi_[p][j] = dij ... */ - - for (i = 0; i < NVEL; i++) { - for (j = 0; j < NVEL; j++) { - dij = (double) (i == j); - sum = 0.0; - for (p = 0; p < NVEL; p++) { - sum += ma_[i][p]*mi_[p][j]; - } - test_assert(fabs(sum - dij) < TEST_DOUBLE_TOLERANCE); - } - } +#endif return; } @@ -607,69 +580,3 @@ int do_test_lb_model_io(pe_t * pe, cs_t * cs) { return 0; } - -/***************************************************************************** - * - * test_d3q19_ghosts - * - * In comparison with Chen and Ladd (2007) we have - * - * chi1 (2cs^2 - 3)(3c_z^2 - cs^2) mode[10] - * chi2 (2cs^2 - 3)(c_y^2 - c_x^2) mode[14] - * chi3 3cs^4 - 6cs^2 + 1 mode[18] - * - * jchi1 is in fact rho chi3 cv - * jchi1[X] (3*cs^4 - 6cs^2 + 1) cx mode[11] - * jchi1[Y] (3*cs^4 - 6cs^2 + 1) cy mode[12] - * jchi1[Z] (3*cs^4 - 6cs^2 + 1) cz mode[13] - * - * jchi2 is rho chi2 cv - * jchi2[X] (2cs^2 - 3)(c_y^2 - c_x^2) c_x mode[15] - * jchi2[Y] (2cs^2 - 3)(c_y^2 - c_x^2) c_y mode[16] - * jchi2[Z] (2cs^2 - 3)(c_y^2 - c_x^2) c_z mode[17] - * - * The expressions for the ghost currents appearing in Chun and Ladd - * are not quite consistent; the reason for this is unclear. - * Note that c_x and c_z are transposed in chi1 and chi2 cf Chun and Ladd. - * - *****************************************************************************/ - -int do_test_d3q19_ghosts(void) { - - int p; - double rho = 1.0; - double cs2, chi1, chi2, chi3; - double jchi1[3], jchi2[3]; - - if (NVEL != 19) return 0; - - for (p = 0; p < NVEL; p++) { - - cs2 = cv[p][X]*cv[p][X] + cv[p][Y]*cv[p][Y] + cv[p][Z]*cv[p][Z]; - chi1 = (2.0*cs2 - 3.0)*(3.0*cv[p][Z]*cv[p][Z] - cs2); - chi2 = (2.0*cs2 - 3.0)*(cv[p][Y]*cv[p][Y] - cv[p][X]*cv[p][X]); - chi3 = 3.0*cs2*cs2 - 6.0*cs2 + 1; - - jchi1[X] = rho*chi1*cv[p][X]; - jchi1[Y] = rho*chi1*cv[p][Y]; - jchi1[Z] = rho*chi1*cv[p][Z]; - - jchi2[X] = rho*chi2*cv[p][X]; - jchi2[Y] = rho*chi2*cv[p][Y]; - jchi2[Z] = rho*chi2*cv[p][Z]; - - test_assert(fabs(ma_[10][p] - chi1) < TEST_DOUBLE_TOLERANCE); - test_assert(fabs(ma_[14][p] - chi2) < TEST_DOUBLE_TOLERANCE); - test_assert(fabs(ma_[18][p] - chi3) < TEST_DOUBLE_TOLERANCE); - - test_assert(fabs(ma_[11][p] - jchi1[X]) < TEST_DOUBLE_TOLERANCE); - test_assert(fabs(ma_[12][p] - jchi1[Y]) < TEST_DOUBLE_TOLERANCE); - test_assert(fabs(ma_[13][p] - jchi1[Z]) < TEST_DOUBLE_TOLERANCE); - - test_assert(fabs(ma_[15][p] - jchi2[X]) < TEST_DOUBLE_TOLERANCE); - test_assert(fabs(ma_[16][p] - jchi2[Y]) < TEST_DOUBLE_TOLERANCE); - test_assert(fabs(ma_[17][p] - jchi2[Z]) < TEST_DOUBLE_TOLERANCE); - } - - return 0; -} diff --git a/tests/unit/tests.c b/tests/unit/tests.c index 560462d4f..86623ee68 100644 --- a/tests/unit/tests.c +++ b/tests/unit/tests.c @@ -71,6 +71,12 @@ __host__ int tests_create() { test_io_suite(); test_io_options_suite(); test_io_options_rt_suite(); + test_lb_d2q9_suite(); + test_lb_d3q15_suite(); + test_lb_d3q19_suite(); + test_lb_model_suite(); + test_lb_openbc_options_suite(); + test_lb_inflow_rhou_suite(); test_le_suite(); test_lubrication_suite(); test_map_suite(); diff --git a/tests/unit/tests.h b/tests/unit/tests.h index 305257314..48269b938 100644 --- a/tests/unit/tests.h +++ b/tests/unit/tests.h @@ -51,6 +51,12 @@ int test_hydro_suite(void); int test_io_suite(void); int test_io_options_suite(void); int test_io_options_rt_suite(void); +int test_lb_d2q9_suite(void); +int test_lb_d3q15_suite(void); +int test_lb_d3q19_suite(void); +int test_lb_model_suite(void); +int test_lb_openbc_options_suite(void); +int test_lb_inflow_rhou_suite(void); int test_le_suite(void); int test_kernel_suite(void); int test_lubrication_suite(void); From 367b1ea92e0c8816ab24c012a0de0451681abec1 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Mon, 1 Nov 2021 17:33:58 +0000 Subject: [PATCH 018/117] First try open boundary conditions --- tests/unit/test_lb_inflow_rhou.c | 95 +++++++++++++ tests/unit/test_lb_openbc_options.c | 211 ++++++++++++++++++++++++++++ 2 files changed, 306 insertions(+) create mode 100644 tests/unit/test_lb_inflow_rhou.c create mode 100644 tests/unit/test_lb_openbc_options.c diff --git a/tests/unit/test_lb_inflow_rhou.c b/tests/unit/test_lb_inflow_rhou.c new file mode 100644 index 000000000..67ff213b2 --- /dev/null +++ b/tests/unit/test_lb_inflow_rhou.c @@ -0,0 +1,95 @@ +/***************************************************************************** + * + * test_lb_inflow_rhou.c + * + * + *****************************************************************************/ + +#include + +#include "lb_inflow_rhou.c" + +/* Tests */ + +__host__ int test_lb_inflow_rhou_create(pe_t * pe, cs_t * cs); +__host__ int test_lb_inflow_rhou_update(pe_t * pe, cs_t * cs); + +/***************************************************************************** + * + * test_lb_inflow_rhou_suite + * + *****************************************************************************/ + +__host__ int test_lb_inflow_rhou_suite(void) { + + pe_t * pe = NULL; + cs_t * cs = NULL; + + pe_create(MPI_COMM_WORLD, PE_QUIET, &pe); + cs_create(pe, &cs); + cs_init(cs); + + test_lb_inflow_rhou_create(pe, cs); + test_lb_inflow_rhou_update(pe, cs); + + pe_info(pe, "PASS ./unit/test_lb_inflow_rhou\n"); + + cs_free(cs); + pe_free(pe); + + return 0; +} + +/***************************************************************************** + * + * test_lb_inflow_rhou_create + * + *****************************************************************************/ + +__host__ int test_lb_inflow_rhou_create(pe_t * pe, cs_t * cs) { + + lb_openbc_options_t options = lb_openbc_options_default(); + lb_inflow_rhou_t * inflow = NULL; + + assert(pe); + assert(cs); + + lb_inflow_rhou_create(pe, cs, &options, &inflow); + + assert(inflow); + assert(inflow->pe == pe); + assert(inflow->cs = cs); + + assert(inflow->super.func); + assert(inflow->super.id == LB_OPEN_BC_INFLOW_RHOU); + + /* Check options */ + + assert(inflow->options.inflow); + + /* Default options given no links */ + + assert(inflow->nlink == 0); + assert(inflow->linkp); + assert(inflow->linki); + assert(inflow->linkj); + + lb_inflow_rhou_free(inflow); + + return 0; +} + +/***************************************************************************** + * + * test_lb_inflow_rhou_update + * + *****************************************************************************/ + +__host__ int test_lb_inflow_rhou_update(pe_t * pe, cs_t * cs) { + + assert(pe); + assert(cs); + + + return 0; +} diff --git a/tests/unit/test_lb_openbc_options.c b/tests/unit/test_lb_openbc_options.c new file mode 100644 index 000000000..d73989c35 --- /dev/null +++ b/tests/unit/test_lb_openbc_options.c @@ -0,0 +1,211 @@ +/***************************************************************************** + * + * test_lb_openbc_options.c + * + * + * Edinburgh Solft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#include +#include + +#include "lb_openbc_options.h" + +__host__ int test_lb_openbc_options_inflow_default(void); +__host__ int test_lb_openbc_options_outflow_default(void); +__host__ int test_lb_openbc_options_inflow_valid(void); +__host__ int test_lb_openbc_options_outflow_valid(void); +__host__ int test_lb_openbc_options_flow_valid(void); + +/***************************************************************************** + * + * test_lb_openbc_options_suite + * + *****************************************************************************/ + +__host__ int test_lb_openbc_options_suite(void) { + + pe_t * pe = NULL; + + pe_create(MPI_COMM_WORLD, PE_QUIET, &pe); + + test_lb_openbc_options_inflow_default(); + test_lb_openbc_options_outflow_default(); + test_lb_openbc_options_inflow_valid(); + test_lb_openbc_options_outflow_valid(); + test_lb_openbc_options_flow_valid(); + + pe_info(pe, "PASS ./unit/test_lb_openbc_options\n"); + + pe_free(pe); + + return 0; +} + +/***************************************************************************** + * + * test_lb_openbc_options_inflow_default + * + *****************************************************************************/ + +__host__ int test_lb_openbc_options_inflow_default(void) { + + int isvalid = 0; + + { + lb_inflow_enum_t bctype = lb_openbc_options_inflow_default(); + assert(bctype == LB_INFLOW_NONE); + isvalid = lb_openbc_options_inflow_valid(bctype); + } + + return isvalid; +} + +/***************************************************************************** + * + * test_lb_openbc_options_outflow_default + * + *****************************************************************************/ + +__host__ int test_lb_openbc_options_outflow_default(void) { + + int isvalid = 0; + + { + lb_outflow_enum_t bctype = lb_openbc_options_outflow_default(); + + assert(bctype == LB_OUTFLOW_NONE); + isvalid = lb_openbc_options_outflow_valid(bctype); + } + + return isvalid; +} + +/***************************************************************************** + * + * test_lb_openbc_options_default + * + *****************************************************************************/ + +__host__ int test_lb_openbc_options_default(void) { + + int isvalid = 0; + + { + lb_openbc_options_t options = lb_openbc_options_default(); + + assert(options.bctype == 0); + assert(options.inflow == LB_INFLOW_NONE); + assert(options.outflow == LB_OUTFLOW_NONE); + + isvalid = lb_openbc_options_valid(&options); + } + + return isvalid; +} + + + +/***************************************************************************** + * + * test_lb_openbc_options_inflow_valid + * + *****************************************************************************/ + +__host__ int test_lb_openbc_options_inflow_valid(void) { + + int isvalid = 0; + + { + lb_inflow_enum_t bctype = LB_INFLOW_NONE; + + isvalid = lb_openbc_options_inflow_valid(bctype); + assert(isvalid); + } + + { + lb_inflow_enum_t bctype = LB_INFLOW_MAX; + + isvalid = lb_openbc_options_inflow_valid(bctype); + assert(!isvalid); + } + + return isvalid; +} + + +/***************************************************************************** + * + * test_lb_openbc_options_outflow_valid + * + *****************************************************************************/ + +__host__ int test_lb_openbc_options_outflow_valid(void) { + + int isvalid = 0; + + { + lb_outflow_enum_t bctype = LB_OUTFLOW_NONE; + + isvalid = lb_openbc_options_outflow_valid(bctype); + assert(isvalid); + } + + { + lb_outflow_enum_t bctype = LB_OUTFLOW_MAX; + + isvalid = lb_openbc_options_outflow_valid(bctype); + assert(!isvalid); + } + + return isvalid; +} + +/***************************************************************************** + * + * test_lb_openbc_options_flow_valid + * + *****************************************************************************/ + +__host__ int test_lb_openbc_options_flow_valid(void) { + + int isvalid = 0; + + { + int flow[3] = {0, 0, 0}; + + isvalid = lb_openbc_options_flow_valid(flow); + assert(isvalid); + } + + { + int flow[3] = {0, 1, 0}; + + isvalid = lb_openbc_options_flow_valid(flow); + assert(isvalid); + } + + { + int flow[3] = {1, 1, 0}; + + isvalid = lb_openbc_options_flow_valid(flow); + assert(!isvalid); + } + + { + int flow[3] = {1, 1, 1}; + + isvalid = lb_openbc_options_flow_valid(flow); + assert(!isvalid); + } + + return isvalid; +} + From e109cfcca867411b8db804fc56e5e66edcf291ab Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Mon, 1 Nov 2021 17:46:01 +0000 Subject: [PATCH 019/117] Add missing header --- src/lb_open_bc.h | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/lb_open_bc.h diff --git a/src/lb_open_bc.h b/src/lb_open_bc.h new file mode 100644 index 000000000..3a63279b4 --- /dev/null +++ b/src/lb_open_bc.h @@ -0,0 +1,51 @@ +/***************************************************************************** + * + * lb_open_bc.h + * + * Lattice fluid open boundary condition (abstract type). + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#ifndef LUDWIG_LB_OPEN_BC_H +#define LUDWIG_LB_OPEN_BC_H + +#include "hydro.h" +#include "model.h" + +/* Implementations available */ + +typedef enum {LB_OPEN_BC_INFLOW_RHOU} lb_open_bc_enum_t; + +typedef struct lb_open_bc_vtable_s lb_open_bc_vtable_t; +typedef struct lb_open_bc_s lb_open_bc_t; + +/* Abstract function table */ +/* lb_open_bc_free_ft is destructor */ +/* lb_open_bc_update_ft update driver with optional extra info */ +/* lb_open_bc_stats_ft general purpose stats with optional extra info */ + +typedef int (* lb_open_bc_free_ft) (lb_open_bc_t * bc); +typedef int (* lb_open_bc_update_ft) (lb_open_bc_t * bc, hydro_t * hydro, + lb_t * lb); +typedef int (* lb_open_bc_stats_ft) (lb_open_bc_t * bc); + +struct lb_open_bc_vtable_s { + lb_open_bc_free_ft free; /* Desctructor */ + lb_open_bc_update_ft update; /* Update */ + lb_open_bc_stats_ft stats; /* General information */ +}; + +struct lb_open_bc_s { + const lb_open_bc_vtable_t * func; /* function table */ + lb_open_bc_enum_t id; /* unique type identifier */ +}; + +#endif From f3833ba20867df34211943006c0554363ec107e1 Mon Sep 17 00:00:00 2001 From: not populated Date: Fri, 5 Nov 2021 09:03:37 +0000 Subject: [PATCH 020/117] Add emulsion active stress parameters --- src/lc_droplet.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lc_droplet.h b/src/lc_droplet.h index 7999ce720..73f10a08a 100644 --- a/src/lc_droplet.h +++ b/src/lc_droplet.h @@ -8,7 +8,7 @@ * Edinburgh Soft Matter and Statistical Physics Group and * Edinburgh Parallel Computing Centre * - * (c) 2012-2018 The University of Edinburgh + * (c) 2012-2021 The University of Edinburgh * * Contributing authors: * Juho Lintuvuori @@ -45,6 +45,8 @@ struct fe_lc_droplet_param_s { double gamma0; /* \gamma(phi) = gamma0 + delta x (1 + phi) */ double delta; /* As above */ double w; /* Surface anchoring constant */ + double zeta0 ; /* emulsion activity parameter */ + double zeta1; /* emulsion activity parameter */ }; __host__ int fe_lc_droplet_create(pe_t * pe, cs_t * cs, fe_lc_t * lc, From dadd4b383f42e182eddd571b3156ef87721fdd4c Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Fri, 5 Nov 2021 16:05:21 +0000 Subject: [PATCH 021/117] Update some minor buglets --- src/symmetric.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/symmetric.c b/src/symmetric.c index 04e61c765..46d8c294b 100644 --- a/src/symmetric.c +++ b/src/symmetric.c @@ -460,7 +460,7 @@ __host__ int fe_symm_theta_to_h(double theta, double * h) { z = csqrt(4.0*cpow(a1, 2)/a3 + a3 + 1.0/a3 - 2.0); /* May not quite make DBL_EPSILON depending on argument ... */ - if (fabs(cimag(z) > 2.0*DBL_EPSILON)) ierr = -1; + if (fabs(cimag(z)) > 2.0*DBL_EPSILON) ierr = -1; *h = creal(z); @@ -488,13 +488,13 @@ __host__ int fe_symm_h_to_costheta(double h, double * costheta) { int ierr = 0; - if (abs(h) > 1.0) { + if (fabs(h) > 1.0) { ierr = -1; *costheta = -999.999; } else { *costheta = 0.5*(-pow(1.0 - h, 1.5) + pow(1.0 + h, 1.5)); - if (abs(h) > sqrt(2.0*sqrt(3.0) - 3.0)) ierr = -1; + if (fabs(h) > sqrt(2.0*sqrt(3.0) - 3.0)) ierr = -1; } return ierr; From 7b347a0771cd3388ed5837e47f70507ad822c322 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Fri, 5 Nov 2021 16:05:51 +0000 Subject: [PATCH 022/117] Add emulsion active stress --- src/lc_droplet.c | 52 ++++++++++++++++++++++++++++++++++++++++++++- src/lc_droplet_rt.c | 21 +++++++++++++++--- 2 files changed, 69 insertions(+), 4 deletions(-) diff --git a/src/lc_droplet.c b/src/lc_droplet.c index d25dc3995..5ba722310 100644 --- a/src/lc_droplet.c +++ b/src/lc_droplet.c @@ -77,7 +77,9 @@ static __constant__ fe_vt_t fe_drop_dvt = { __host__ __device__ int fe_lc_droplet_anchoring_h(fe_lc_droplet_t * fe, int index, double h[3][3]); - +__host__ __device__ +int fe_lc_droplet_active_stress(const fe_lc_droplet_param_t * fp, double phi, + double q[3][3], double s[3][3]); __global__ void fe_lc_droplet_bf_kernel(kernel_ctxt_t * ktx, fe_lc_droplet_t * fe, @@ -592,6 +594,22 @@ int fe_lc_droplet_str_symm(fe_lc_droplet_t * fe, int index, double sth[3][3]){ } } + + /* Put active stress here (even if zero) */ + + { + double phi = 0; + double sa[3][3] = {}; + + field_scalar(fe->symm->phi, index, &phi); + fe_lc_droplet_active_stress(fe->param, phi, q, sa); + for (ia = 0; ia < 3; ia++) { + for (ib = 0; ib < 3; ib++) { + sth[ia][ib] += sa[ia][ib]; + } + } + } + /* Additional minus sign. */ for (ia = 0; ia < 3; ia++) { @@ -603,6 +621,38 @@ int fe_lc_droplet_str_symm(fe_lc_droplet_t * fe, int index, double sth[3][3]){ return 0; } +/***************************************************************************** + * + * fe_lc_droplet_active_stress + * + * The active stress is + * + * S_ab = [ zeta_1 Q_ab - (1/3) zeta_0 d_ab ] f(phi) + * + * where f(phi) = 0.5(1 + phi) makes phi = +1 the active phase. + * + ****************************************************************************/ + +__host__ __device__ +int fe_lc_droplet_active_stress(const fe_lc_droplet_param_t * fp, double phi, + double q[3][3], double s[3][3]) { + assert(fp); + + { + double r3 = (1.0/3.0); + double fphi = 0.5*(1.0 + phi); + + for (int ia = 0; ia < 3; ia++) { + for (int ib = 0; ib < 3; ib++) { + double d_ab = 1.0*(ia == ib); + s[ia][ib] = fphi*(-r3*fp->zeta0*d_ab - fp->zeta1*q[ia][ib]); + } + } + } + + return 0; +} + /***************************************************************************** * * fe_lc_droplet_str_symm_v diff --git a/src/lc_droplet_rt.c b/src/lc_droplet_rt.c index b1bb56c0a..51befec57 100644 --- a/src/lc_droplet_rt.c +++ b/src/lc_droplet_rt.c @@ -7,7 +7,7 @@ * Edinburgh Soft Matter and Statistical Physics Group * and Edinburgh Parallel Computing Centre * - * (c) 2012-2016 The University of Edinburgh + * (c) 2012-2021 The University of Edinburgh * ****************************************************************************/ @@ -29,7 +29,7 @@ int fe_lc_droplet_run_time(pe_t * pe, rt_t * rt, fe_lc_droplet_t * fe) { int n; - fe_lc_droplet_param_t param; + fe_lc_droplet_param_t param = {}; assert(fe); @@ -44,10 +44,25 @@ int fe_lc_droplet_run_time(pe_t * pe, rt_t * rt, fe_lc_droplet_t * fe) { n = rt_double_parameter(rt, "lc_droplet_W", ¶m.w); if (n == 0) pe_fatal(pe, "Please specify lc_droplet_W in input\n"); - + pe_info(pe, "Isotropic/LC control gamma0 = %12.5e\n", param.gamma0); pe_info(pe, "Isotropic/LC control delta = %12.5e\n", param.delta); pe_info(pe, "Anchoring parameter W = %12.5e\n", param.w); + + { + /* Optional activity parameters */ + int nz0 = 0; + int nz1 = 0; + + nz0 = rt_double_parameter(rt, "lc_droplet_active_zeta0", ¶m.zeta0); + nz1 = rt_double_parameter(rt, "lc_droplet_active_zeta1", ¶m.zeta1); + + if (nz0 || nz1) { + /* Report */ + pe_info(pe, "Emulsion activity: zeta0 = %12.5e\n", param.zeta0); + pe_info(pe, "Emulsion activity: zeta1 = %12.5e\n", param.zeta1); + } + } fe_lc_droplet_param_set(fe, param); From 27a5adb70ef532b39eea6732caae1b6de8fdd5c0 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Fri, 5 Nov 2021 16:07:22 +0000 Subject: [PATCH 023/117] Update active stress implementation --- src/blue_phase.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/blue_phase.c b/src/blue_phase.c index c3b0c98ad..f2d0d1153 100644 --- a/src/blue_phase.c +++ b/src/blue_phase.c @@ -661,7 +661,7 @@ __host__ __device__ int fe_lc_compute_stress_active(fe_lc_t * fe, double s[3][3]) { int ia, ib; KRONECKER_DELTA_CHAR(d); - +#ifdef OLD_SITUATION /* Previously comment said: -zeta*(q_ab - 1/3 d_ab) * while code was -zeta*(q[ia][ib] + r3*d[ia][ib]) * for zeta = zeta1 */ @@ -674,6 +674,16 @@ __host__ __device__ int fe_lc_compute_stress_active(fe_lc_t * fe, - fe->param->zeta2*(dp[ia][ib] + dp[ib][ia]); } } +#else + /* The documented approach */ + for (ia = 0; ia < 3; ia++) { + for (ib = 0; ib < 3; ib++) { + s[ia][ib] = fe->param->zeta0*d[ia][ib] + - fe->param->zeta1*q[ia][ib] + - fe->param->zeta2*(dp[ia][ib] + dp[ib][ia]); + } + } +#endif /* This is an extra minus sign for the divergance. */ From 4039e38ebd2e85286a1b2aeabe09f1e09494a5db Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Fri, 5 Nov 2021 16:07:50 +0000 Subject: [PATCH 024/117] Allow missing lc_gamma if droplet fe --- src/blue_phase_rt.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/blue_phase_rt.c b/src/blue_phase_rt.c index cf7051bfe..9b6dd49fe 100644 --- a/src/blue_phase_rt.c +++ b/src/blue_phase_rt.c @@ -38,6 +38,7 @@ __host__ int blue_phase_init_rt(pe_t * pe, rt_t *rt, fe_lc_t * fe, beris_edw_t * be) { int n; + int fe_is_lc_droplet = 0; int redshift_update; char method[BUFSIZ] = "none"; char type[BUFSIZ] = "none"; @@ -70,13 +71,21 @@ __host__ int blue_phase_init_rt(pe_t * pe, rt_t *rt, pe_info(pe, "Blue phase free energy selected.\n"); + { + char description[BUFSIZ] = {}; + rt_string_parameter(rt, "free_energy", description, BUFSIZ); + fe_is_lc_droplet = (strcmp(description, "lc_droplet") == 0); + } /* PARAMETERS */ + /* Note that for LC droplet, we should not specify gamma here. */ n = rt_double_parameter(rt, "lc_a0", &fe_param.a0); if (n != 1) pe_fatal(pe, "Please specify lc_a0 \n"); n = rt_double_parameter(rt, "lc_gamma", &fe_param.gamma); - if (n != 1) pe_fatal(pe, "Please specify lc_gamma \n"); + if (n != 1 && fe_is_lc_droplet == 0) { + pe_fatal(pe, "Please specify lc_gamma \n"); + } n = rt_double_parameter(rt, "lc_q0", &fe_param.q0); if (n != 1) pe_fatal(pe, "Please specify lc_q0 \n"); @@ -133,7 +142,6 @@ __host__ int blue_phase_init_rt(pe_t * pe, rt_t *rt, /* Active stress is: * s_ab = zeta0 d_ab - zeta1 Q_ab - zeta2 (d_a p_b + d_b p_a) * with p_a = Q_ak d_m Q_mk - * The sign of zeta0 is currently +ve here (clarify). */ fe_param.is_active = rt_switch(rt, "lc_activity"); @@ -141,7 +149,7 @@ __host__ int blue_phase_init_rt(pe_t * pe, rt_t *rt, fe_param.is_active == 0 ? "No" : "Yes"); if (fe_param.is_active) { - zeta0 = (1.0/3.0); + zeta0 = 0.0; zeta1 = 0.0; zeta2 = 0.0; rt_double_parameter(rt, "lc_active_zeta0", &zeta0); From fe1f4524817efa36ceb3e4ffe3f5cf29c55f8003 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Fri, 5 Nov 2021 16:08:28 +0000 Subject: [PATCH 025/117] Add tests --- tests/unit/test_fe_lc_droplet.c | 151 ++++++++++++++++++++++++++++++++ tests/unit/tests.c | 1 + tests/unit/tests.h | 1 + 3 files changed, 153 insertions(+) create mode 100644 tests/unit/test_fe_lc_droplet.c diff --git a/tests/unit/test_fe_lc_droplet.c b/tests/unit/test_fe_lc_droplet.c new file mode 100644 index 000000000..62eff719a --- /dev/null +++ b/tests/unit/test_fe_lc_droplet.c @@ -0,0 +1,151 @@ +/***************************************************************************** + * + * test_fe_lc_droplet.c + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#include +#include +#include + +#include "lc_droplet.h" + +/* Forward declarations some additional testable routines */ + +int fe_lc_droplet_active_stress(const fe_lc_droplet_param_t * fp, double phi, + double q[3][3], double s[3][3]); + +/* Tests */ + +int test_fe_lc_droplet_active_stress(pe_t * pe); + +/***************************************************************************** + * + * test_fe_lc_droplet_suite + * + *****************************************************************************/ + +int test_fe_lc_droplet_suite() { + + pe_t * pe = NULL; + + pe_create(MPI_COMM_WORLD, PE_QUIET, &pe); + + test_fe_lc_droplet_active_stress(pe); + + pe_info(pe, "PASS ./unit/test_fe_lc_droplet\n"); + pe_free(pe); + + return 0; +} + +/***************************************************************************** + * + * test_fe_lc_droplet_active_stress + * + *****************************************************************************/ + +__host__ int test_fe_lc_droplet_active_stress(pe_t * pe) { + + assert(pe); + + /* zeta_0 dependence */ + + { + double zeta0 = 2.0; + double zeta1 = 0.0; + double phi = 1.0; + fe_lc_droplet_param_t fp = {.zeta0 = zeta0, .zeta1 = zeta1}; + + double q[3][3] = {}; + double s[3][3] = {}; + + fe_lc_droplet_active_stress(&fp, phi, q, s); + + assert(fabs(s[X][X] - (-2.0/3.0)) < DBL_EPSILON); + assert(fabs(s[X][Y] - ( 0.0 )) < DBL_EPSILON); + assert(fabs(s[X][Z] - ( 0.0 )) < DBL_EPSILON); + + assert(fabs(s[Y][X] - ( 0.0 )) < DBL_EPSILON); + assert(fabs(s[Y][Y] - (-2.0/3.0)) < DBL_EPSILON); + assert(fabs(s[Y][Z] - ( 0.0 )) < DBL_EPSILON); + + assert(fabs(s[Z][X] - ( 0.0 )) < DBL_EPSILON); + assert(fabs(s[Z][Y] - ( 0.0 )) < DBL_EPSILON); + assert(fabs(s[Z][Z] - (-2.0/3.0)) < DBL_EPSILON); + } + + /* zeta_1 q_ab dependence; requires q_ab */ + + { + double zeta0 = 0.0; + double zeta1 = 2.0; + double phi = 1.0; + fe_lc_droplet_param_t fp = {.zeta0 = zeta0, .zeta1 = zeta1}; + + double q[3][3] = { {1., 2., 3.,}, {2., 4., 5.}, {3., 5., -3.} }; + double s[3][3] = {}; + + fe_lc_droplet_active_stress(&fp, phi, q, s); + + assert(fabs(s[X][X] - (-q[X][X]*zeta1)) < DBL_EPSILON); + assert(fabs(s[X][Y] - (-q[X][Y]*zeta1)) < DBL_EPSILON); + assert(fabs(s[X][Z] - (-q[X][Z]*zeta1)) < DBL_EPSILON); + + assert(fabs(s[Y][X] - (-q[Y][X]*zeta1)) < DBL_EPSILON); + assert(fabs(s[Y][Y] - (-q[Y][Y]*zeta1)) < DBL_EPSILON); + assert(fabs(s[Y][Z] - (-q[Y][Z]*zeta1)) < DBL_EPSILON); + + assert(fabs(s[Z][X] - (-q[Z][X]*zeta1)) < DBL_EPSILON); + assert(fabs(s[Z][Y] - (-q[Z][Y]*zeta1)) < DBL_EPSILON); + assert(fabs(s[Z][Z] - (-q[Z][Z]*zeta1)) < DBL_EPSILON); + } + + /* phi dependence */ + + { + double zeta0 = 0.0; + double zeta1 = 1.0; + fe_lc_droplet_param_t fp = {.zeta0 = zeta0, .zeta1 = zeta1}; + + double q[3][3] = { {1., 1., 1.,}, {1., 1., 1.}, {1., 1., 1.} }; + double s[3][3] = {}; + + double phi = -1.0; + + fe_lc_droplet_active_stress(&fp, phi, q, s); + + assert(fabs(s[X][X] - 0.0) < DBL_EPSILON); + assert(fabs(s[X][Y] - 0.0) < DBL_EPSILON); + assert(fabs(s[X][Z] - 0.0) < DBL_EPSILON); + assert(fabs(s[Y][X] - 0.0) < DBL_EPSILON); + assert(fabs(s[Y][Y] - 0.0) < DBL_EPSILON); + assert(fabs(s[Y][Z] - 0.0) < DBL_EPSILON); + assert(fabs(s[Z][X] - 0.0) < DBL_EPSILON); + assert(fabs(s[Z][Y] - 0.0) < DBL_EPSILON); + assert(fabs(s[Z][Z] - 0.0) < DBL_EPSILON); + + phi = 0.0; + fe_lc_droplet_active_stress(&fp, phi, q, s); + + assert(fabs(s[X][X] - (-0.5)) < DBL_EPSILON); + assert(fabs(s[X][Y] - (-0.5)) < DBL_EPSILON); + assert(fabs(s[X][Z] - (-0.5)) < DBL_EPSILON); + assert(fabs(s[Y][X] - (-0.5)) < DBL_EPSILON); + assert(fabs(s[Y][Y] - (-0.5)) < DBL_EPSILON); + assert(fabs(s[Y][Z] - (-0.5)) < DBL_EPSILON); + assert(fabs(s[Z][X] - (-0.5)) < DBL_EPSILON); + assert(fabs(s[Z][Y] - (-0.5)) < DBL_EPSILON); + assert(fabs(s[Z][Z] - (-0.5)) < DBL_EPSILON); + } + + return 0; +} diff --git a/tests/unit/tests.c b/tests/unit/tests.c index 560462d4f..d430f5efe 100644 --- a/tests/unit/tests.c +++ b/tests/unit/tests.c @@ -64,6 +64,7 @@ __host__ int tests_create() { test_ewald_suite(); test_fe_electro_suite(); test_fe_electro_symm_suite(); + test_fe_lc_droplet_suite(); test_field_suite(); test_field_grad_suite(); test_halo_suite(); diff --git a/tests/unit/tests.h b/tests/unit/tests.h index 305257314..4c477c131 100644 --- a/tests/unit/tests.h +++ b/tests/unit/tests.h @@ -41,6 +41,7 @@ int test_coords_suite(void); int test_ewald_suite(void); int test_fe_electro_suite(void); int test_fe_electro_symm_suite(void); +int test_fe_lc_droplet_suite(void); int test_fe_surfactant1_suite(void); int test_fe_symmetric_suite(void); int test_fe_ternary_suite(void); From 1d36a8f4fc1cc32a63464ce79024aa7253ac8607 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Fri, 5 Nov 2021 16:08:40 +0000 Subject: [PATCH 026/117] Minor update --- tests/unit/test_fe_symmetric.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/test_fe_symmetric.c b/tests/unit/test_fe_symmetric.c index 7e14d1109..0a7499798 100644 --- a/tests/unit/test_fe_symmetric.c +++ b/tests/unit/test_fe_symmetric.c @@ -72,7 +72,7 @@ int test_fe_symm_theta_to_h(pe_t * pe) { ierr += fe_symm_theta_to_h(theta, &h); assert(ierr == 0); - assert(fabs(h - sqrt(2.0*sqrt(3.0) - 3.0)) < DBL_EPSILON); + assert(fabs(h - sqrt(2.0*sqrt(3.0) - 3.0)) < 2.0*DBL_EPSILON); } return ierr; From 39059da3ccfdcd5382cdf0f18d0dec4158d81020 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Fri, 5 Nov 2021 16:09:07 +0000 Subject: [PATCH 027/117] Update active stress to documented implementation --- tests/regression/d3q19-short/serial-actv-s01.inp | 1 + tests/regression/d3q19-short/serial-actv-s02.inp | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/regression/d3q19-short/serial-actv-s01.inp b/tests/regression/d3q19-short/serial-actv-s01.inp index 068db28ad..c45d2e377 100644 --- a/tests/regression/d3q19-short/serial-actv-s01.inp +++ b/tests/regression/d3q19-short/serial-actv-s01.inp @@ -54,6 +54,7 @@ lc_xi 0.7 lc_Gamma 0.3375 lc_activity yes +lc_active_zeta0 0.33333333333333333 lc_active_zeta1 0.005 lc_q_initialisation active_nematic_q2d_y diff --git a/tests/regression/d3q19-short/serial-actv-s02.inp b/tests/regression/d3q19-short/serial-actv-s02.inp index 5652a9452..0c2c5fbda 100644 --- a/tests/regression/d3q19-short/serial-actv-s02.inp +++ b/tests/regression/d3q19-short/serial-actv-s02.inp @@ -53,6 +53,7 @@ lc_xi 0.7 lc_Gamma 0.3375 lc_activity yes +lc_active_zeta0 0.333333333333333 lc_active_zeta1 0.05 lc_q_initialisation active_nematic_q2d_y From 330e7b9f77d05792a5dcf60fb55aea02b9057f06 Mon Sep 17 00:00:00 2001 From: not populated Date: Fri, 5 Nov 2021 17:46:07 +0000 Subject: [PATCH 028/117] Pad to avoid false sharing in host version --- src/hydro.c | 64 ++++++++++++++++++++++++++------------------ target/target_cuda.h | 1 + target/target_hip.h | 1 + target/target_x86.h | 1 + 4 files changed, 41 insertions(+), 26 deletions(-) diff --git a/src/hydro.c b/src/hydro.c index 52dbbc63c..65d113461 100644 --- a/src/hydro.c +++ b/src/hydro.c @@ -1001,18 +1001,17 @@ __global__ void hydro_accumulate_kernel(kernel_ctxt_t * ktx, hydro_t * hydro, int kiterations; int tid; - double fxb, fyb, fzb; - __shared__ double fx[TARGET_MAX_THREADS_PER_BLOCK]; - __shared__ double fy[TARGET_MAX_THREADS_PER_BLOCK]; - __shared__ double fz[TARGET_MAX_THREADS_PER_BLOCK]; + __shared__ double fx[TARGET_PAD*TARGET_MAX_THREADS_PER_BLOCK]; + __shared__ double fy[TARGET_PAD*TARGET_MAX_THREADS_PER_BLOCK]; + __shared__ double fz[TARGET_PAD*TARGET_MAX_THREADS_PER_BLOCK]; assert(ktx); assert(hydro); tid = threadIdx.x; - fx[tid] = 0.0; - fy[tid] = 0.0; - fz[tid] = 0.0; + fx[TARGET_PAD*tid] = 0.0; + fy[TARGET_PAD*tid] = 0.0; + fz[TARGET_PAD*tid] = 0.0; kiterations = kernel_iterations(ktx); @@ -1027,17 +1026,24 @@ __global__ void hydro_accumulate_kernel(kernel_ctxt_t * ktx, hydro_t * hydro, index = kernel_coords_index(ktx, ic, jc, kc); hydro_f_local(hydro, index, f); - fx[tid] += f[X]; - fy[tid] += f[Y]; - fz[tid] += f[Z]; + fx[TARGET_PAD*tid] += f[X]; + fy[TARGET_PAD*tid] += f[Y]; + fz[TARGET_PAD*tid] += f[Z]; } + __syncthreads(); + /* Reduction */ - fxb = tdpAtomicBlockAddDouble(fx); - fyb = tdpAtomicBlockAddDouble(fy); - fzb = tdpAtomicBlockAddDouble(fz); if (tid == 0) { + double fxb = 0.0; + double fyb = 0.0; + double fzb = 0.0; + for (int it = 0; it < blockDim.x; it++) { + fxb += fx[TARGET_PAD*it]; + fyb += fy[TARGET_PAD*it]; + fzb += fz[TARGET_PAD*it]; + } tdpAtomicAddDouble(fnet + X, fxb); tdpAtomicAddDouble(fnet + Y, fyb); tdpAtomicAddDouble(fnet + Z, fzb); @@ -1061,18 +1067,17 @@ __global__ void hydro_accumulate_kernel_v(kernel_ctxt_t * ktx, hydro_t * hydro, int kiterations; int tid; - double fxb, fyb, fzb; - __shared__ double fx[TARGET_MAX_THREADS_PER_BLOCK]; - __shared__ double fy[TARGET_MAX_THREADS_PER_BLOCK]; - __shared__ double fz[TARGET_MAX_THREADS_PER_BLOCK]; + __shared__ double fx[TARGET_PAD*TARGET_MAX_THREADS_PER_BLOCK]; + __shared__ double fy[TARGET_PAD*TARGET_MAX_THREADS_PER_BLOCK]; + __shared__ double fz[TARGET_PAD*TARGET_MAX_THREADS_PER_BLOCK]; assert(ktx); assert(hydro); tid = threadIdx.x; - fx[tid] = 0.0; - fy[tid] = 0.0; - fz[tid] = 0.0; + fx[TARGET_PAD*tid] = 0.0; + fy[TARGET_PAD*tid] = 0.0; + fz[TARGET_PAD*tid] = 0.0; kiterations = kernel_vector_iterations(ktx); @@ -1092,17 +1097,24 @@ __global__ void hydro_accumulate_kernel_v(kernel_ctxt_t * ktx, hydro_t * hydro, f[ia] = ftmp; } - fx[tid] += f[X]; - fy[tid] += f[Y]; - fz[tid] += f[Z]; + fx[TARGET_PAD*tid] += f[X]; + fy[TARGET_PAD*tid] += f[Y]; + fz[TARGET_PAD*tid] += f[Z]; } + __syncthreads(); + /* Reduction */ - fxb = tdpAtomicBlockAddDouble(fx); - fyb = tdpAtomicBlockAddDouble(fy); - fzb = tdpAtomicBlockAddDouble(fz); if (tid == 0) { + double fxb = 0.0; + double fyb = 0.0; + double fzb = 0.0; + for (int it = 0; it < blockDim.x; it++) { + fxb += fx[8*it]; + fyb += fy[8*it]; + fzb += fz[8*it]; + } tdpAtomicAddDouble(fnet + X, fxb); tdpAtomicAddDouble(fnet + Y, fyb); tdpAtomicAddDouble(fnet + Z, fzb); diff --git a/target/target_cuda.h b/target/target_cuda.h index d39076af3..1be96e07e 100644 --- a/target/target_cuda.h +++ b/target/target_cuda.h @@ -48,6 +48,7 @@ typedef cudaError_t tdpError_t; #define TARGET_MAX_THREADS_PER_BLOCK 128 +#define TARGET_PAD 1 /* Macros for calls involing device symbols */ diff --git a/target/target_hip.h b/target/target_hip.h index 62f2c99ac..0aef26f55 100644 --- a/target/target_hip.h +++ b/target/target_hip.h @@ -50,6 +50,7 @@ typedef hipError_t tdpError_t; #define TARGET_MAX_THREADS_PER_BLOCK 128 +#define TARGET_PAD 1 /* Macros for calls involing device symbols */ diff --git a/target/target_x86.h b/target/target_x86.h index d6ab9c4d6..eb9da5051 100644 --- a/target/target_x86.h +++ b/target/target_x86.h @@ -163,6 +163,7 @@ void tdp_x86_postlaunch(void); #include #define TARGET_MAX_THREADS_PER_BLOCK 256 +#define TARGET_PAD 8 #define __syncthreads() _Pragma("omp barrier") #define __threadfence() /* only __syncthreads() is a barrier */ From f1bfd2fc12ccebf31bb0cc02ca17905d5cdffc8b Mon Sep 17 00:00:00 2001 From: not populated Date: Fri, 5 Nov 2021 17:49:13 +0000 Subject: [PATCH 029/117] Active stress update --- CHANGES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 6c885a6a3..bfb4c1fad 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,10 @@ ### Changes +version 0.15.0 + +- Active stress implementation is updated to conform to the documented + case; active emulsion stress is available. version 0.14.0 From 5d716b09dfe3cb1e88e219f5b2b2665ce8e66809 Mon Sep 17 00:00:00 2001 From: not populated Date: Tue, 9 Nov 2021 08:36:43 +0000 Subject: [PATCH 030/117] Remember TARGET_PAD in non-OpenMP --- target/target_x86.h | 1 + 1 file changed, 1 insertion(+) diff --git a/target/target_x86.h b/target/target_x86.h index eb9da5051..d3dedd342 100644 --- a/target/target_x86.h +++ b/target/target_x86.h @@ -194,6 +194,7 @@ void tdp_x86_postlaunch(void); #else /* Not OPENMP */ #define TARGET_MAX_THREADS_PER_BLOCK 1 +#define TARGET_PAD 1 #define omp_get_num_threads() 1 #define omp_get_thread_num() 0 #define omp_get_max_threads() 1 From afa6f3de0e79c7eb9d4e2dfb8e7473bc450a36de Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Tue, 9 Nov 2021 15:47:51 +0000 Subject: [PATCH 031/117] Remove unused vector routines --- src/model.c | 161 ---------------------------------------------------- src/model.h | 17 +----- 2 files changed, 3 insertions(+), 175 deletions(-) diff --git a/src/model.c b/src/model.c index c43503bf9..2f3c73497 100644 --- a/src/model.c +++ b/src/model.c @@ -1446,167 +1446,6 @@ int lb_1st_moment_equilib_set(lb_t * lb, int index, double rho, double u[3]) { return 0; } -/***************************************************************************** - * - * lb_f_index - * - * Return the distribution n at index. - * - *****************************************************************************/ - -__host__ __device__ -int lb_f_index(lb_t * lb, int index, int n, double f[NVEL]) { - - int p; - - assert(lb); - assert(n >= 0 && n < lb->ndist); - assert(index >= 0 && index < lb->nsite); - - for (p = 0; p < NVEL; p++) { - f[p] = lb->f[LB_ADDR(lb->nsite, lb->ndist, NVEL, index, n, p)]; - } - - return 0; -} - - -/***************************************************************************** - * - * lb_f_multi_index - * - * Return a vector of distributions starting at index - * where the vector length is fixed at NSIMDVL - * - *****************************************************************************/ - -__host__ __device__ -int lb_f_multi_index(lb_t * lb, int index, int n, double fv[NVEL][NSIMDVL]) { - - int p, iv; - - assert(lb); - assert(n >= 0 && n < lb->ndist); - assert(index >= 0 && index < lb->nsite); - - for (p = 0; p < NVEL; p++) { - for (iv = 0; iv < NSIMDVL; iv++) { - fv[p][iv] = lb->f[LB_ADDR(lb->nsite, lb->ndist, NVEL, index + iv, n, p)]; - } - } - - return 0; -} - -/***************************************************************************** - * - * lb_multi_index_part - * - * Return a vector of distributions starting at index - * where the vector length is passed in at runtime - * - *****************************************************************************/ - -__host__ __device__ -int lb_f_multi_index_part(lb_t * lb, int index, int n, double fv[NVEL][NSIMDVL], - int nv) { - - int p, iv; - - assert(lb); - assert(n >= 0 && n < lb->ndist); - assert(index >= 0 && index < lb->nsite); - assert(0); /* Not used */ - - for (p = 0; p < NVEL; p++) { - for (iv = 0; iv < nv; iv++) { - fv[p][iv] = lb->f[LB_ADDR(lb->nsite, lb->ndist, NVEL, index + iv, n, p)]; - } - } - - return 0; -} - - -/***************************************************************************** - * - * lb_index_set - * - * Set distribution n and index. - * - *****************************************************************************/ - -__host__ __device__ -int lb_f_index_set(lb_t * lb, int index, int n, double f[NVEL]) { - - int p; - - assert(lb); - assert(n >= 0 && n < lb->ndist); - assert(index >= 0 && index < lb->nsite); - - for (p = 0; p < NVEL; p++) { - lb->f[LB_ADDR(lb->nsite, lb->ndist, NVEL, index, n, p)] = f[p]; - } - - return 0; -} - - -/***************************************************************************** - * - * lb_f_multi_index_set - * - * Set a vector of distributions starting at index - * where the vector length is fixed at NSIMDVL - * - *****************************************************************************/ - -__host__ __device__ -int lb_f_multi_index_set(lb_t * lb, int index, int n, double fv[NVEL][NSIMDVL]){ - - int p, iv; - - assert(lb); - assert(n >= 0 && n < lb->ndist); - assert(index >= 0 && index < lb->nsite); - assert(0); - for (p = 0; p < NVEL; p++) { - for (iv = 0; iv < NSIMDVL; iv++) { - lb->f[LB_ADDR(lb->nsite, lb->ndist, NVEL, index + iv, n, p)] = fv[p][iv]; - } - } - - return 0; -} - -/***************************************************************************** - * - * lb_f_multi_index_set_part - * - * Set a vector of distributions starting at index - * where the vector length is passed in at runtime - * - *****************************************************************************/ - -__host__ __device__ -int lb_f_multi_index_set_part(lb_t * lb, int index, int n, - double fv[NVEL][NSIMDVL], int nv) { - int p, iv; - - assert(lb); - assert(n >= 0 && n < lb->ndist); - assert(index >= 0 && index < lb->nsite); - assert(0); - for (p = 0; p < NVEL; p++) { - for (iv = 0; iv < nv; iv++) { - lb->f[LB_ADDR(lb->nsite, lb->ndist, NVEL, index + iv, n, p)] = fv[p][iv]; - } - } - - return 0; -} - /***************************************************************************** * * lb_halo_via_copy diff --git a/src/model.h b/src/model.h index 7c9570d2a..d83926797 100644 --- a/src/model.h +++ b/src/model.h @@ -8,7 +8,7 @@ * Edinburgh Soft Matter and Statistical Physics Group and * Edinburgh Parallel Computing Centre * - * (c) 2010-2020 The University of Edinburgh + * (c) 2010-2021 The University of Edinburgh * * Contributing authors: * Kevin Stratford (kevin@epcc.ed.ac.uk) @@ -92,6 +92,8 @@ typedef enum lb_halo_enum_type {LB_HALO_FULL, typedef enum {LB_RELAXATION_M10, LB_RELAXATION_BGK, LB_RELAXATION_TRT} lb_relaxation_enum_t; +#include "lb_model_s.h" + __host__ int lb_create_ndist(pe_t * pe, cs_t * cs, int ndist, lb_t ** lb); __host__ int lb_create(pe_t * pe, cs_t * cs, lb_t ** lb); __host__ int lb_init(lb_t * lb); @@ -116,19 +118,6 @@ __host__ __device__ int lb_f(lb_t * lb, int index, int p, int n, double * f); __host__ __device__ int lb_f_set(lb_t * lb, int index, int p, int n, double f); __host__ __device__ int lb_0th_moment(lb_t * lb, int index, lb_dist_enum_t nd, double * rho); -__host__ __device__ int lb_f_index(lb_t * lb, int index, int n, double f[NVEL]); -__host__ __device__ int lb_f_index_set(lb_t * lb, int index, int n, - double f[NVEL]); -__host__ __device__ int lb_f_multi_index_part(lb_t * lb, int index, int n, - double f[NVEL][NSIMDVL], int nv); -__host__ __device__ int lb_f_multi_index_set_part(lb_t * lb, int index, int n, - double f[NVEL][NSIMDVL], - int nv); -__host__ __device__ int lb_f_multi_index(lb_t * lb, int index, int n, - double f[NVEL][NSIMDVL]); -__host__ __device__ int lb_f_multi_index_set(lb_t * lb, int index, int n, - double f[NVEL][NSIMDVL]); - /* These could be __host__ __device__ pending removal of * static constants */ From 4772b0cf5aba01aaed00fde3c7a20ba455fbd9e2 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Tue, 9 Nov 2021 15:52:02 +0000 Subject: [PATCH 032/117] Add explicit density field --- src/hydro.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++- src/hydro.h | 5 ++++- 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/src/hydro.c b/src/hydro.c index 52dbbc63c..5a99bbe38 100644 --- a/src/hydro.c +++ b/src/hydro.c @@ -7,7 +7,7 @@ * Edinburgh Soft Matter and Statistical Physics Group and * Edinburgh Parallel Computing Centre * - * (c) 2012-2020 The University of Edinburgh + * (c) 2012-2021 The University of Edinburgh * * Contributing authors: * Kevin Stratford (kevin@epcc.ed.ac.uk) @@ -76,8 +76,11 @@ __host__ int hydro_create(pe_t * pe, cs_t * cs, lees_edw_t * le, int nhcomm, cs_nsites(cs, &obj->nsite); if (le) lees_edw_nsites(le, &obj->nsite); + obj->rho = (double *) mem_aligned_calloc(MEM_PAGESIZE, obj->nsite, + sizeof(double)); obj->u = (double *) mem_aligned_calloc(MEM_PAGESIZE, NHDIM*obj->nsite, sizeof(double)); + if (obj->rho == NULL) pe_fatal(pe, "calloc(hydro-rho) failed\n"); if (obj->u == NULL) pe_fatal(pe, "calloc(hydro->u) failed\n"); obj->f = (double *) mem_aligned_calloc(MEM_PAGESIZE, NHDIM*obj->nsite, @@ -105,6 +108,11 @@ __host__ int hydro_create(pe_t * pe, cs_t * cs, lees_edw_t * le, int nhcomm, tdpAssert(tdpMalloc((void **) &obj->target, sizeof(hydro_t))); tdpAssert(tdpMemset(obj->target, 0, sizeof(hydro_t))); + tdpAssert(tdpMalloc((void **) &tmp, obj->nsite*sizeof(double))); + tdpAssert(tdpMemset(tmp, 0, obj->nsite*sizeof(double))); + tdpAssert(tdpMemcpy(&obj->target->rho, &tmp, sizeof(double *), + tdpMemcpyHostToDevice)); + tdpAssert(tdpMalloc((void **) &tmp, NHDIM*obj->nsite*sizeof(double))); tdpAssert(tdpMemset(tmp, 0, NHDIM*obj->nsite*sizeof(double))); tdpAssert(tdpMemcpy(&obj->target->u, &tmp, sizeof(double *), @@ -145,6 +153,11 @@ __host__ int hydro_free(hydro_t * obj) { tdpGetDeviceCount(&ndevice); if (ndevice > 0) { + + tdpAssert(tdpMemcpy(&tmp, &obj->target->rho, sizeof(double *), + tdpMemcpyDeviceToHost)); + tdpAssert(tdpFree(tmp)); + tdpAssert(tdpMemcpy(&tmp, &obj->target->u, sizeof(double *), tdpMemcpyDeviceToHost)); tdpAssert(tdpFree(tmp)); @@ -162,6 +175,7 @@ __host__ int hydro_free(hydro_t * obj) { free(obj->eta); free(obj->f); free(obj->u); + free(obj->rho); free(obj); return 0; @@ -189,6 +203,10 @@ __host__ int hydro_memcpy(hydro_t * obj, tdpMemcpyKind flag) { assert(obj->target == obj); } else { + double * tmprho = NULL; + + tdpAssert(tdpMemcpy(&tmprho, &obj->target->rho, sizeof(double *), + tdpMemcpyDeviceToHost)); tdpAssert(tdpMemcpy(&tmpf, &obj->target->f, sizeof(double *), tdpMemcpyDeviceToHost)); tdpAssert(tdpMemcpy(&tmpu, &obj->target->u, sizeof(double *), @@ -198,12 +216,14 @@ __host__ int hydro_memcpy(hydro_t * obj, tdpMemcpyKind flag) { switch (flag) { case tdpMemcpyHostToDevice: + tdpAssert(tdpMemcpy(tmprho, obj->rho, obj->nsite*sizeof(double), flag)); tdpAssert(tdpMemcpy(tmpu, obj->u, NHDIM*obj->nsite*sizeof(double), flag)); tdpAssert(tdpMemcpy(tmpf, obj->f, NHDIM*obj->nsite*sizeof(double), flag)); tdpAssert(tdpMemcpy(tmpeta, obj->eta, obj->nsite*sizeof(double), flag)); tdpAssert(tdpMemcpy(&obj->target->nsite, &obj->nsite, sizeof(int), flag)); break; case tdpMemcpyDeviceToHost: + tdpAssert(tdpMemcpy(obj->rho, tmprho, obj->nsite*sizeof(double), flag)); tdpAssert(tdpMemcpy(obj->f, tmpf, NHDIM*obj->nsite*sizeof(double), flag)); tdpAssert(tdpMemcpy(obj->u, tmpu, NHDIM*obj->nsite*sizeof(double), flag)); tdpAssert(tdpMemcpy(obj->eta, tmpeta, obj->nsite*sizeof(double), flag)); @@ -235,6 +255,9 @@ __host__ int hydro_u_halo(hydro_t * obj) { * * hydro_halo_swap * + * There is no halo swap in the density at the moment, as it is never + * required. + * *****************************************************************************/ __host__ int hydro_halo_swap(hydro_t * obj, hydro_halo_enum_t flag) { @@ -378,6 +401,37 @@ int hydro_f_local_add(hydro_t * obj, int index, const double force[3]) { return 0; } +/***************************************************************************** + * + * hydro_rho_set + * + *****************************************************************************/ + +__host__ __device__ int hydro_rho_set(hydro_t * hydro, int index, double rho) { + + assert(hydro); + + hydro->rho[addr_rank0(hydro->nsite, index)] = rho; + + return 0; +} + +/***************************************************************************** + * + * hydro_rho + * + *****************************************************************************/ + +__host__ __device__ int hydro_rho(hydro_t * hydro, int index, double * rho) { + + assert(hydro); + assert(rho); + + *rho = hydro->rho[addr_rank0(hydro->nsite, index)]; + + return 0; +} + /***************************************************************************** * * hydro_u_set diff --git a/src/hydro.h b/src/hydro.h index 0ae5f0f42..ebe1fb1f9 100644 --- a/src/hydro.h +++ b/src/hydro.h @@ -7,7 +7,7 @@ * Edinburgh Soft Matter and Statistical Physics Group and * Edinburgh Parallel Computing Centre * - * (c) 2012-2020 The University of Edinburgh + * (c) 2012-2021 The University of Edinburgh * * Contributing authors: * Kevin Stratford (kevin@epcc.ed.ac.uk) @@ -32,6 +32,7 @@ typedef struct hydro_s hydro_t; struct hydro_s { int nsite; /* Allocated sites (local) */ int nhcomm; /* Width of halo region for u field */ + double * rho; /* Density field */ double * u; /* Velocity field (on host) */ double * f; /* Body force field (on host) */ double * eta; /* Local shear stress */ @@ -68,6 +69,8 @@ __host__ __device__ int hydro_f_local_set(hydro_t * obj, int index, __host__ __device__ int hydro_f_local(hydro_t * obj, int index, double force[3]); __host__ __device__ int hydro_f_local_add(hydro_t * obj, int index, const double force[3]); +__host__ __device__ int hydro_rho_set(hydro_t * hydro, int index, double rho); +__host__ __device__ int hydro_rho(hydro_t * hydro, int index, double * rho); __host__ __device__ int hydro_u_set(hydro_t * obj, int index, const double u[3]); __host__ __device__ int hydro_u(hydro_t * obj, int index, double u[3]); From 1677edf2bb4b41f0cd327d8b954865b470f840b6 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Tue, 9 Nov 2021 15:53:38 +0000 Subject: [PATCH 033/117] Remove commented-out code --- src/lb_model.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lb_model.c b/src/lb_model.c index 3a0018afc..91b75a633 100644 --- a/src/lb_model.c +++ b/src/lb_model.c @@ -23,7 +23,7 @@ #include "lb_d3q19.h" #include "lb_d3q27.h" -/* #include "lb_model.h"*/ +#include "lb_model.h" /***************************************************************************** * From 4d17ad783bf3bf5deeeb6707e4a117b169648446 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Tue, 9 Nov 2021 16:07:05 +0000 Subject: [PATCH 034/117] Remove routines remved from MPI3 --- mpi_s/mpi.h | 13 ----------- mpi_s/mpi_serial.c | 56 ---------------------------------------------- 2 files changed, 69 deletions(-) diff --git a/mpi_s/mpi.h b/mpi_s/mpi.h index 83e3b54b1..edcb190c6 100644 --- a/mpi_s/mpi.h +++ b/mpi_s/mpi.h @@ -88,11 +88,6 @@ enum collective_operations {MPI_MAX, MPI_LOR, MPI_LXOR}; -/* special datatypes for constructing derived datatypes */ - -#define MPI_UB 0 -#define MPI_LB 0 - /* reserved communicators */ enum reserved_communicators{MPI_COMM_WORLD, MPI_COMM_SELF}; @@ -159,10 +154,6 @@ int MPI_Type_contiguous(int count, MPI_Datatype oldtype, MPI_Datatype * newtype); int MPI_Type_vector(int count, int blocklength, int stride, MPI_Datatype oldtype, MPI_Datatype * newtype); -int MPI_Type_struct(int count, int * array_of_blocklengths, - MPI_Aint * array_of_displacements, - MPI_Datatype * array_of_types, MPI_Datatype * newtype); -int MPI_Address(void * location, MPI_Aint * address); int MPI_Type_commit(MPI_Datatype * datatype); int MPI_Type_free(MPI_Datatype * datatype); int MPI_Waitall(int count, MPI_Request * array_of_requests, @@ -213,10 +204,6 @@ int MPI_Abort(MPI_Comm comm, int errorcode); /* MPI 2.0 */ /* In particular, replacements for routines removed from MPI 3 */ -/* MPI_Address() -> MPI_Get_Address() - * MPI_Type_struct() -> MPI_Type_create_struct() - * MPI_Type_lb() and MPI_Type_ub() -> MPI_Type_get_extent() - * See MPI 3 standard */ int MPI_Comm_set_errhandler(MPI_Comm comm, MPI_Errhandler erhandler); int MPI_Get_address(const void * location, MPI_Aint * address); diff --git a/mpi_s/mpi_serial.c b/mpi_s/mpi_serial.c index 2e0821df9..02abac21f 100644 --- a/mpi_s/mpi_serial.c +++ b/mpi_s/mpi_serial.c @@ -737,62 +737,6 @@ int MPI_Type_vector(int count, int blocklength, int stride, return MPI_SUCCESS; } -/***************************************************************************** - * - * MPI_Type_struct - * - * Superceded by MPI_Type_create_struct. - * - *****************************************************************************/ - -int MPI_Type_struct(int count, int * array_of_blocklengths, - MPI_Aint * array_of_displacements, - MPI_Datatype * array_of_types, MPI_Datatype * newtype) { - - assert(count > 0); - assert(array_of_blocklengths); - assert(array_of_displacements); - assert(array_of_types); - assert(newtype); - - printf("MPI_Type_struct: please use MPI_Type_create_struct instead\n"); - - return -1; -} - -/***************************************************************************** - * - * MPI_Address - * - * Please use MPI_Get_Address(). - * - *****************************************************************************/ - -int MPI_Address(void * location, MPI_Aint * address) { - - assert(location); - assert(address); - - *address = 0; - - return MPI_SUCCESS; -} - -/***************************************************************************** - * - * MPI_Errhandler_set - * - *****************************************************************************/ - -int MPI_Errhandler_set(MPI_Comm comm, MPI_Errhandler errhandler) { - - assert(mpi_info); - assert(comm != MPI_COMM_NULL); - assert(errhandler == MPI_ERRORS_ARE_FATAL); - - return MPI_SUCCESS; -} - /***************************************************************************** * * MPI_Cart_create From b32d0b07e1f8645cd1d72967d171cc82ef8fb776 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Tue, 9 Nov 2021 16:21:05 +0000 Subject: [PATCH 035/117] Should be using 1+strnlen() really --- src/compiler.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler.c b/src/compiler.c index a6527778e..364607308 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -84,7 +84,7 @@ int compiler_id(compiler_info_t * compiler) { /* Include __CUDA_ARCH__ */ return 0; #endif - + #ifdef __clang__ /* Load details */ compiler->major = __clang_major__; @@ -109,7 +109,7 @@ int compiler_id(compiler_info_t * compiler) { compiler->major = __GNUC__; compiler->minor = __GNUC_MINOR__; compiler->patchlevel = __GNUC_PATCHLEVEL__; - strncpy(compiler->version, __VERSION__, strnlen(__VERSION__, BUFSIZ-1)); + strncpy(compiler->version, __VERSION__, 1+strnlen(__VERSION__, BUFSIZ-1)); sprintf(compiler->name, "%s", "Gnu"); ierr = 0; From 312f330754c0a4a1c1c2862bd61a30fd690cb2ad Mon Sep 17 00:00:00 2001 From: Oliver Henrich Date: Wed, 10 Nov 2021 16:20:43 +0000 Subject: [PATCH 036/117] Declared implicitly declared functions, verified gradient and bulk stress functions --- src/blue_phase.c | 77 ++++-------------------------------------------- src/blue_phase.h | 11 +++++-- 2 files changed, 14 insertions(+), 74 deletions(-) diff --git a/src/blue_phase.c b/src/blue_phase.c index dc8be82dc..2d9d03fb1 100644 --- a/src/blue_phase.c +++ b/src/blue_phase.c @@ -473,7 +473,6 @@ __host__ __device__ int fe_lc_bulk_stress(fe_lc_t * fe, int index, KRONECKER_DELTA_CHAR(d); assert(fe); - assert(fed); assert(fe->q); field_tensor(fe->q, index, q); @@ -506,45 +505,9 @@ __host__ __device__ int fe_lc_bulk_stress(fe_lc_t * fe, int index, } } - /* bulk contribution to free energy */ - - q2 = 0.0; - - /* Q_ab^2 */ - - for (ia = 0; ia < 3; ia++) { - for (ib = 0; ib < 3; ib++) { - q2 += q[ia][ib]*q[ia][ib]; - } - } - - /* Q_ab Q_bc Q_ca */ - - q3 = 0.0; - - for (ia = 0; ia < 3; ia++) { - for (ib = 0; ib < 3; ib++) { - for (ic = 0; ic < 3; ic++) { - /* We use here the fact that q[ic][ia] = q[ia][ic] */ - q3 += q[ia][ib]*q[ib][ic]*q[ia][ic]; - } - } - } - - /* (2q_0 Q_ab)^2 */ - /* With symmetric Q_db write Q_bd */ - - dq1 = 0.0; - - for (ia = 0; ia < 3; ia++) { - for (ib = 0; ib < 3; ib++) { - sum = 2.0*q0*q[ia][ib]; - dq1 += sum*sum; - } - } - fed = 0.5*a0*(1.0 - r3*gamma)*q2 - r3*a0*gamma*q3 + 0.25*a0*gamma*q2*q2 - + 0.5*kappa1*dq1; + /* bulk contribution to free energy */ + fe_lc_compute_bulk_fed(fe, q, &fed); /* bulk contribtion to stress using the above contributions */ @@ -671,47 +634,17 @@ __host__ __device__ int fe_lc_grad_stress(fe_lc_t * fe, int index, h[ia][ib] = kappa0*dsq[ia][ib] - 2.0*kappa1*q0*sum + 4.0*r3*kappa1*q0*eq*d[ia][ib]; - } - } - - /* gradient contribution to free energy */ - - /* (d_b Q_ab)^2 */ - - dq0 = 0.0; - for (ia = 0; ia < 3; ia++) { - sum = 0.0; - for (ib = 0; ib < 3; ib++) { - sum += dq[ib][ia][ib]; } - dq0 += sum*sum; } - /* (e_acd d_c Q_db + 2q_0 Q_ab)^2 */ - /* With symmetric Q_db write Q_bd */ - - dq1 = 0.0; - - for (ia = 0; ia < 3; ia++) { - for (ib = 0; ib < 3; ib++) { - sum = 0.0; - for (ic = 0; ic < 3; ic++) { - for (id = 0; id < 3; id++) { - sum += e[ia][ic][id]*dq[ic][ib][id]; - } - } - dq1 += sum*sum; - } - } + /* gradient contribution to free energy */ + fe_lc_compute_gradient_fed(fe, q, dq, &fed); - fed = 0.5*kappa0*dq0 + 0.5*kappa1*dq1; + /* gradient contribtion to stress using the above contributions */ p0 = 0.0 - fed; - - /* gradient contribtion to stress using the above contributions */ - /* The contraction Q_ab H_ab */ qh = 0.0; diff --git a/src/blue_phase.h b/src/blue_phase.h index 6c5454874..ddbaef539 100644 --- a/src/blue_phase.h +++ b/src/blue_phase.h @@ -119,11 +119,18 @@ __host__ __device__ int fe_lc_str_anti(fe_lc_t * fe, int index, double s[3][3]); __host__ __device__ -int fe_lc_compute_fed(fe_lc_t * fe, double gamma, double q[3][3], +int fe_lc_compute_fed(fe_lc_t * fe, double gamma, double q[3][3], double dq[3][3][3], double * fed); __host__ __device__ -int fe_lc_compute_h(fe_lc_t * fe, double gaama, double q[3][3], +int fe_lc_compute_bulk_fed(fe_lc_t * fe, double q[3][3], double * fed); + +__host__ __device__ +int fe_lc_compute_gradient_fed(fe_lc_t * fe, double q[3][3], + double dq[3][3][3], double * fed); + +__host__ __device__ +int fe_lc_compute_h(fe_lc_t * fe, double gamma, double q[3][3], double dq[3][3][3], double dsq[3][3], double h[3][3]); __host__ __device__ From 8a596d12096d1591da172b28b5c084d8d1f1f999 Mon Sep 17 00:00:00 2001 From: Oliver Henrich Date: Wed, 10 Nov 2021 16:24:16 +0000 Subject: [PATCH 037/117] Removed unused variables --- src/blue_phase.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/blue_phase.c b/src/blue_phase.c index 2d9d03fb1..800f870e1 100644 --- a/src/blue_phase.c +++ b/src/blue_phase.c @@ -463,8 +463,7 @@ __host__ __device__ int fe_lc_bulk_stress(fe_lc_t * fe, int index, double q0; /* Redshifted value */ double kappa1; /* Redshifted value */ - double q2, q3; - double dq1; + double q2; double sum; const double r3 = (1.0/3.0); @@ -588,7 +587,7 @@ __host__ __device__ int fe_lc_grad_stress(fe_lc_t * fe, int index, double kappa0, kappa1; /* Redshifted values */ double eq; - double dq0, dq1, sum; + double sum; const double r3 = (1.0/3.0); int ia, ib, ic, id, ie; From d25de4a35926c3b4a2706130020e020dd6d4b702 Mon Sep 17 00:00:00 2001 From: Oliver Henrich Date: Wed, 10 Nov 2021 16:38:02 +0000 Subject: [PATCH 038/117] Removed member syntax --- src/blue_phase.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/blue_phase.c b/src/blue_phase.c index 800f870e1..c7f0802b4 100644 --- a/src/blue_phase.c +++ b/src/blue_phase.c @@ -497,10 +497,8 @@ __host__ __device__ int fe_lc_bulk_stress(fe_lc_t * fe, int index, for (ic = 0; ic < 3; ic++) { sum += q[ia][ic]*q[ib][ic]; } - h[ia][ib] = -fe->param->a0*(1.0 - r3*gamma)*q[ia][ib] - + fe->param->a0*gamma*(sum - r3*q2*d[ia][ib]) - - fe->param->a0*gamma*q2*q[ia][ib] - - 4.0*kappa1*q0*q0*q[ia][ib]; + h[ia][ib] = -a0*(1.0 - r3*gamma)*q[ia][ib] + a0*gamma*(sum - r3*q2*d[ia][ib]) + - a0*gamma*q2*q[ia][ib] - 4.0*kappa1*q0*q0*q[ia][ib]; } } From 8d40e94aded1f22da67b4bc0086e71175a213d86 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Thu, 11 Nov 2021 12:29:37 +0000 Subject: [PATCH 039/117] Add test for rho field --- tests/unit/test_hydro.c | 42 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/tests/unit/test_hydro.c b/tests/unit/test_hydro.c index 99413cb9c..4d2b7bf8a 100644 --- a/tests/unit/test_hydro.c +++ b/tests/unit/test_hydro.c @@ -8,7 +8,7 @@ * Edinburgh Soft Matter and Statisitical Physics Group and * Edinburgh Parallel Computing Centre * - * (c) 2014-2020 The University of Edinburgh + * (c) 2014-2021 The University of Edinburgh * * Contributing authors * Kevin Stratford (kevin@epcc.ed.ac.uk) @@ -34,6 +34,8 @@ static int do_test1(pe_t * pe); static int do_test_halo1(pe_t * pe, int nhalo, int nhcomm); static int do_test_io1(pe_t * pe, int io_format); +int test_hydro_rho(pe_t * pe); + /***************************************************************************** * * test_hydro_suite @@ -51,6 +53,8 @@ int test_hydro_suite(void) { do_test_halo1(pe, 2, 2); do_test_halo1(pe, 2, 1); + test_hydro_rho(pe); + do_test_io1(pe, IO_FORMAT_DEFAULT); do_test_io1(pe, IO_FORMAT_ASCII); do_test_io1(pe, IO_FORMAT_BINARY); @@ -202,3 +206,39 @@ static int do_test_io1(pe_t * pe, int io_format) { return 0; } + +/***************************************************************************** + * + * test_hydro_rho + * + *****************************************************************************/ + +int test_hydro_rho(pe_t * pe) { + + cs_t * cs = NULL; + hydro_t * hydro = NULL; + + assert(pe); + + cs_create(pe, &cs); + cs_init(cs); + + hydro_create(pe, cs, NULL, 1, &hydro); + + assert(hydro->rho); + + { + int index = hydro->nsite - 1; + double rho0 = 2.0; + double rho = 0.0; + + hydro_rho_set(hydro, index, rho0); + hydro_rho(hydro, index, &rho); + assert(fabs(rho - rho0) < DBL_EPSILON); + } + + hydro_free(hydro); + cs_free(cs); + + return 0; +} From c82f0e5ab13284974b820fec9d65d1901a871aaf Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Thu, 11 Nov 2021 12:31:08 +0000 Subject: [PATCH 040/117] Add higher moment tests --- tests/unit/test_lb_model.c | 69 +++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 9 deletions(-) diff --git a/tests/unit/test_lb_model.c b/tests/unit/test_lb_model.c index 3188c7539..f6598348f 100644 --- a/tests/unit/test_lb_model.c +++ b/tests/unit/test_lb_model.c @@ -5,13 +5,13 @@ * Tests that all model should pass. * * - * Edinburgh Soft Matter and Statistical Physics Group and - * Edinburgh Parallel Computing Centre + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre * - * (c) 2021 The University of Edinburgh + * (c) 2021 The University of Edinburgh * - * Contributing authors: - * Kevin Stratford (kevin@epcc.ed.ac.uk) + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) * *****************************************************************************/ @@ -125,6 +125,9 @@ int test_lb_model_cv(const lb_model_t * model) { int test_lb_model_wv(const lb_model_t * model) { + int ierr = 0; + KRONECKER_DELTA_CHAR(d_); + assert(model); /* Sum of quadrature weights, velocities */ @@ -151,17 +154,61 @@ int test_lb_model_wv(const lb_model_t * model) { { for (int ia = 0; ia < model->ndim; ia++) { for (int ib = 0; ib < model->ndim; ib++) { - double dij = (ia == ib); double sum = 0.0; for (int p = 0; p < model->nvel; p++) { sum += model->wv[p]*model->cv[p][ia]*model->cv[p][ib]; } - assert(fabs(sum - dij*model->cs2) < DBL_EPSILON); + assert(fabs(sum - d_[ia][ib]*model->cs2) < DBL_EPSILON); } } } - return 0; + /* Third moment \sum_i w_i cia c_ib c_ig = 0 */ + + { + for (int ia = 0; ia < model->ndim; ia++) { + for (int ib = 0; ib < model->ndim; ib++) { + for (int ig = 0; ig < model->ndim; ig++) { + double sum = 0.0; + for (int p = 0; p < model->nvel; p++) { + int8_t (*cv)[3] = model->cv; + sum += model->wv[p]*cv[p][ia]*cv[p][ib]*cv[p][ig]; + } + assert(fabs(sum - 0.0) < DBL_EPSILON); + } + } + } + } + + /* Fourth order moment: + * \sum_i w_i c_ia c_ib c_ig c_ih = c_s^4 (d_ab d_gh + d_ag d_bh + d_ah d_bg) + * with d_ab Kronecker delta. */ + + { + + for (int ia = 0; ia < model->ndim; ia++) { + for (int ib = 0; ib < model->ndim; ib++) { + for (int ig = 0; ig < model->ndim; ig++) { + for (int ih = 0; ih < model->ndim; ih++) { + double delta = d_[ia][ib]*d_[ig][ih] + d_[ia][ig]*d_[ib][ih] + + d_[ia][ih]*d_[ib][ig]; + double expect = model->cs2*model->cs2*delta; + + double sum = 0.0; + for (int p = 0; p < model->nvel; p++) { + int8_t (*cv)[3] = model->cv; + sum += model->wv[p]*cv[p][ia]*cv[p][ib]*cv[p][ig]*cv[p][ih]; + } + + assert(fabs(sum - expect) < DBL_EPSILON); + ierr += (fabs(sum -expect) > DBL_EPSILON); + } + } + } + } + } + + return ierr; } /***************************************************************************** @@ -172,6 +219,8 @@ int test_lb_model_wv(const lb_model_t * model) { int test_lb_model_ma(const lb_model_t * model) { + int ierr = 0; + assert(model); /* Check normalisers \sum_p na[i]*wv[p]*ma[i][p]*ma[j][p] = dij. */ @@ -186,6 +235,7 @@ int test_lb_model_ma(const lb_model_t * model) { } /* Just too tight to make DBL_EPSILON ... */ assert(fabs(sum - dij) < 2*DBL_EPSILON); + ierr += (fabs(sum - dij) > 2*DBL_EPSILON); } } @@ -210,11 +260,12 @@ int test_lb_model_ma(const lb_model_t * model) { /* This element of the inverse should be ... */ double mipq = model->wv[p]*model->na[q]*model->ma[q][p]; assert(fabs(mipq - mi[p][q]) < DBL_EPSILON); + ierr += (fabs(mipq - mi[p][q]) > DBL_EPSILON); } } util_matrix_free(nvel, &mi); } - return 0; + return ierr; } From 590687218e0f73695fb39fca93a80d04cbd6ca9f Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Thu, 11 Nov 2021 12:37:16 +0000 Subject: [PATCH 041/117] Add inflow distribution update --- src/lb_inflow_rhou.c | 108 ++++++++++++++---- src/lb_inflow_rhou.h | 5 +- src/lb_open_bc.h | 9 +- src/lb_openbc_options.c | 4 +- src/lb_openbc_options.h | 1 + tests/unit/test_lb_inflow_rhou.c | 183 ++++++++++++++++++++++++++++++- 6 files changed, 284 insertions(+), 26 deletions(-) diff --git a/src/lb_inflow_rhou.c b/src/lb_inflow_rhou.c index 63b6e27a8..735e4fb5a 100644 --- a/src/lb_inflow_rhou.c +++ b/src/lb_inflow_rhou.c @@ -25,10 +25,10 @@ __host__ int lb_inflow_init_link(lb_inflow_rhou_t * inflow, static int int_max(int a, int b) {return (a > b) ?a :b;} - static const lb_open_bc_vtable_t vt_ = { (lb_open_bc_free_ft) lb_inflow_rhou_free, (lb_open_bc_update_ft) lb_inflow_rhou_update, + (lb_open_bc_impose_ft) lb_inflow_rhou_impose, (lb_open_bc_stats_ft) lb_inflow_rhou_stats }; @@ -39,8 +39,8 @@ static const lb_open_bc_vtable_t vt_ = { *****************************************************************************/ __host__ int lb_inflow_rhou_create(pe_t * pe, cs_t * cs, - const lb_openbc_options_t * options, - lb_inflow_rhou_t ** inflow) { + const lb_openbc_options_t * options, + lb_inflow_rhou_t ** inflow) { lb_inflow_rhou_t * bc = NULL; assert(pe); @@ -214,6 +214,61 @@ __host__ int lb_inflow_rhou_free(lb_inflow_rhou_t * inflow) { * * lb_inflow_rhou_update * + * Set any relevant hydrodynamic conditions at the inflow: + * (1) rho is taken from directly adjacent site in domain; + * (2) u is set to the prescribed constant value. + * + *****************************************************************************/ + +__host__ int lb_inflow_rhou_update(lb_inflow_rhou_t * inflow, hydro_t * hydro) { + + cs_t * cs = NULL; + int id = -1; + int noffset[3] = {}; + + assert(inflow); + + cs = inflow->cs; + cs_nlocal_offset(cs, noffset); + + if (inflow->options.flow[X]) id = X; + if (inflow->options.flow[Y]) id = Y; + if (inflow->options.flow[Z]) id = Z; + + + if (noffset[id] == 0) { + int nlocal[3] = {}; + int idx = inflow->options.flow[X]; + int jdy = inflow->options.flow[Y]; + int kdz = inflow->options.flow[Z]; + + cs_nlocal(cs, nlocal); + + nlocal[id] = 1; /* Only leftmost edge in the relevant direction */ + + for (int ic = 1; ic <= nlocal[X]; ic++) { + for (int jc = 1; jc <= nlocal[Y]; jc++) { + for (int kc = 1; kc <= nlocal[Z]; kc++) { + + int index0 = cs_index(cs, ic - idx, jc - jdy, kc - kdz); + int index1 = cs_index(cs, ic, jc, kc); + double rho = 1.0; + + hydro_rho(hydro, index1, &rho); + hydro_rho_set(hydro, index0, rho); + hydro_u_set(hydro, index0, inflow->options.u0); + } + } + } + } + + return 0; +} + +/***************************************************************************** + * + * lb_inflow_rhou_impose + * * Drive the update of (i.e., apply) the boundary conditions. * * 1. We must update the rho u in the halo region post collision @@ -226,31 +281,46 @@ __host__ int lb_inflow_rhou_free(lb_inflow_rhou_t * inflow) { * *****************************************************************************/ -__host__ int lb_inflow_rhou_update(lb_inflow_rhou_t * inflow, hydro_t * hydro, +__host__ int lb_inflow_rhou_impose(lb_inflow_rhou_t * inflow, hydro_t * hydro, lb_t * lb) { assert(inflow); - assert(hydro); assert(lb); - /* Potentially both at the same time, as independent */ + /* For each incoming link set f_p = f^eq_p (rho, u) */ + + for (int n = 0; n < inflow->nlink; n++) { + + int index = inflow->linkj[n]; + int8_t q = lb->model.nvel - inflow->linkp[n]; + + double rho = 0.0; + double u[3] = {}; - /* Inflow */ - /* Simple for each link: */ - /* compute relevant rho = rho(i); u0 fixed */ - /* set appropriate f^eq_p(rho, u0) at j */ + hydro_rho(hydro, index, &rho); + hydro_u(hydro, index, u); - /* Less simple for each link: */ - /* compute relevant rho = rho(i) post collision */ - /* compute reelvant u0 = u0(r_j) set by boundary position */ - /* set appropriate f^eq_p(rho, u0) */ + { + double cs2 = lb->model.cs2; + double rcs2 = (1.0/cs2); + double udotc = 0.0; + double sdotq = 0.0; + double fp = 0.0; - /* Outflow */ + for (int ia = 0; ia < 3; ia++) { + udotc += u[ia]*lb->model.cv[q][ia]; + for (int ib = 0; ib < 3; ib++) { + double d_ab = (ia == ib); + double s_ab = lb->model.cv[q][ia]*lb->model.cv[q][ib] - cs2*d_ab; - /* Simple for each link: */ - /* compute relevant rho = rho0 */ - /* compute reelvant u0 = u0(r_i) */ - /* set appropriate f^eq_p(rho, u0) */ + sdotq += s_ab*u[ia]*u[ib]; + } + } + + fp = rho*lb->model.wv[q]*(1.0 + rcs2*udotc + 0.5*rcs2*rcs2*sdotq); + lb_f_set(lb, index, q, LB_RHO, fp); + } + } return 0; } diff --git a/src/lb_inflow_rhou.h b/src/lb_inflow_rhou.h index 21b41caba..f853ede6a 100644 --- a/src/lb_inflow_rhou.h +++ b/src/lb_inflow_rhou.h @@ -33,8 +33,9 @@ __host__ int lb_inflow_rhou_create(pe_t * pe, cs_t * cs, lb_inflow_rhou_t ** inflow); __host__ int lb_inflow_rhou_free(lb_inflow_rhou_t * inflow); -__host__ int lb_inflow_rhou_update(lb_inflow_rhou_t * inflow, - hydro_t * hydro, lb_t * lb); +__host__ int lb_inflow_rhou_update(lb_inflow_rhou_t * inflow, hydro_t * hydro); +__host__ int lb_inflow_rhou_impose(lb_inflow_rhou_t * inflow, hydro_t * hydro, + lb_t * lb); __host__ int lb_inflow_rhou_stats(lb_inflow_rhou_t * inflow); __host__ int lb_inflow_rhou_info(lb_inflow_rhou_t * inflow); diff --git a/src/lb_open_bc.h b/src/lb_open_bc.h index 3a63279b4..b55123ab0 100644 --- a/src/lb_open_bc.h +++ b/src/lb_open_bc.h @@ -7,7 +7,7 @@ * Edinburgh Soft Matter and Statistical Physics Group and * Edinburgh Parallel Computing Centre * - * (c) 2021 + * (c) 2021 The University of Edinburgh * * Contributing authors: * Kevin Stratford (kevin@epcc.ed.ac.uk) @@ -29,17 +29,20 @@ typedef struct lb_open_bc_s lb_open_bc_t; /* Abstract function table */ /* lb_open_bc_free_ft is destructor */ -/* lb_open_bc_update_ft update driver with optional extra info */ +/* lb_open_bc_update_ft update driver to set (rho, u) */ +/* lb_open_bc_impose_ft apply conditions (set relevant f_i) */ /* lb_open_bc_stats_ft general purpose stats with optional extra info */ typedef int (* lb_open_bc_free_ft) (lb_open_bc_t * bc); -typedef int (* lb_open_bc_update_ft) (lb_open_bc_t * bc, hydro_t * hydro, +typedef int (* lb_open_bc_update_ft) (lb_open_bc_t * bc, hydro_t * hydro); +typedef int (* lb_open_bc_impose_ft) (lb_open_bc_t * bc, hydro_t * hydro, lb_t * lb); typedef int (* lb_open_bc_stats_ft) (lb_open_bc_t * bc); struct lb_open_bc_vtable_s { lb_open_bc_free_ft free; /* Desctructor */ lb_open_bc_update_ft update; /* Update */ + lb_open_bc_impose_ft impose; /* Apply update to distributions */ lb_open_bc_stats_ft stats; /* General information */ }; diff --git a/src/lb_openbc_options.c b/src/lb_openbc_options.c index 7b043817f..1eb3255da 100644 --- a/src/lb_openbc_options.c +++ b/src/lb_openbc_options.c @@ -24,6 +24,7 @@ #define LB_INFLOW_DEFAULT() LB_INFLOW_NONE #define LB_OUTFLOW_DEFAULT() LB_OUTFLOW_NONE #define LB_FLOW_DEFAULT() {0,0,0} +#define LB_FLOW_U0_DEFAULT() {0.0,0.0,0.0} /***************************************************************************** * @@ -58,7 +59,8 @@ __host__ lb_openbc_options_t lb_openbc_options_default(void) { lb_openbc_options_t options = {.bctype = 0, .inflow = LB_INFLOW_DEFAULT(), .outflow = LB_OUTFLOW_DEFAULT(), - .flow = LB_FLOW_DEFAULT()}; + .flow = LB_FLOW_DEFAULT(), + .u0 = LB_FLOW_U0_DEFAULT()}; return options; } diff --git a/src/lb_openbc_options.h b/src/lb_openbc_options.h index 0a0ac7056..f629f7d9a 100644 --- a/src/lb_openbc_options.h +++ b/src/lb_openbc_options.h @@ -31,6 +31,7 @@ struct lb_openbc_options_s { lb_inflow_enum_t inflow; /* Inflow boundary condition type */ lb_outflow_enum_t outflow; /* Outflow boundary condition type */ int flow[3]; /* Flow coordinate direction (exactly 1) */ + double u0[3]; /* A velocity */ }; __host__ lb_inflow_enum_t lb_openbc_options_inflow_default(void); diff --git a/tests/unit/test_lb_inflow_rhou.c b/tests/unit/test_lb_inflow_rhou.c index 67ff213b2..d9cf6744a 100644 --- a/tests/unit/test_lb_inflow_rhou.c +++ b/tests/unit/test_lb_inflow_rhou.c @@ -2,17 +2,27 @@ * * test_lb_inflow_rhou.c * + * (c) 2021 The University of Edinburgh + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) * *****************************************************************************/ #include +#include +#include -#include "lb_inflow_rhou.c" +#include "lb_inflow_rhou.h" /* Tests */ __host__ int test_lb_inflow_rhou_create(pe_t * pe, cs_t * cs); __host__ int test_lb_inflow_rhou_update(pe_t * pe, cs_t * cs); +__host__ int test_lb_inflow_rhou_impose(pe_t * pe, cs_t * cs); /***************************************************************************** * @@ -31,6 +41,7 @@ __host__ int test_lb_inflow_rhou_suite(void) { test_lb_inflow_rhou_create(pe, cs); test_lb_inflow_rhou_update(pe, cs); + test_lb_inflow_rhou_impose(pe, cs); pe_info(pe, "PASS ./unit/test_lb_inflow_rhou\n"); @@ -79,6 +90,18 @@ __host__ int test_lb_inflow_rhou_create(pe_t * pe, cs_t * cs) { return 0; } +/***************************************************************************** + * + * test_lb_inflow_rhou_update + * + *****************************************************************************/ + +typedef struct limits_s { + int imin, imax; + int jmin, jmax; + int kmin, kmax; +} limits_t; + /***************************************************************************** * * test_lb_inflow_rhou_update @@ -87,9 +110,167 @@ __host__ int test_lb_inflow_rhou_create(pe_t * pe, cs_t * cs) { __host__ int test_lb_inflow_rhou_update(pe_t * pe, cs_t * cs) { + int nlocal[3] = {}; + int noffset[3] = {}; + double rho0 = 2.0; + + lb_openbc_options_t options = {.flow = {1, 0, 0}, + .u0 = {-1.0,-2.0,-3.0}}; + lb_inflow_rhou_t * inflow = NULL; + hydro_t * hydro = NULL; + assert(pe); assert(cs); + cs_nlocal(cs, nlocal); + cs_nlocal_offset(cs, noffset); + + lb_inflow_rhou_create(pe, cs, &options, &inflow); + hydro_create(pe, cs, NULL, 1, &hydro); + + /* Set the relevant domain values (rho only here) */ + + if (noffset[X] == 0) { + + limits_t limits = {1, 1, 1, nlocal[Y], 1, nlocal[Z]}; + + for (int ic = limits.imin; ic <= limits.imax; ic++) { + for (int jc = limits.jmin; jc <= limits.jmax; jc++) { + for (int kc = limits.kmin; kc <= limits.kmax; kc++) { + int index = cs_index(cs, ic, jc, kc); + hydro_rho_set(hydro, index, rho0); + } + } + } + } + + /* Run the update. */ + /* Check rho, u = 0 in the boundary region are set */ + + lb_inflow_rhou_update(inflow, hydro); + + if (noffset[X] == 0) { + + limits_t limits = {0, 0, 1, nlocal[Y], 1, nlocal[Z]}; + + for (int ic = limits.imin; ic <= limits.imax; ic++) { + for (int jc = limits.jmin; jc <= limits.jmax; jc++) { + for (int kc = limits.kmin; kc <= limits.kmax; kc++) { + int index = cs_index(cs, ic, jc, kc); + double rho = 0.0; + double u[3] = {}; + + hydro_rho(hydro, index, &rho); + hydro_u(hydro, index, u); + + assert(fabs(rho - rho0) < DBL_EPSILON); + assert(fabs(u[X] - inflow->options.u0[X]) < DBL_EPSILON); + assert(fabs(u[Y] - inflow->options.u0[Y]) < DBL_EPSILON); + assert(fabs(u[Z] - inflow->options.u0[Z]) < DBL_EPSILON); + } + } + } + } + + hydro_free(hydro); + lb_inflow_rhou_free(inflow); return 0; } + +/***************************************************************************** + * + * test_lb_inflow_rhou_impose + * + *****************************************************************************/ + +__host__ int test_lb_inflow_rhou_impose(pe_t * pe, cs_t * cs) { + + int ierr = 0; + + int nlocal[3] = {}; + int ntotal[3] = {}; + int noffset[3] = {}; + + double rho0 = 1.0; + + lb_openbc_options_t options = {.nvel = NVEL, + .flow = {1, 0, 0}, + .u0 = {0.01, 0.0, 0.0}}; + lb_inflow_rhou_t * inflow = NULL; + hydro_t * hydro = NULL; + lb_t * lb = NULL; + + assert(pe); + assert(cs); + + /* Set up. */ + + cs_nlocal(cs, nlocal); + cs_ntotal(cs, ntotal); + cs_nlocal_offset(cs, noffset); + + lb_inflow_rhou_create(pe, cs, &options, &inflow); + hydro_create(pe, cs, NULL, 1, &hydro); + lb_create(pe, cs, &lb); + lb_init(lb); + + /* Set the relevant domain values (rho only here) */ + + if (noffset[X] == 0) { + + limits_t limits = {1, 1, 1, nlocal[Y], 1, nlocal[Z]}; + + for (int ic = limits.imin; ic <= limits.imax; ic++) { + for (int jc = limits.jmin; jc <= limits.jmax; jc++) { + for (int kc = limits.kmin; kc <= limits.kmax; kc++) { + int index = cs_index(cs, ic, jc, kc); + hydro_rho_set(hydro, index, rho0); + } + } + } + } + + lb_inflow_rhou_update(inflow, hydro); + lb_inflow_rhou_impose(inflow, hydro, lb); + + /* Check relevant f_i are set correctly. */ + /* So, for each site in the boundary region, check ingoing distributions. */ + + if (noffset[X] == 0) { + limits_t limits = {0, 0, 1, nlocal[Y], 1, nlocal[Z]}; + + for (int ic = limits.imin; ic <= limits.imax; ic++) { + for (int jc = limits.jmin; jc <= limits.jmax; jc++) { + for (int kc = limits.kmin; kc <= limits.kmax; kc++) { + for (int p = 1; p < lb->model.nvel; p++) { + + int index = cs_index(cs, ic, jc, kc); + double f = 0.0; + + /* Only distributions ending in the local domain ... */ + if (lb->model.cv[p][X] != +1) continue; + if (noffset[Y] + jc + lb->model.cv[p][Y] < 1) continue; + if (noffset[Z] + kc + lb->model.cv[p][Z] < 1) continue; + if (noffset[Y] + jc + lb->model.cv[p][Y] > ntotal[Y]) continue; + if (noffset[Z] + kc + lb->model.cv[p][Z] > ntotal[Z]) continue; + + lb_f(lb, index, p, LB_RHO, &f); + { + double ux = inflow->options.u0[X]; + double fp = lb->model.wv[p]*rho0*(1.0 + 3.0*ux + 3.0*ux*ux); + assert(fabs(f - fp) < DBL_EPSILON); + ierr += (fabs(f - fp) > DBL_EPSILON); + } + } + } + } + } + } + + lb_free(lb); + hydro_free(hydro); + lb_inflow_rhou_free(inflow); + + return ierr; +} From 2aaad8996b197edd308f6c09d083a7eff50107c6 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Thu, 11 Nov 2021 15:29:46 +0000 Subject: [PATCH 042/117] Add tests for bulk/grad fed and stress --- src/blue_phase.h | 6 ++ tests/unit/test_blue_phase.c | 153 ++++++++++++++++++++++++++++++++++- 2 files changed, 158 insertions(+), 1 deletion(-) diff --git a/src/blue_phase.h b/src/blue_phase.h index ddbaef539..c207a156f 100644 --- a/src/blue_phase.h +++ b/src/blue_phase.h @@ -175,6 +175,12 @@ void fe_lc_compute_stress_v(fe_lc_t * fe, double h[3][3][NSIMDVL], double s[3][3][NSIMDVL]); +__host__ __device__ +int fe_lc_bulk_stress(fe_lc_t * fe, int index, double sbulk[3][3]); + +__host__ __device__ +int fe_lc_grad_stress(fe_lc_t * fe, int index, double sgrad[3][3]); + /* Function of the parameters only */ diff --git a/tests/unit/test_blue_phase.c b/tests/unit/test_blue_phase.c index 2854a73d7..1bb2ae58c 100644 --- a/tests/unit/test_blue_phase.c +++ b/tests/unit/test_blue_phase.c @@ -348,6 +348,15 @@ int test_o8m_struct(pe_t * pe, cs_t * cs, lees_edw_t * le, fe_lc_t * fe, fe_lc_compute_fed(fe, gamma, q, dq, &value); test_assert(fabs(value - 6.060508e-03) < TEST_FLOAT_TOLERANCE); + { + double fed_bulk = 0.0; + double fed_grad = 0.0; + + fe_lc_compute_bulk_fed(fe, q, &fed_bulk); + fe_lc_compute_gradient_fed(fe, q, dq, &fed_grad); + assert(fabs(value - (fed_bulk + fed_grad)) < DBL_EPSILON); + } + ic = 1; jc = 1; kc = 2; @@ -358,6 +367,15 @@ int test_o8m_struct(pe_t * pe, cs_t * cs, lees_edw_t * le, fe_lc_t * fe, fe_lc_compute_fed(fe, gamma, q, dq, &value); test_assert(fabs(value - 1.056203e-02) < TEST_FLOAT_TOLERANCE); + + { + double fed_bulk = 0.0; + double fed_grad = 0.0; + + fe_lc_compute_bulk_fed(fe, q, &fed_bulk); + fe_lc_compute_gradient_fed(fe, q, dq, &fed_grad); + assert(fabs(value - (fed_bulk + fed_grad)) < DBL_EPSILON); + } ic = 1; jc = 1; @@ -370,6 +388,15 @@ int test_o8m_struct(pe_t * pe, cs_t * cs, lees_edw_t * le, fe_lc_t * fe, fe_lc_compute_fed(fe, gamma, q, dq, &value); test_assert(fabs(value - 6.060508e-03) < TEST_FLOAT_TOLERANCE); + { + double fed_bulk = 0.0; + double fed_grad = 0.0; + + fe_lc_compute_bulk_fed(fe, q, &fed_bulk); + fe_lc_compute_gradient_fed(fe, q, dq, &fed_grad); + assert(fabs(value - (fed_bulk + fed_grad)) < DBL_EPSILON); + } + ic = 1; jc = 12; kc = 4; @@ -381,6 +408,15 @@ int test_o8m_struct(pe_t * pe, cs_t * cs, lees_edw_t * le, fe_lc_t * fe, fe_lc_compute_fed(fe, gamma, q, dq, &value); test_assert(fabs(value - 6.609012e-04) < TEST_FLOAT_TOLERANCE); + { + double fed_bulk = 0.0; + double fed_grad = 0.0; + + fe_lc_compute_bulk_fed(fe, q, &fed_bulk); + fe_lc_compute_gradient_fed(fe, q, dq, &fed_grad); + assert(fabs(value - (fed_bulk + fed_grad)) < DBL_EPSILON); + } + ic = 2; jc = 7; kc = 6; @@ -392,6 +428,15 @@ int test_o8m_struct(pe_t * pe, cs_t * cs, lees_edw_t * le, fe_lc_t * fe, fe_lc_compute_fed(fe, gamma, q, dq, &value); test_assert(fabs(value - 6.609012e-04) < TEST_FLOAT_TOLERANCE); + { + double fed_bulk = 0.0; + double fed_grad = 0.0; + + fe_lc_compute_bulk_fed(fe, q, &fed_bulk); + fe_lc_compute_gradient_fed(fe, q, dq, &fed_grad); + assert(fabs(value - (fed_bulk + fed_grad)) < DBL_EPSILON); + } + /* Now the molecular field */ @@ -534,7 +579,6 @@ int test_o8m_struct(pe_t * pe, cs_t * cs, lees_edw_t * le, fe_lc_t * fe, test_assert(fabs(dsq[Z][Y] - -9.837494e-03) < TEST_FLOAT_TOLERANCE); test_assert(fabs(dsq[Z][Z] - -7.887056e-03) < TEST_FLOAT_TOLERANCE); - ic = 1; jc = 1; kc = 2; @@ -631,6 +675,113 @@ int test_o8m_struct(pe_t * pe, cs_t * cs, lees_edw_t * le, fe_lc_t * fe, test_assert(fabs(dsq[Z][Y] - 1.308445e-03) < TEST_FLOAT_TOLERANCE); test_assert(fabs(dsq[Z][Z] - -5.056451e-03) < TEST_FLOAT_TOLERANCE); + /* Now do that again without doctoring the values of the gradients + * to test the decomposition into bulk and gradient parts */ + + { + double sfull[3][3] = {}; + double sbulk[3][3] = {}; + double sgrad[3][3] = {}; + ic = 1; + jc = 1; + kc = 1; + index = lees_edw_index(le, ic, jc, kc); + + fe_lc_stress(fe, index, sfull); + fe_lc_bulk_stress(fe, index, sbulk); + fe_lc_grad_stress(fe, index, sgrad); + + for (int ia = 0; ia < 3; ia++) { + for (int ib = 0; ib < 3; ib++) { + assert(fabs(sfull[ia][ib] - (sbulk[ia][ib] + sgrad[ia][ib])) + < DBL_EPSILON); + } + } + } + + { + double sfull[3][3] = {}; + double sbulk[3][3] = {}; + double sgrad[3][3] = {}; + ic = 1; + jc = 1; + kc = 2; + index = lees_edw_index(le, ic, jc, kc); + + fe_lc_stress(fe, index, sfull); + fe_lc_bulk_stress(fe, index, sbulk); + fe_lc_grad_stress(fe, index, sgrad); + + for (int ia = 0; ia < 3; ia++) { + for (int ib = 0; ib < 3; ib++) { + assert(fabs(sfull[ia][ib] - (sbulk[ia][ib] + sgrad[ia][ib])) + < DBL_EPSILON); + } + } + } + + { + double sfull[3][3] = {}; + double sbulk[3][3] = {}; + double sgrad[3][3] = {}; + ic = 1; + jc = 1; + kc = 3; + index = lees_edw_index(le, ic, jc, kc); + + fe_lc_stress(fe, index, sfull); + fe_lc_bulk_stress(fe, index, sbulk); + fe_lc_grad_stress(fe, index, sgrad); + + for (int ia = 0; ia < 3; ia++) { + for (int ib = 0; ib < 3; ib++) { + assert(fabs(sfull[ia][ib] - (sbulk[ia][ib] + sgrad[ia][ib])) + < DBL_EPSILON); + } + } + } + + { + double sfull[3][3] = {}; + double sbulk[3][3] = {}; + double sgrad[3][3] = {}; + ic = 1; + jc = 12; + kc = 4; + index = lees_edw_index(le, ic, jc, kc); + + fe_lc_stress(fe, index, sfull); + fe_lc_bulk_stress(fe, index, sbulk); + fe_lc_grad_stress(fe, index, sgrad); + + for (int ia = 0; ia < 3; ia++) { + for (int ib = 0; ib < 3; ib++) { + assert(fabs(sfull[ia][ib] - (sbulk[ia][ib] + sgrad[ia][ib])) + < DBL_EPSILON); + } + } + } + + { + double sfull[3][3] = {}; + double sbulk[3][3] = {}; + double sgrad[3][3] = {}; + ic = 2; + jc = 6; + kc = 7; + index = lees_edw_index(le, ic, jc, kc); + + fe_lc_stress(fe, index, sfull); + fe_lc_bulk_stress(fe, index, sbulk); + fe_lc_grad_stress(fe, index, sgrad); + + for (int ia = 0; ia < 3; ia++) { + for (int ib = 0; ib < 3; ib++) { + assert(fabs(sfull[ia][ib] - (sbulk[ia][ib] + sgrad[ia][ib])) + < DBL_EPSILON); + } + } + } /* Electric field test */ From c72e9b25c9da9e566601fb3499255246c208bc30 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Thu, 11 Nov 2021 17:29:04 +0000 Subject: [PATCH 043/117] Repair 5th order for device --- src/advection.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/advection.c b/src/advection.c index 14d8ed443..62bb15474 100644 --- a/src/advection.c +++ b/src/advection.c @@ -471,7 +471,10 @@ int advection_x(advflux_t * obj, hydro_t * hydro, field_t * field) { advflux_memcpy(obj, tdpMemcpyHostToDevice); break; case 5: + /* Ditto */ + advflux_memcpy(obj, tdpMemcpyDeviceToHost); advection_le_5th(obj, hydro, nf, field->data); + advflux_memcpy(obj, tdpMemcpyHostToDevice); break; default: pe_fatal(obj->pe, "Unexpected advection scheme order\n"); From b7358daba736871cf3c50bd6a9cf98c9b184b8ad Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Fri, 12 Nov 2021 17:12:41 +0000 Subject: [PATCH 044/117] Added outflow pending test --- src/{lb_inflow_rhou.c => lb_bc_inflow_rhou.c} | 117 +++--- src/lb_bc_inflow_rhou.h | 52 +++ src/lb_bc_open.h | 59 +++ src/lb_bc_outflow_opts.c | 48 +++ src/lb_bc_outflow_opts.h | 35 ++ src/lb_bc_outflow_rhou.c | 346 ++++++++++++++++++ src/lb_bc_outflow_rhou.h | 47 +++ src/lb_inflow_rhou.h | 44 --- src/lb_model.c | 32 ++ src/lb_model.h | 2 + src/lb_open_bc.h | 54 --- ...inflow_rhou.c => test_lb_bc_inflow_rhou.c} | 62 ++-- tests/unit/test_lb_bc_outflow_opts.c | 94 +++++ tests/unit/test_lb_model.c | 17 +- tests/unit/tests.c | 3 +- tests/unit/tests.h | 3 +- 16 files changed, 828 insertions(+), 187 deletions(-) rename src/{lb_inflow_rhou.c => lb_bc_inflow_rhou.c} (69%) create mode 100644 src/lb_bc_inflow_rhou.h create mode 100644 src/lb_bc_open.h create mode 100644 src/lb_bc_outflow_opts.c create mode 100644 src/lb_bc_outflow_opts.h create mode 100644 src/lb_bc_outflow_rhou.c create mode 100644 src/lb_bc_outflow_rhou.h delete mode 100644 src/lb_inflow_rhou.h delete mode 100644 src/lb_open_bc.h rename tests/unit/{test_lb_inflow_rhou.c => test_lb_bc_inflow_rhou.c} (79%) create mode 100644 tests/unit/test_lb_bc_outflow_opts.c diff --git a/src/lb_inflow_rhou.c b/src/lb_bc_inflow_rhou.c similarity index 69% rename from src/lb_inflow_rhou.c rename to src/lb_bc_inflow_rhou.c index 735e4fb5a..00bee7997 100644 --- a/src/lb_inflow_rhou.c +++ b/src/lb_bc_inflow_rhou.c @@ -1,8 +1,19 @@ /***************************************************************************** * - * lb_inflow_rhou.c + * lb_bc_inflow_rhou.c + * + * Implementation of an inflowboundary condition which assumes + * a channel geometry with walls in two dimensions. + * + * The inflow in the flow direction is then at the left or lower + * end of the system and sets, e.g.,: + * + * rho_inflow(x=0,y,z) = rho(x=1,y,z) the adjacent point + * u_inflow(x=0,y,z) = u0 a prescribed value + * + * Incoming distributions are then set f_i = f^eq_i(rho, u) in + * the inflow boundary region. * - * Concrete instance of lb_open_bc.h for inflow. * * Edinburgh Soft Matter and Statistical Phsyics Group and * Edinburgh Parallel Computing Centre @@ -15,57 +26,57 @@ #include #include "lb_model.h" -#include "lb_inflow_rhou.h" +#include "lb_bc_inflow_rhou.h" -typedef enum {LB_LINK_COUNT, LB_LINK_ASSIGN} lb_link_init_enum_t; +typedef enum {LINK_COUNT, LINK_ASSIGN} link_init_enum_t; -__host__ int lb_inflow_rhou_init_internal(lb_inflow_rhou_t * inflow); -__host__ int lb_inflow_init_link(lb_inflow_rhou_t * inflow, - lb_link_init_enum_t flag, int id); +__host__ int lb_bc_inflow_rhou_init_internal(lb_bc_inflow_rhou_t * inflow); +__host__ int lb_bc_inflow_init_link(lb_bc_inflow_rhou_t * inflow, + link_init_enum_t flag, int id); -static int int_max(int a, int b) {return (a > b) ?a :b;} +static int int_max(int a, int b) {return (a > b) ? a : b;} -static const lb_open_bc_vtable_t vt_ = { - (lb_open_bc_free_ft) lb_inflow_rhou_free, - (lb_open_bc_update_ft) lb_inflow_rhou_update, - (lb_open_bc_impose_ft) lb_inflow_rhou_impose, - (lb_open_bc_stats_ft) lb_inflow_rhou_stats +static const lb_bc_open_vtable_t vt_ = { + (lb_bc_open_free_ft) lb_bc_inflow_rhou_free, + (lb_bc_open_update_ft) lb_bc_inflow_rhou_update, + (lb_bc_open_impose_ft) lb_bc_inflow_rhou_impose, + (lb_bc_open_stats_ft) lb_bc_inflow_rhou_stats }; /***************************************************************************** * - * lb_inflow_rhou_create + * lb_bc_inflow_rhou_create * *****************************************************************************/ -__host__ int lb_inflow_rhou_create(pe_t * pe, cs_t * cs, - const lb_openbc_options_t * options, - lb_inflow_rhou_t ** inflow) { - lb_inflow_rhou_t * bc = NULL; +__host__ int lb_bc_inflow_rhou_create(pe_t * pe, cs_t * cs, + const lb_openbc_options_t * options, + lb_bc_inflow_rhou_t ** inflow) { + lb_bc_inflow_rhou_t * bc = NULL; assert(pe); assert(cs); assert(options); assert(inflow); - bc = (lb_inflow_rhou_t *) calloc(1, sizeof(lb_inflow_rhou_t)); + bc = (lb_bc_inflow_rhou_t *) calloc(1, sizeof(lb_bc_inflow_rhou_t)); assert(bc); - if (bc == NULL) pe_fatal(pe, "Failed to allocate lb_inflow_rhou_t"); + if (bc == NULL) pe_fatal(pe, "Failed to allocate lb_bc_inflow_rhou_t"); /* Pointers; superclass block */ bc->pe = pe; bc->cs = cs; bc->super.func = &vt_; - bc->super.id = LB_OPEN_BC_INFLOW_RHOU; + bc->super.id = LB_BC_INFLOW_RHOU; if (!lb_openbc_options_valid(options)) { /* Internal error if we reach this point. */ - pe_fatal(pe, "lb_inflow_rhou_create: lb_openbc_options_t invalid\n"); + pe_fatal(pe, "lb_bc_inflow_rhou_create: lb_openbc_options_t invalid\n"); } bc->options = *options; - lb_inflow_rhou_init_internal(bc); + lb_bc_inflow_rhou_init_internal(bc); *inflow = bc; @@ -74,17 +85,17 @@ __host__ int lb_inflow_rhou_create(pe_t * pe, cs_t * cs, /***************************************************************************** * - * lb_inflow_rhou_init_internal + * lb_bc_inflow_rhou_init_internal * *****************************************************************************/ -__host__ int lb_inflow_rhou_init_internal(lb_inflow_rhou_t * inflow) { +__host__ int lb_bc_inflow_rhou_init_internal(lb_bc_inflow_rhou_t * inflow) { assert(inflow); - if (inflow->options.flow[X]) lb_inflow_init_link(inflow, LB_LINK_COUNT, X); - if (inflow->options.flow[Y]) lb_inflow_init_link(inflow, LB_LINK_COUNT, Y); - if (inflow->options.flow[Z]) lb_inflow_init_link(inflow, LB_LINK_COUNT, Z); + if (inflow->options.flow[X]) lb_bc_inflow_init_link(inflow, LINK_COUNT, X); + if (inflow->options.flow[Y]) lb_bc_inflow_init_link(inflow, LINK_COUNT, Y); + if (inflow->options.flow[Z]) lb_bc_inflow_init_link(inflow, LINK_COUNT, Z); { pe_t * pe = inflow->pe; @@ -103,16 +114,16 @@ __host__ int lb_inflow_rhou_init_internal(lb_inflow_rhou_t * inflow) { if (inflow->linkj == NULL) pe_fatal(pe, "calloc(inflow->linkj) NULL\n"); } - if (inflow->options.flow[X]) lb_inflow_init_link(inflow, LB_LINK_ASSIGN, X); - if (inflow->options.flow[Y]) lb_inflow_init_link(inflow, LB_LINK_ASSIGN, Y); - if (inflow->options.flow[Z]) lb_inflow_init_link(inflow, LB_LINK_ASSIGN, Z); + if (inflow->options.flow[X]) lb_bc_inflow_init_link(inflow, LINK_ASSIGN, X); + if (inflow->options.flow[Y]) lb_bc_inflow_init_link(inflow, LINK_ASSIGN, Y); + if (inflow->options.flow[Z]) lb_bc_inflow_init_link(inflow, LINK_ASSIGN, Z); return 0; } /***************************************************************************** * - * lb_inflow_init_link + * lb_bc_inflow_init_link * * Identify links representing incoming distributions at the inflow * which are fluid to fluid in the coordinate direction "id". @@ -125,8 +136,8 @@ __host__ int lb_inflow_rhou_init_internal(lb_inflow_rhou_t * inflow) { * *****************************************************************************/ -__host__ int lb_inflow_init_link(lb_inflow_rhou_t * inflow, - lb_link_init_enum_t init, int id) { +__host__ int lb_bc_inflow_init_link(lb_bc_inflow_rhou_t * inflow, + link_init_enum_t init, int id) { cs_t * cs = NULL; int noffset[3] = {}; @@ -173,7 +184,7 @@ __host__ int lb_inflow_init_link(lb_inflow_rhou_t * inflow, if (noffset[id2] + ijk[id2] < 1 ) continue; if (noffset[id2] + ijk[id2] > ntotal[id2]) continue; - if (init == LB_LINK_ASSIGN) { + if (init == LINK_ASSIGN) { inflow->linkp[nlink] = p; inflow->linki[nlink] = cs_index(cs, ic, jc, kc); inflow->linkj[nlink] = cs_index(cs, ic1, jc1, kc1); @@ -194,11 +205,11 @@ __host__ int lb_inflow_init_link(lb_inflow_rhou_t * inflow, /***************************************************************************** * - * lb_inflow_rhou_free + * lb_bc_inflow_rhou_free * *****************************************************************************/ -__host__ int lb_inflow_rhou_free(lb_inflow_rhou_t * inflow) { +__host__ int lb_bc_inflow_rhou_free(lb_bc_inflow_rhou_t * inflow) { assert(inflow); @@ -212,7 +223,7 @@ __host__ int lb_inflow_rhou_free(lb_inflow_rhou_t * inflow) { /***************************************************************************** * - * lb_inflow_rhou_update + * lb_bc_inflow_rhou_update * * Set any relevant hydrodynamic conditions at the inflow: * (1) rho is taken from directly adjacent site in domain; @@ -220,13 +231,15 @@ __host__ int lb_inflow_rhou_free(lb_inflow_rhou_t * inflow) { * *****************************************************************************/ -__host__ int lb_inflow_rhou_update(lb_inflow_rhou_t * inflow, hydro_t * hydro) { +__host__ int lb_bc_inflow_rhou_update(lb_bc_inflow_rhou_t * inflow, + hydro_t * hydro) { cs_t * cs = NULL; int id = -1; int noffset[3] = {}; assert(inflow); + assert(hydro); cs = inflow->cs; cs_nlocal_offset(cs, noffset); @@ -267,24 +280,17 @@ __host__ int lb_inflow_rhou_update(lb_inflow_rhou_t * inflow, hydro_t * hydro) { /***************************************************************************** * - * lb_inflow_rhou_impose + * lb_bc_inflow_rhou_impose * - * Drive the update of (i.e., apply) the boundary conditions. - * - * 1. We must update the rho u in the halo region post collision - * - Allows any relevant f_i(rho, u) to be computed. - * - Allows correct u to enter any flux calculation at edge of grid. - * 2. Update post collision distributions in halo region appropriately - * to enter propagation stage. - * - * After lattice halo swap; before propagation. + * Intent: After lattice halo swap; before propagation. * *****************************************************************************/ -__host__ int lb_inflow_rhou_impose(lb_inflow_rhou_t * inflow, hydro_t * hydro, - lb_t * lb) { - +__host__ int lb_bc_inflow_rhou_impose(lb_bc_inflow_rhou_t * inflow, + hydro_t * hydro, + lb_t * lb) { assert(inflow); + assert(hydro); assert(lb); /* For each incoming link set f_p = f^eq_p (rho, u) */ @@ -317,6 +323,7 @@ __host__ int lb_inflow_rhou_impose(lb_inflow_rhou_t * inflow, hydro_t * hydro, } } + /* Here's the equilibrium */ fp = rho*lb->model.wv[q]*(1.0 + rcs2*udotc + 0.5*rcs2*rcs2*sdotq); lb_f_set(lb, index, q, LB_RHO, fp); } @@ -327,13 +334,13 @@ __host__ int lb_inflow_rhou_impose(lb_inflow_rhou_t * inflow, hydro_t * hydro, /***************************************************************************** * - * lb_inflow_rhou_stats + * lb_bc_inflow_rhou_stats * - * No operation at the moment. + * Placeholder. No operation at the moment. * *****************************************************************************/ -__host__ int lb_inflow_rhou_stats(lb_inflow_rhou_t * inflow) { +__host__ int lb_bc_inflow_rhou_stats(lb_bc_inflow_rhou_t * inflow) { return 0; } diff --git a/src/lb_bc_inflow_rhou.h b/src/lb_bc_inflow_rhou.h new file mode 100644 index 000000000..97eaebd8f --- /dev/null +++ b/src/lb_bc_inflow_rhou.h @@ -0,0 +1,52 @@ +/***************************************************************************** + * + * lb_bc_inflow_rhou.h + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#ifndef LUDWIG_LB_BC_INFLOW_RHOU_H +#define LUDWIG_LB_BC_INFLOW_RHOU_H + +#include "lb_bc_open.h" +#include "lb_openbc_options.h" + +typedef struct lb_bc_inflow_rhou_s lb_bc_inflow_rhou_t; + +/* Inflow boundary condition. */ + +struct lb_bc_inflow_rhou_s { + lb_bc_open_t super; /* Superclass block */ + pe_t * pe; /* Parallel environment */ + cs_t * cs; /* Coordinate system */ + lb_openbc_options_t options; /* Options/parameters */ + lb_bc_inflow_rhou_t * target; /* Target pointer */ + + /* Boundary links */ + int nlink; /* Number of links (local) */ + int8_t * linkp; /* Velocity index in LB basis (i->j) */ + int * linki; /* Fluid site in system */ + int * linkj; /* Fluid site in inflow halo boundary */ +}; + +__host__ int lb_bc_inflow_rhou_create(pe_t * pe, cs_t * cs, + const lb_openbc_options_t * options, + lb_bc_inflow_rhou_t ** inflow); + +__host__ int lb_bc_inflow_rhou_free(lb_bc_inflow_rhou_t * inflow); +__host__ int lb_bc_inflow_rhou_update(lb_bc_inflow_rhou_t * inflow, + hydro_t * hydro); +__host__ int lb_bc_inflow_rhou_impose(lb_bc_inflow_rhou_t * inflow, + hydro_t * hydro, + lb_t * lb); +__host__ int lb_bc_inflow_rhou_stats(lb_bc_inflow_rhou_t * inflow); + +#endif + diff --git a/src/lb_bc_open.h b/src/lb_bc_open.h new file mode 100644 index 000000000..a4cd946cf --- /dev/null +++ b/src/lb_bc_open.h @@ -0,0 +1,59 @@ +/***************************************************************************** + * + * lb_bc_open.h + * + * Lattice fluid open boundary condition (abstract type). + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#ifndef LUDWIG_LB_BC_OPEN_H +#define LUDWIG_LB_BC_OPEN_H + +#include "hydro.h" +#include "model.h" + +typedef struct lb_bc_open_vtable_s lb_bc_open_vtable_t; +typedef struct lb_bc_open_s lb_bc_open_t; + +/* Abstract function table */ +/* lb_bc_open_free_ft is destructor */ +/* lb_bc_open_update_ft update driver to set (rho, u) */ +/* lb_bc_open_impose_ft apply conditions (set relevant f_i) */ +/* lb_bc_open_stats_ft general purpose stats with optional extra info */ + +typedef int (* lb_bc_open_free_ft) (lb_bc_open_t * bc); +typedef int (* lb_bc_open_update_ft) (lb_bc_open_t * bc, hydro_t * hydro); +typedef int (* lb_bc_open_impose_ft) (lb_bc_open_t * bc, hydro_t * hydro, + lb_t * lb); +typedef int (* lb_bc_open_stats_ft) (lb_bc_open_t * bc); + +struct lb_bc_open_vtable_s { + lb_bc_open_free_ft free; /* Desctructor */ + lb_bc_open_update_ft update; /* Update */ + lb_bc_open_impose_ft impose; /* Apply update to distributions */ + lb_bc_open_stats_ft stats; /* General information */ +}; + +/* Implementations */ + +typedef enum lb_bc_open_enum {LB_BC_INVALID, + LB_BC_INFLOW_RHOU, + LB_BC_OUTFLOW_RHOU, + LB_BC_MAX} lb_bc_open_enum_t; + +/* Superclass block */ + +struct lb_bc_open_s { + const lb_bc_open_vtable_t * func; /* function table */ + lb_bc_open_enum_t id; /* unique type identifier */ +}; + +#endif diff --git a/src/lb_bc_outflow_opts.c b/src/lb_bc_outflow_opts.c new file mode 100644 index 000000000..9f7e5bce4 --- /dev/null +++ b/src/lb_bc_outflow_opts.c @@ -0,0 +1,48 @@ +/***************************************************************************** + * + * lb_bc_outflow_opts.c + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#include "lb_bc_outflow_opts.h" + +/***************************************************************************** + * + * lb_bc_outflow_opts_default + * + *****************************************************************************/ + +lb_bc_outflow_opts_t lb_bc_outflow_opts_default(void) { + + lb_bc_outflow_opts_t opts = {.nvel = 0, .flow = {}, .rho0 = 1.0, .u0 = {}}; + + return opts; +} + +/***************************************************************************** + * + * lb_bc_outflow_options_valid + * + *****************************************************************************/ + +int lb_bc_outflow_opts_valid(lb_bc_outflow_opts_t options) { + + int isvalid = 0; /* 0 = invalid */ + + int sum = options.flow[X] + options.flow[Y] + options.flow[Z]; + + isvalid = lb_model_is_available(options.nvel); /* Available */ + isvalid = (isvalid && (sum == 0 || sum == 1)); /* One direction, or none */ + + /* We're not making any stipulations about (rho, u0). */ + + return isvalid; +} diff --git a/src/lb_bc_outflow_opts.h b/src/lb_bc_outflow_opts.h new file mode 100644 index 000000000..cac85f76e --- /dev/null +++ b/src/lb_bc_outflow_opts.h @@ -0,0 +1,35 @@ +/***************************************************************************** + * + * lb_bc_outflow_opts.h + * + * Container for outflow boundary condition options. + * + * + * Edinburgh Soft Matter and Statisitical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#ifndef LB_BC_OUTFLOW_OPTS_H +#define LB_BC_OUTFLOW_OPTS_H + +#include "lb_model.h" + +typedef struct lb_bc_outflow_opts_s lb_bc_outflow_opts_t; + +struct lb_bc_outflow_opts_s { + int nvel; + int flow[3]; + double rho0; + double u0[3]; +}; + +lb_bc_outflow_opts_t lb_bc_outflow_opts_default(void); +int lb_bc_outflow_opts_valid(lb_bc_outflow_opts_t options); + +#endif diff --git a/src/lb_bc_outflow_rhou.c b/src/lb_bc_outflow_rhou.c new file mode 100644 index 000000000..0fe8640d8 --- /dev/null +++ b/src/lb_bc_outflow_rhou.c @@ -0,0 +1,346 @@ +/***************************************************************************** + * + * lb_bc_outflow_rhou.c + * + * Implementation of an outflow boundary condition which assumes + * a channel geometry with walls in two dimensions. + * + * Hydrodynamic conditions at the outflow are, .e.g.,: + * + * rho_outflow(x=L,y,z) = rho0 + * u_outflow(x=L,y,z) = u(L-1,y,z) + * + * Incoming distributions are then set f_i = f^eq_i(rho, u) in + * the outflow boundary region. Outgoing distributions from the + * domain proper merely "disappear". + * + * + * Edinburgh Soft Matter and Statistical Phsyics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + *****************************************************************************/ + +#include +#include + +#include "lb_model.h" +#include "lb_bc_outflow_rhou.h" + +typedef enum {LINK_COUNT, LINK_ASSIGN} link_init_enum_t; + +__host__ int lb_bc_outflow_rhou_init_internal(lb_bc_outflow_rhou_t * outflow); +__host__ int lb_bc_outflow_init_link(lb_bc_outflow_rhou_t * outflow, + link_init_enum_t flag, int id); + +static int int_max(int a, int b) {return (a > b) ? a : b;} + +static const lb_bc_open_vtable_t vt_ = { + (lb_bc_open_free_ft) lb_bc_outflow_rhou_free, + (lb_bc_open_update_ft) lb_bc_outflow_rhou_update, + (lb_bc_open_impose_ft) lb_bc_outflow_rhou_impose, + (lb_bc_open_stats_ft) lb_bc_outflow_rhou_stats +}; + +/***************************************************************************** + * + * lb_bc_outflow_rhou_create + * + *****************************************************************************/ + +__host__ int lb_bc_outflow_rhou_create(pe_t * pe, cs_t * cs, + const lb_bc_outflow_opts_t * options, + lb_bc_outflow_rhou_t ** outflow) { + lb_bc_outflow_rhou_t * bc = NULL; + + assert(pe); + assert(cs); + assert(options); + assert(outflow); + + bc = (lb_bc_outflow_rhou_t *) calloc(1, sizeof(lb_bc_outflow_rhou_t)); + assert(bc); + if (bc == NULL) pe_fatal(pe, "Failed to allocate lb_bc_outflow_rhou_t"); + + /* Pointers; superclass block */ + bc->pe = pe; + bc->cs = cs; + + bc->super.func = &vt_; + bc->super.id = LB_BC_OUTFLOW_RHOU; + + if (!lb_bc_outflow_opts_valid(*options)) { + /* Internal error if we reach this point. */ + pe_fatal(pe, "lb_bc_outflow_rhou_create: options invalid\n"); + } + bc->options = *options; + + lb_bc_outflow_rhou_init_internal(bc); + + *outflow = bc; + + return 0; +} + +/***************************************************************************** + * + * lb_bc_outflow_rhou_init_internal + * + *****************************************************************************/ + +__host__ int lb_bc_outflow_rhou_init_internal(lb_bc_outflow_rhou_t * outflow) { + + assert(outflow); + + if (outflow->options.flow[X]) lb_bc_outflow_init_link(outflow, LINK_COUNT, X); + if (outflow->options.flow[Y]) lb_bc_outflow_init_link(outflow, LINK_COUNT, Y); + if (outflow->options.flow[Z]) lb_bc_outflow_init_link(outflow, LINK_COUNT, Z); + + { + pe_t * pe = outflow->pe; + int nlink = int_max(1, outflow->nlink); /* No zero sized allocations. */ + + outflow->linkp = (int8_t *) calloc(nlink, sizeof(int8_t)); + outflow->linki = (int *) calloc(nlink, sizeof(int)); + outflow->linkj = (int *) calloc(nlink, sizeof(int)); + + assert(outflow->linkp); + assert(outflow->linki); + assert(outflow->linkj); + + if (outflow->linkp == NULL) pe_fatal(pe, "calloc(outflow->linkp) NULL\n"); + if (outflow->linki == NULL) pe_fatal(pe, "calloc(outflow->linki) NULL\n"); + if (outflow->linkj == NULL) pe_fatal(pe, "calloc(outflow->linkj) NULL\n"); + } + + if (outflow->options.flow[X]) lb_bc_outflow_init_link(outflow, LINK_ASSIGN, X); + if (outflow->options.flow[Y]) lb_bc_outflow_init_link(outflow, LINK_ASSIGN, Y); + if (outflow->options.flow[Z]) lb_bc_outflow_init_link(outflow, LINK_ASSIGN, Z); + + return 0; +} + +/***************************************************************************** + * + * lb_bc_outflow_init_link + * + * Identify links representing incoming distributions at the outflow + * which are fluid to fluid in the coordinate direction "id". + * + * This assumes that the other two directions are walls, and so no + * duplicates of incoming solid-fluid (bbl) links are wanted. + * + *****************************************************************************/ + +__host__ int lb_bc_outflow_init_link(lb_bc_outflow_rhou_t * outflow, + link_init_enum_t init, int id) { + + cs_t * cs = NULL; + int noffset[3] = {}; + int nlink = 0; + + assert(outflow); + assert(id == X || id == Y || id == Z); + + cs = outflow->cs; + cs_nlocal_offset(cs, noffset); + + if (noffset[id] == 0) { + int nmin[3] = {1, 1, 1}; + int ntotal[3] = {}; + int nlocal[3] = {}; + + lb_model_t model = {}; + lb_model_create(outflow->options.nvel, &model); + + cs_ntotal(cs, ntotal); + cs_nlocal(cs, nlocal); + + nmin[id] = nlocal[id]; /* Only rightmost edge in the relevant direction */ + + for (int ic = nmin[X]; ic <= nlocal[X]; ic++) { + for (int jc = nmin[Y]; jc <= nlocal[Y]; jc++) { + for (int kc = nmin[Z]; kc <= nlocal[Z]; kc++) { + + for (int p = 1; p < model.nvel; p++) { + + if (model.cv[p][id] != +1) continue; + + int ic1 = ic + model.cv[p][X]; + int jc1 = jc + model.cv[p][Y]; + int kc1 = kc + model.cv[p][Z]; + + /* Some shuffling to get "other 2 directions" */ + int id1 = (id + 1) % 3; + int id2 = (id + 2) % 3; + + int ijk[3] = {ic1, jc1, kc1}; + + if (noffset[id1] + ijk[id1] < 1 ) continue; + if (noffset[id1] + ijk[id1] > ntotal[id1]) continue; + if (noffset[id2] + ijk[id2] < 1 ) continue; + if (noffset[id2] + ijk[id2] > ntotal[id2]) continue; + + if (init == LINK_ASSIGN) { + outflow->linkp[nlink] = model.nvel - p; + outflow->linki[nlink] = cs_index(cs, ic1, jc1, kc1); + outflow->linkj[nlink] = cs_index(cs, ic, jc, kc); + } + nlink += 1; + } + } + } + } + + lb_model_free(&model); + } + + outflow->nlink = nlink; + + return 0; +} + +/***************************************************************************** + * + * lb_bc_outflow_rhou_free + * + *****************************************************************************/ + +__host__ int lb_bc_outflow_rhou_free(lb_bc_outflow_rhou_t * outflow) { + + assert(outflow); + + free(outflow->linkj); + free(outflow->linki); + free(outflow->linkp); + free(outflow); + + return 0; +} + +/***************************************************************************** + * + * lb_bc_outflow_rhou_update + * + * Set any relevant hydrodynamic conditions at the outflow: + * (1) rho is constant as prescribed + * (2) u is set to the value relevant at outflow. + * + *****************************************************************************/ + +__host__ int lb_bc_outflow_rhou_update(lb_bc_outflow_rhou_t * outflow, + hydro_t * hydro) { + + cs_t * cs = NULL; + int id = -1; + int noffset[3] = {}; + + assert(outflow); + assert(hydro); + + cs = outflow->cs; + cs_nlocal_offset(cs, noffset); + + if (outflow->options.flow[X]) id = X; + if (outflow->options.flow[Y]) id = Y; + if (outflow->options.flow[Z]) id = Z; + + + if (noffset[id] == 0) { + int nmin[3] = {1,1,1}; + int nlocal[3] = {}; + int idx = outflow->options.flow[X]; + int jdy = outflow->options.flow[Y]; + int kdz = outflow->options.flow[Z]; + + cs_nlocal(cs, nlocal); + + nmin[id] = nlocal[id]; /* Only rightmost edge in the relevant direction */ + + for (int ic = nmin[X]; ic <= nlocal[X]; ic++) { + for (int jc = nmin[Y]; jc <= nlocal[Y]; jc++) { + for (int kc = nmin[Z]; kc <= nlocal[Z]; kc++) { + + int index0 = cs_index(cs, ic + idx, jc + jdy, kc + kdz); + int index1 = cs_index(cs, ic, jc, kc); + double u[3] = {}; + + hydro_rho_set(hydro, index0, outflow->options.rho0); + hydro_u(hydro, index1, u); + hydro_u_set(hydro, index0, u); + } + } + } + } + + return 0; +} + +/***************************************************************************** + * + * lb_bc_outflow_rhou_impose + * + * ABSOLUTELY THE SAME + * Intent: After lattice halo swap; before propagation. + * + *****************************************************************************/ + +__host__ int lb_bc_outflow_rhou_impose(lb_bc_outflow_rhou_t * outflow, + hydro_t * hydro, + lb_t * lb) { + assert(outflow); + assert(hydro); + assert(lb); + + /* For each incoming link (at outflow) set f_p = f^eq_p (rho, u) */ + + for (int n = 0; n < outflow->nlink; n++) { + + int index = outflow->linki[n]; + int8_t p = outflow->linkp[n]; + + double rho = 0.0; + double u[3] = {}; + + hydro_rho(hydro, index, &rho); + hydro_u(hydro, index, u); + + { + double cs2 = lb->model.cs2; + double rcs2 = (1.0/cs2); + double udotc = 0.0; + double sdotq = 0.0; + double fp = 0.0; + + for (int ia = 0; ia < 3; ia++) { + udotc += u[ia]*lb->model.cv[p][ia]; + for (int ib = 0; ib < 3; ib++) { + double d_ab = (ia == ib); + double s_ab = lb->model.cv[p][ia]*lb->model.cv[p][ib] - cs2*d_ab; + + sdotq += s_ab*u[ia]*u[ib]; + } + } + + /* Here's the equilibrium */ + fp = rho*lb->model.wv[p]*(1.0 + rcs2*udotc + 0.5*rcs2*rcs2*sdotq); + lb_f_set(lb, index, p, LB_RHO, fp); + } + } + + return 0; +} + +/***************************************************************************** + * + * lb_bc_outflow_rhou_stats + * + * Placeholder. No operation at the moment. + * + *****************************************************************************/ + +__host__ int lb_bc_outflow_rhou_stats(lb_bc_outflow_rhou_t * outflow) { + + return 0; +} diff --git a/src/lb_bc_outflow_rhou.h b/src/lb_bc_outflow_rhou.h new file mode 100644 index 000000000..85aa7fa28 --- /dev/null +++ b/src/lb_bc_outflow_rhou.h @@ -0,0 +1,47 @@ +/***************************************************************************** + * + * lb_bc_outflow_rhou.h + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#ifndef LB_BC_OUTFLOW_RHOU_H +#define LB_BC_OUTFLOW_RHOU_H + +#include "lb_bc_open.h" +#include "lb_bc_outflow_opts.h" + +typedef struct lb_bc_outflow_rhou_s lb_bc_outflow_rhou_t; + +struct lb_bc_outflow_rhou_s { + lb_bc_open_t super; /* Superclass block "abstract class" */ + pe_t * pe; /* Parallel environment */ + cs_t * cs; /* Coordinate system */ + lb_bc_outflow_opts_t options; /* Parameters/options */ + + /* Boundary links */ + int nlink; /* Number of links (local) */ + int * linki; /* Fluid site boundary region */ + int * linkj; /* Fluid site in domain proper */ + int8_t * linkp; /* Velocity index in LB basis (i->j) */ +}; + +__host__ int lb_bc_outflow_rhou_create(pe_t * pe, cs_t * cs, + const lb_bc_outflow_opts_t * options, + lb_bc_outflow_rhou_t ** outflow); +__host__ int lb_bc_outflow_rhou_free(lb_bc_outflow_rhou_t * outflow); + +__host__ int lb_bc_outflow_rhou_update(lb_bc_outflow_rhou_t * outflow, + hydro_t * hydro); +__host__ int lb_bc_outflow_rhou_impose(lb_bc_outflow_rhou_t * outflow, + hydro_t * hydro, lb_t * lb); +__host__ int lb_bc_outflow_rhou_stats(lb_bc_outflow_rhou_t * outflow); + +#endif diff --git a/src/lb_inflow_rhou.h b/src/lb_inflow_rhou.h deleted file mode 100644 index f853ede6a..000000000 --- a/src/lb_inflow_rhou.h +++ /dev/null @@ -1,44 +0,0 @@ -/***************************************************************************** - * - * lb_inflow_rhou.h - * - *****************************************************************************/ - -#ifndef LUDWIG_LB_INFLOW_RHOU_H -#define LUDWIG_LB_INFLOW_RHOU_H - -#include "lb_open_bc.h" -#include "lb_openbc_options.h" - -typedef struct lb_inflow_rhou_s lb_inflow_rhou_t; - -/* Inflow boundary condition. */ - -struct lb_inflow_rhou_s { - lb_open_bc_t super; /* Superclass block */ - pe_t * pe; /* Parallel environment */ - cs_t * cs; /* Coordinate system */ - lb_openbc_options_t options; /* Options/parameters */ - lb_inflow_rhou_t * target; /* Target pointer */ - - /* Boundary links */ - int nlink; /* Number of links (local) */ - int8_t * linkp; /* Velocity index in LB basis (i->j) */ - int * linki; /* Fluid site in system */ - int * linkj; /* Fluid site in inflow halo boundary */ -}; - -__host__ int lb_inflow_rhou_create(pe_t * pe, cs_t * cs, - const lb_openbc_options_t * options, - lb_inflow_rhou_t ** inflow); - -__host__ int lb_inflow_rhou_free(lb_inflow_rhou_t * inflow); -__host__ int lb_inflow_rhou_update(lb_inflow_rhou_t * inflow, hydro_t * hydro); -__host__ int lb_inflow_rhou_impose(lb_inflow_rhou_t * inflow, hydro_t * hydro, - lb_t * lb); -__host__ int lb_inflow_rhou_stats(lb_inflow_rhou_t * inflow); - -__host__ int lb_inflow_rhou_info(lb_inflow_rhou_t * inflow); - -#endif - diff --git a/src/lb_model.c b/src/lb_model.c index 91b75a633..f65a02810 100644 --- a/src/lb_model.c +++ b/src/lb_model.c @@ -25,6 +25,38 @@ #include "lb_model.h" +/***************************************************************************** + * + * lb_model_is_available + * + *****************************************************************************/ + +int lb_model_is_available(int nvel) { + + int available = 0; + + available += (nvel == NVEL_D2Q9); + available += (nvel == NVEL_D3Q15); + available += (nvel == NVEL_D3Q19); + + return available; +} + +/***************************************************************************** + * + * lb_model_nhydro + * + *****************************************************************************/ + +int lb_model_nhydro(int ndim) { + + /* The number of hydrodynamic modes is (rho, u_a, S_ab): */ + + int nhydro = 1 + ndim + ndim*(ndim + 1)/2; + + return nhydro; +} + /***************************************************************************** * * lb_model_create diff --git a/src/lb_model.h b/src/lb_model.h index 37fe2be69..5e1a052a2 100644 --- a/src/lb_model.h +++ b/src/lb_model.h @@ -34,6 +34,8 @@ struct lb_model_s { double cs2; /* (speed of sound)^2 */ }; +int lb_model_is_available(int nvel); +int lb_model_nhydro(int ndim); int lb_model_create(int nvel, lb_model_t * model); int lb_model_free(lb_model_t * model); diff --git a/src/lb_open_bc.h b/src/lb_open_bc.h deleted file mode 100644 index b55123ab0..000000000 --- a/src/lb_open_bc.h +++ /dev/null @@ -1,54 +0,0 @@ -/***************************************************************************** - * - * lb_open_bc.h - * - * Lattice fluid open boundary condition (abstract type). - * - * Edinburgh Soft Matter and Statistical Physics Group and - * Edinburgh Parallel Computing Centre - * - * (c) 2021 The University of Edinburgh - * - * Contributing authors: - * Kevin Stratford (kevin@epcc.ed.ac.uk) - * - *****************************************************************************/ - -#ifndef LUDWIG_LB_OPEN_BC_H -#define LUDWIG_LB_OPEN_BC_H - -#include "hydro.h" -#include "model.h" - -/* Implementations available */ - -typedef enum {LB_OPEN_BC_INFLOW_RHOU} lb_open_bc_enum_t; - -typedef struct lb_open_bc_vtable_s lb_open_bc_vtable_t; -typedef struct lb_open_bc_s lb_open_bc_t; - -/* Abstract function table */ -/* lb_open_bc_free_ft is destructor */ -/* lb_open_bc_update_ft update driver to set (rho, u) */ -/* lb_open_bc_impose_ft apply conditions (set relevant f_i) */ -/* lb_open_bc_stats_ft general purpose stats with optional extra info */ - -typedef int (* lb_open_bc_free_ft) (lb_open_bc_t * bc); -typedef int (* lb_open_bc_update_ft) (lb_open_bc_t * bc, hydro_t * hydro); -typedef int (* lb_open_bc_impose_ft) (lb_open_bc_t * bc, hydro_t * hydro, - lb_t * lb); -typedef int (* lb_open_bc_stats_ft) (lb_open_bc_t * bc); - -struct lb_open_bc_vtable_s { - lb_open_bc_free_ft free; /* Desctructor */ - lb_open_bc_update_ft update; /* Update */ - lb_open_bc_impose_ft impose; /* Apply update to distributions */ - lb_open_bc_stats_ft stats; /* General information */ -}; - -struct lb_open_bc_s { - const lb_open_bc_vtable_t * func; /* function table */ - lb_open_bc_enum_t id; /* unique type identifier */ -}; - -#endif diff --git a/tests/unit/test_lb_inflow_rhou.c b/tests/unit/test_lb_bc_inflow_rhou.c similarity index 79% rename from tests/unit/test_lb_inflow_rhou.c rename to tests/unit/test_lb_bc_inflow_rhou.c index d9cf6744a..baf367796 100644 --- a/tests/unit/test_lb_inflow_rhou.c +++ b/tests/unit/test_lb_bc_inflow_rhou.c @@ -1,6 +1,6 @@ /***************************************************************************** * - * test_lb_inflow_rhou.c + * test_lb_bc_inflow_rhou.c * * (c) 2021 The University of Edinburgh * @@ -16,21 +16,21 @@ #include #include -#include "lb_inflow_rhou.h" +#include "lb_bc_inflow_rhou.h" /* Tests */ -__host__ int test_lb_inflow_rhou_create(pe_t * pe, cs_t * cs); -__host__ int test_lb_inflow_rhou_update(pe_t * pe, cs_t * cs); -__host__ int test_lb_inflow_rhou_impose(pe_t * pe, cs_t * cs); +__host__ int test_lb_bc_inflow_rhou_create(pe_t * pe, cs_t * cs); +__host__ int test_lb_bc_inflow_rhou_update(pe_t * pe, cs_t * cs); +__host__ int test_lb_bc_inflow_rhou_impose(pe_t * pe, cs_t * cs); /***************************************************************************** * - * test_lb_inflow_rhou_suite + * test_lb_bc_inflow_rhou_suite * *****************************************************************************/ -__host__ int test_lb_inflow_rhou_suite(void) { +__host__ int test_lb_bc_inflow_rhou_suite(void) { pe_t * pe = NULL; cs_t * cs = NULL; @@ -39,11 +39,11 @@ __host__ int test_lb_inflow_rhou_suite(void) { cs_create(pe, &cs); cs_init(cs); - test_lb_inflow_rhou_create(pe, cs); - test_lb_inflow_rhou_update(pe, cs); - test_lb_inflow_rhou_impose(pe, cs); + test_lb_bc_inflow_rhou_create(pe, cs); + test_lb_bc_inflow_rhou_update(pe, cs); + test_lb_bc_inflow_rhou_impose(pe, cs); - pe_info(pe, "PASS ./unit/test_lb_inflow_rhou\n"); + pe_info(pe, "PASS ./unit/test_lb_bc_inflow_rhou\n"); cs_free(cs); pe_free(pe); @@ -53,26 +53,26 @@ __host__ int test_lb_inflow_rhou_suite(void) { /***************************************************************************** * - * test_lb_inflow_rhou_create + * test_lb_bc_inflow_rhou_create * *****************************************************************************/ -__host__ int test_lb_inflow_rhou_create(pe_t * pe, cs_t * cs) { +__host__ int test_lb_bc_inflow_rhou_create(pe_t * pe, cs_t * cs) { lb_openbc_options_t options = lb_openbc_options_default(); - lb_inflow_rhou_t * inflow = NULL; + lb_bc_inflow_rhou_t * inflow = NULL; assert(pe); assert(cs); - lb_inflow_rhou_create(pe, cs, &options, &inflow); + lb_bc_inflow_rhou_create(pe, cs, &options, &inflow); assert(inflow); assert(inflow->pe == pe); assert(inflow->cs = cs); assert(inflow->super.func); - assert(inflow->super.id == LB_OPEN_BC_INFLOW_RHOU); + assert(inflow->super.id == LB_BC_INFLOW_RHOU); /* Check options */ @@ -85,14 +85,14 @@ __host__ int test_lb_inflow_rhou_create(pe_t * pe, cs_t * cs) { assert(inflow->linki); assert(inflow->linkj); - lb_inflow_rhou_free(inflow); + lb_bc_inflow_rhou_free(inflow); return 0; } /***************************************************************************** * - * test_lb_inflow_rhou_update + * test_lb_bc_inflow_rhou_update * *****************************************************************************/ @@ -104,11 +104,11 @@ typedef struct limits_s { /***************************************************************************** * - * test_lb_inflow_rhou_update + * test_lb_bc_inflow_rhou_update * *****************************************************************************/ -__host__ int test_lb_inflow_rhou_update(pe_t * pe, cs_t * cs) { +__host__ int test_lb_bc_inflow_rhou_update(pe_t * pe, cs_t * cs) { int nlocal[3] = {}; int noffset[3] = {}; @@ -116,7 +116,7 @@ __host__ int test_lb_inflow_rhou_update(pe_t * pe, cs_t * cs) { lb_openbc_options_t options = {.flow = {1, 0, 0}, .u0 = {-1.0,-2.0,-3.0}}; - lb_inflow_rhou_t * inflow = NULL; + lb_bc_inflow_rhou_t * inflow = NULL; hydro_t * hydro = NULL; assert(pe); @@ -125,7 +125,7 @@ __host__ int test_lb_inflow_rhou_update(pe_t * pe, cs_t * cs) { cs_nlocal(cs, nlocal); cs_nlocal_offset(cs, noffset); - lb_inflow_rhou_create(pe, cs, &options, &inflow); + lb_bc_inflow_rhou_create(pe, cs, &options, &inflow); hydro_create(pe, cs, NULL, 1, &hydro); /* Set the relevant domain values (rho only here) */ @@ -147,7 +147,7 @@ __host__ int test_lb_inflow_rhou_update(pe_t * pe, cs_t * cs) { /* Run the update. */ /* Check rho, u = 0 in the boundary region are set */ - lb_inflow_rhou_update(inflow, hydro); + lb_bc_inflow_rhou_update(inflow, hydro); if (noffset[X] == 0) { @@ -173,18 +173,18 @@ __host__ int test_lb_inflow_rhou_update(pe_t * pe, cs_t * cs) { } hydro_free(hydro); - lb_inflow_rhou_free(inflow); + lb_bc_inflow_rhou_free(inflow); return 0; } /***************************************************************************** * - * test_lb_inflow_rhou_impose + * test_lb_bc_inflow_rhou_impose * *****************************************************************************/ -__host__ int test_lb_inflow_rhou_impose(pe_t * pe, cs_t * cs) { +__host__ int test_lb_bc_inflow_rhou_impose(pe_t * pe, cs_t * cs) { int ierr = 0; @@ -197,7 +197,7 @@ __host__ int test_lb_inflow_rhou_impose(pe_t * pe, cs_t * cs) { lb_openbc_options_t options = {.nvel = NVEL, .flow = {1, 0, 0}, .u0 = {0.01, 0.0, 0.0}}; - lb_inflow_rhou_t * inflow = NULL; + lb_bc_inflow_rhou_t * inflow = NULL; hydro_t * hydro = NULL; lb_t * lb = NULL; @@ -210,7 +210,7 @@ __host__ int test_lb_inflow_rhou_impose(pe_t * pe, cs_t * cs) { cs_ntotal(cs, ntotal); cs_nlocal_offset(cs, noffset); - lb_inflow_rhou_create(pe, cs, &options, &inflow); + lb_bc_inflow_rhou_create(pe, cs, &options, &inflow); hydro_create(pe, cs, NULL, 1, &hydro); lb_create(pe, cs, &lb); lb_init(lb); @@ -231,8 +231,8 @@ __host__ int test_lb_inflow_rhou_impose(pe_t * pe, cs_t * cs) { } } - lb_inflow_rhou_update(inflow, hydro); - lb_inflow_rhou_impose(inflow, hydro, lb); + lb_bc_inflow_rhou_update(inflow, hydro); + lb_bc_inflow_rhou_impose(inflow, hydro, lb); /* Check relevant f_i are set correctly. */ /* So, for each site in the boundary region, check ingoing distributions. */ @@ -270,7 +270,7 @@ __host__ int test_lb_inflow_rhou_impose(pe_t * pe, cs_t * cs) { lb_free(lb); hydro_free(hydro); - lb_inflow_rhou_free(inflow); + lb_bc_inflow_rhou_free(inflow); return ierr; } diff --git a/tests/unit/test_lb_bc_outflow_opts.c b/tests/unit/test_lb_bc_outflow_opts.c new file mode 100644 index 000000000..ea5cb17ca --- /dev/null +++ b/tests/unit/test_lb_bc_outflow_opts.c @@ -0,0 +1,94 @@ +/***************************************************************************** + * + * test_lb_bc_outflow_opts.c + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#include + +#include "pe.h" +#include "lb_bc_outflow_opts.h" + +__host__ int test_lb_bc_outflow_opts_default(void); +__host__ int test_lb_bc_outflow_opts_valid(void); + +/***************************************************************************** + * + * test_lb_bc_outflow_opts_suite + * + *****************************************************************************/ + +__host__ int test_lb_bc_outflow_opts_suite(void) { + + pe_t * pe = NULL; + + pe_create(MPI_COMM_WORLD, PE_QUIET, &pe); + + test_lb_bc_outflow_opts_default(); + test_lb_bc_outflow_opts_valid(); + + pe_info(pe, "PASS ./unit/test_lb_bc_outflow_opts\n"); + pe_free(pe); + + return 0; +} + +/***************************************************************************** + * + * test_lb_bc_outflo_opts_default + * + *****************************************************************************/ + +__host__ int test_lb_bc_outflow_opts_default(void) { + + lb_bc_outflow_opts_t defaults = lb_bc_outflow_opts_default(); + + assert(defaults.nvel == 0); + assert(defaults.flow[X] == 0); + assert(defaults.flow[Y] == 0); + assert(defaults.flow[Z] == 0); + + return defaults.nvel; +} + +/***************************************************************************** + * + * test_lb_bc_outflow_opts_valid + * + *****************************************************************************/ + +__host__ int test_lb_bc_outflow_opts_valid(void) { + + int ierr = 0; + + { + lb_bc_outflow_opts_t options = lb_bc_outflow_opts_default(); + + ierr = lb_bc_outflow_opts_valid(options); + assert(ierr == 0); + } + + { + lb_bc_outflow_opts_t options = {.nvel = 9, .flow = {1, 0, 0}}; + + ierr = lb_bc_outflow_opts_valid(options); + assert(ierr != 0); + } + + { + lb_bc_outflow_opts_t options = {.nvel = 9, .flow = {1, 1, 0}}; + + ierr = lb_bc_outflow_opts_valid(options); + assert(ierr == 0); + } + + return ierr; +} diff --git a/tests/unit/test_lb_model.c b/tests/unit/test_lb_model.c index f6598348f..d204ea178 100644 --- a/tests/unit/test_lb_model.c +++ b/tests/unit/test_lb_model.c @@ -23,7 +23,7 @@ #include "util.h" #include "lb_model.h" - +int test_lb_model_nhydro(void); int test_lb_model_create(int nvel); int test_lb_model_cv(const lb_model_t * model); int test_lb_model_wv(const lb_model_t * model); @@ -41,6 +41,7 @@ int test_lb_model_suite(void) { pe_create(MPI_COMM_WORLD, PE_QUIET, &pe); + test_lb_model_nhydro(); test_lb_model_create(9); test_lb_model_create(15); test_lb_model_create(19); @@ -52,6 +53,20 @@ int test_lb_model_suite(void) { return 0; } +/***************************************************************************** + * + * test_lb_model_nhydro + * + *****************************************************************************/ + +int test_lb_model_nhydro(void) { + + assert(lb_model_nhydro(2) == 6); + assert(lb_model_nhydro(3) == 10); + + return 0; +} + /***************************************************************************** * * test_lb_model_create diff --git a/tests/unit/tests.c b/tests/unit/tests.c index 86623ee68..3173b124c 100644 --- a/tests/unit/tests.c +++ b/tests/unit/tests.c @@ -76,7 +76,8 @@ __host__ int tests_create() { test_lb_d3q19_suite(); test_lb_model_suite(); test_lb_openbc_options_suite(); - test_lb_inflow_rhou_suite(); + test_lb_bc_inflow_rhou_suite(); + test_lb_bc_outflow_opts_suite(); test_le_suite(); test_lubrication_suite(); test_map_suite(); diff --git a/tests/unit/tests.h b/tests/unit/tests.h index 48269b938..fd7465d8a 100644 --- a/tests/unit/tests.h +++ b/tests/unit/tests.h @@ -56,7 +56,8 @@ int test_lb_d3q15_suite(void); int test_lb_d3q19_suite(void); int test_lb_model_suite(void); int test_lb_openbc_options_suite(void); -int test_lb_inflow_rhou_suite(void); +int test_lb_bc_inflow_rhou_suite(void); +int test_lb_bc_outflow_opts_suite(void); int test_le_suite(void); int test_kernel_suite(void); int test_lubrication_suite(void); From eb810c59cb537b62736a8d235d454fc3111805d1 Mon Sep 17 00:00:00 2001 From: Oliver Henrich Date: Mon, 15 Nov 2021 14:27:06 +0000 Subject: [PATCH 045/117] Added routines for bulk and gradient stress --- src/phi_force_stress.c | 70 +++++++++++++++++++++++++++++++++++++++++- src/phi_force_stress.h | 3 ++ 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/src/phi_force_stress.c b/src/phi_force_stress.c index 58ff5bcf8..855de767c 100644 --- a/src/phi_force_stress.c +++ b/src/phi_force_stress.c @@ -25,6 +25,7 @@ #include "kernel.h" #include "pth_s.h" #include "phi_force_stress.h" +#include "blue_phase.h" __global__ void pth_kernel(kernel_ctxt_t * ktx, pth_t * pth, fe_t * fe); __global__ void pth_kernel_v(kernel_ctxt_t * ktx, pth_t * pth, fe_t * fe); @@ -160,7 +161,7 @@ __host__ int pth_memcpy(pth_t * pth, tdpMemcpyKind flag) { /***************************************************************************** * - * phi_force_stress_compute + * pth_stress_compute * * Compute the stress everywhere and store. This allows that the * full stress, or just the antisymmetric part is needed. @@ -334,6 +335,73 @@ __global__ void pth_kernel_a_v(kernel_ctxt_t * ktx, pth_t * pth, fe_t * fe) { return; } +/***************************************************************************** + * + * pth_bulk_stress_compute + * + * Compute the stress from bulk FE terms everywhere and store. + * + *****************************************************************************/ + +__host__ int pth_bulk_stress_compute(pth_t * pth, fe_lc_t * fe) { + + int ic, jc, kc; + int index,nlocal[3]; + double sth[3][3]; + + assert(pth); + assert(fe); + + cs_nlocal(pth->cs, nlocal); + + for (ic = 1; ic <= nlocal[X]; ic++) { + for (jc = 1; jc <= nlocal[Y]; jc++) { + for (kc = 1; kc <= nlocal[Z]; kc++) { + + index = cs_index(pth->cs, ic, jc, kc); + fe_lc_bulk_stress(fe, index, sth); + pth_stress_set(pth, index, sth); + + } + } + } + + return 0; +} + +/***************************************************************************** + * + * pth_gradient_stress_compute + * + * Compute the stress from gradient FE terms everywhere and store. + * + *****************************************************************************/ + +__host__ int pth_gradient_stress_compute(pth_t * pth, fe_lc_t * fe) { + + int ic, jc, kc; + int index,nlocal[3]; + double sth[3][3]; + + assert(pth); + assert(fe); + + cs_nlocal(pth->cs, nlocal); + + for (ic = 1; ic <= nlocal[X]; ic++) { + for (jc = 1; jc <= nlocal[Y]; jc++) { + for (kc = 1; kc <= nlocal[Z]; kc++) { + + index = cs_index(pth->cs, ic, jc, kc); + fe_lc_grad_stress(fe, index, sth); + pth_stress_set(pth, index, sth); + + } + } + } + + return 0; +} /***************************************************************************** * diff --git a/src/phi_force_stress.h b/src/phi_force_stress.h index 37bbb5c40..7ee06473f 100644 --- a/src/phi_force_stress.h +++ b/src/phi_force_stress.h @@ -20,6 +20,7 @@ #include "pe.h" #include "coords.h" #include "free_energy.h" +#include "blue_phase.h" enum {PTH_METHOD_NO_FORCE, PTH_METHOD_DIVERGENCE, PTH_METHOD_GRADMU, PTH_METHOD_STRESS_ONLY}; @@ -30,6 +31,8 @@ __host__ int pth_create(pe_t * pe, cs_t * cs, int method, pth_t ** pth); __host__ int pth_free(pth_t * pth); __host__ int pth_memcpy(pth_t * pth, tdpMemcpyKind flag); __host__ int pth_stress_compute(pth_t * pth, fe_t * fe); +__host__ int pth_bulk_stress_compute(pth_t * pth, fe_lc_t * fe); +__host__ int pth_gradient_stress_compute(pth_t * pth, fe_lc_t * fe); __host__ __device__ void pth_stress(pth_t * pth, int index, double p[3][3]); __host__ __device__ void pth_stress_set(pth_t * pth, int index, double p[3][3]); From 07bef52720c830365774ae25bc72252e5b5e4ad5 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Mon, 15 Nov 2021 15:00:02 +0000 Subject: [PATCH 046/117] Add outflow test; move inflow options --- src/lb_bc_inflow_opts.c | 71 ++++++++ src/lb_bc_inflow_opts.h | 34 ++++ src/lb_bc_inflow_rhou.c | 6 +- src/lb_bc_inflow_rhou.h | 6 +- src/lb_bc_outflow_opts.c | 4 +- src/lb_bc_outflow_opts.h | 1 - src/lb_openbc_options.c | 151 ----------------- src/lb_openbc_options.h | 48 ------ tests/unit/test_lb_bc_inflow_opts.c | 140 ++++++++++++++++ tests/unit/test_lb_bc_inflow_rhou.c | 11 +- tests/unit/test_lb_bc_outflow_opts.c | 4 +- tests/unit/test_lb_bc_outflow_rhou.c | 237 +++++++++++++++++++++++++++ tests/unit/test_lb_openbc_options.c | 211 ------------------------ tests/unit/tests.c | 3 +- tests/unit/tests.h | 3 +- 15 files changed, 502 insertions(+), 428 deletions(-) create mode 100644 src/lb_bc_inflow_opts.c create mode 100644 src/lb_bc_inflow_opts.h delete mode 100644 src/lb_openbc_options.c delete mode 100644 src/lb_openbc_options.h create mode 100644 tests/unit/test_lb_bc_inflow_opts.c create mode 100644 tests/unit/test_lb_bc_outflow_rhou.c delete mode 100644 tests/unit/test_lb_openbc_options.c diff --git a/src/lb_bc_inflow_opts.c b/src/lb_bc_inflow_opts.c new file mode 100644 index 000000000..541eefaca --- /dev/null +++ b/src/lb_bc_inflow_opts.c @@ -0,0 +1,71 @@ +/***************************************************************************** + * + * lb_bc_inflow_opts.c + * + * Options container for inflow open boundary conditions. + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#include +#include + +#include "lb_bc_inflow_opts.h" + + +/***************************************************************************** + * + * lb_bc_inflow_opts_default + * + *****************************************************************************/ + +lb_bc_inflow_opts_t lb_bc_inflow_opts_default(void) { + + lb_bc_inflow_opts_t opts = {.nvel = 19, .flow = {}, .u0 = {}}; + + return opts; +} + +/***************************************************************************** + * + * lb_bc_inflow_opts_valid + * + *****************************************************************************/ + +int lb_bc_inflow_opts_valid(lb_bc_inflow_opts_t options) { + + int valid = 0; /* 0 = invalid */ + + int oknvel = lb_model_is_available(options.nvel); + int okflow = lb_bc_inflow_opts_flow_valid(options.flow); + + /* No conditions on u0 at the moment. */ + + valid = (oknvel && okflow); + + return valid; +} + +/***************************************************************************** + * + * lb_bc_inflow_opts_flow_valid + * + *****************************************************************************/ + +int lb_bc_inflow_opts_flow_valid(const int flow[3]) { + + int isvalid = 0; + int sum = flow[0] + flow[1] + flow[2]; + + /* No flow is ok; otherwise only one direction. */ + isvalid = (sum == 0) || (sum == 1); + + return isvalid; +} diff --git a/src/lb_bc_inflow_opts.h b/src/lb_bc_inflow_opts.h new file mode 100644 index 000000000..067de28bc --- /dev/null +++ b/src/lb_bc_inflow_opts.h @@ -0,0 +1,34 @@ +/***************************************************************************** + * + * lb_bc_inflow_opts.h + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Comuting Centre + * + * (c) 2021 The University of Edinburgh + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#ifndef LUDWIG_LB_BC_INFLOW_OPTS_H +#define LUDWIG_LB_BC_INFLOW_OPTS_H + +#include "lb_model.h" + +/* TYPES */ + +typedef struct lb_bc_inflow_opts_s lb_bc_inflow_opts_t; + +struct lb_bc_inflow_opts_s { + int nvel; /* Model */ + int flow[3]; /* Flow coordinate direction (exactly 1) */ + double u0[3]; /* A velocity for the boundary */ +}; + +lb_bc_inflow_opts_t lb_bc_inflow_opts_default(void); + +int lb_bc_inflow_opts_valid(lb_bc_inflow_opts_t options); +int lb_bc_inflow_opts_flow_valid(const int flow[3]); + +#endif diff --git a/src/lb_bc_inflow_rhou.c b/src/lb_bc_inflow_rhou.c index 00bee7997..6c0692b7d 100644 --- a/src/lb_bc_inflow_rhou.c +++ b/src/lb_bc_inflow_rhou.c @@ -50,7 +50,7 @@ static const lb_bc_open_vtable_t vt_ = { *****************************************************************************/ __host__ int lb_bc_inflow_rhou_create(pe_t * pe, cs_t * cs, - const lb_openbc_options_t * options, + const lb_bc_inflow_opts_t * options, lb_bc_inflow_rhou_t ** inflow) { lb_bc_inflow_rhou_t * bc = NULL; @@ -70,7 +70,7 @@ __host__ int lb_bc_inflow_rhou_create(pe_t * pe, cs_t * cs, bc->super.func = &vt_; bc->super.id = LB_BC_INFLOW_RHOU; - if (!lb_openbc_options_valid(options)) { + if (!lb_bc_inflow_opts_valid(*options)) { /* Internal error if we reach this point. */ pe_fatal(pe, "lb_bc_inflow_rhou_create: lb_openbc_options_t invalid\n"); } @@ -265,7 +265,7 @@ __host__ int lb_bc_inflow_rhou_update(lb_bc_inflow_rhou_t * inflow, int index0 = cs_index(cs, ic - idx, jc - jdy, kc - kdz); int index1 = cs_index(cs, ic, jc, kc); - double rho = 1.0; + double rho = 0.0; hydro_rho(hydro, index1, &rho); hydro_rho_set(hydro, index0, rho); diff --git a/src/lb_bc_inflow_rhou.h b/src/lb_bc_inflow_rhou.h index 97eaebd8f..0417c84e7 100644 --- a/src/lb_bc_inflow_rhou.h +++ b/src/lb_bc_inflow_rhou.h @@ -16,7 +16,7 @@ #define LUDWIG_LB_BC_INFLOW_RHOU_H #include "lb_bc_open.h" -#include "lb_openbc_options.h" +#include "lb_bc_inflow_opts.h" typedef struct lb_bc_inflow_rhou_s lb_bc_inflow_rhou_t; @@ -26,7 +26,7 @@ struct lb_bc_inflow_rhou_s { lb_bc_open_t super; /* Superclass block */ pe_t * pe; /* Parallel environment */ cs_t * cs; /* Coordinate system */ - lb_openbc_options_t options; /* Options/parameters */ + lb_bc_inflow_opts_t options; /* Options/parameters */ lb_bc_inflow_rhou_t * target; /* Target pointer */ /* Boundary links */ @@ -37,7 +37,7 @@ struct lb_bc_inflow_rhou_s { }; __host__ int lb_bc_inflow_rhou_create(pe_t * pe, cs_t * cs, - const lb_openbc_options_t * options, + const lb_bc_inflow_opts_t * options, lb_bc_inflow_rhou_t ** inflow); __host__ int lb_bc_inflow_rhou_free(lb_bc_inflow_rhou_t * inflow); diff --git a/src/lb_bc_outflow_opts.c b/src/lb_bc_outflow_opts.c index 9f7e5bce4..406dae84f 100644 --- a/src/lb_bc_outflow_opts.c +++ b/src/lb_bc_outflow_opts.c @@ -22,7 +22,7 @@ lb_bc_outflow_opts_t lb_bc_outflow_opts_default(void) { - lb_bc_outflow_opts_t opts = {.nvel = 0, .flow = {}, .rho0 = 1.0, .u0 = {}}; + lb_bc_outflow_opts_t opts = {.nvel = 19, .flow = {}, .rho0 = 1.0}; return opts; } @@ -42,7 +42,7 @@ int lb_bc_outflow_opts_valid(lb_bc_outflow_opts_t options) { isvalid = lb_model_is_available(options.nvel); /* Available */ isvalid = (isvalid && (sum == 0 || sum == 1)); /* One direction, or none */ - /* We're not making any stipulations about (rho, u0). */ + /* We're not making any stipulations about rho. */ return isvalid; } diff --git a/src/lb_bc_outflow_opts.h b/src/lb_bc_outflow_opts.h index cac85f76e..0137da550 100644 --- a/src/lb_bc_outflow_opts.h +++ b/src/lb_bc_outflow_opts.h @@ -26,7 +26,6 @@ struct lb_bc_outflow_opts_s { int nvel; int flow[3]; double rho0; - double u0[3]; }; lb_bc_outflow_opts_t lb_bc_outflow_opts_default(void); diff --git a/src/lb_openbc_options.c b/src/lb_openbc_options.c deleted file mode 100644 index 1eb3255da..000000000 --- a/src/lb_openbc_options.c +++ /dev/null @@ -1,151 +0,0 @@ -/***************************************************************************** - * - * lb_openbc_options.c - * - * Options container for fluid open boundary conditions. - * - * Edinburgh Soft Matter and Statistical Physics Group and - * Edinburgh Parallel Computing Centre - * - * (c) 2021 The University of Edinburgh - * - * Contributing authors: - * Kevin Stratford (kevin@epcc.ed.ac.uk) - * - *****************************************************************************/ - -#include -#include - -#include "lb_openbc_options.h" - -/* Defaults */ - -#define LB_INFLOW_DEFAULT() LB_INFLOW_NONE -#define LB_OUTFLOW_DEFAULT() LB_OUTFLOW_NONE -#define LB_FLOW_DEFAULT() {0,0,0} -#define LB_FLOW_U0_DEFAULT() {0.0,0.0,0.0} - -/***************************************************************************** - * - * lb_openbc_options_inflow_default - * - *****************************************************************************/ - -__host__ lb_inflow_enum_t lb_openbc_options_inflow_default(void) { - - return LB_INFLOW_DEFAULT(); -} - -/***************************************************************************** - * - * lb_options_openbc_outflow_default - * - *****************************************************************************/ - -__host__ lb_outflow_enum_t lb_openbc_options_outflow_default(void) { - - return LB_OUTFLOW_DEFAULT(); -} - -/***************************************************************************** - * - * lb_openbc_options_default - * - *****************************************************************************/ - -__host__ lb_openbc_options_t lb_openbc_options_default(void) { - - lb_openbc_options_t options = {.bctype = 0, - .inflow = LB_INFLOW_DEFAULT(), - .outflow = LB_OUTFLOW_DEFAULT(), - .flow = LB_FLOW_DEFAULT(), - .u0 = LB_FLOW_U0_DEFAULT()}; - - return options; -} - -/***************************************************************************** - * - * lb_openbc_options_valid - * - *****************************************************************************/ - -__host__ int lb_openbc_options_valid(const lb_openbc_options_t * options) { - - int valid = 0; /* 0 = invalid */ - - valid += lb_openbc_options_inflow_valid(options->inflow); - valid += lb_openbc_options_outflow_valid(options->outflow); - valid += lb_openbc_options_flow_valid(options->flow); - - return valid; -} - -/***************************************************************************** - * - * lb_openbc_options_inflow_valid - * - *****************************************************************************/ - -__host__ int lb_openbc_options_inflow_valid(lb_inflow_enum_t inflow) { - - int isvalid = 0; /* 0 = invalid */ - - isvalid += (inflow == LB_INFLOW_NONE); - - return isvalid; -} - -/***************************************************************************** - * - * lb_openbc_options_outflow_valid - * - *****************************************************************************/ - -__host__ int lb_openbc_options_outflow_valid(lb_outflow_enum_t outflow) { - - int isvalid = 0; /* 0 = invalid */ - - isvalid += (outflow == LB_OUTFLOW_NONE); - - return isvalid; -} - -/***************************************************************************** - * - * lb_openbc_options_flow_valid - * - *****************************************************************************/ - -__host__ int lb_openbc_options_flow_valid(const int flow[3]) { - - int isvalid = 0; - int sum = flow[0] + flow[1] + flow[2]; - - /* No flow is ok; otherwise only one direction. */ - isvalid = (sum == 0) || (sum == 1); - - return isvalid; -} - -/***************************************************************************** - * - * lb_openbc_options_info - * - *****************************************************************************/ - -__host__ int lb_openbc_options_info(pe_t * pe, - const lb_openbc_options_t * options) { - - assert(pe); - assert(options); - - pe_info(pe, "bctype: %d\n", options->bctype); - pe_info(pe, "inflow: %d\n", options->inflow); - pe_info(pe, "outflow: %d\n", options->outflow); - pe_info(pe, "flow: %1d %1d %1d\n", options->flow[0], options->flow[1], - options->flow[2]); - - return 0; -} diff --git a/src/lb_openbc_options.h b/src/lb_openbc_options.h deleted file mode 100644 index f629f7d9a..000000000 --- a/src/lb_openbc_options.h +++ /dev/null @@ -1,48 +0,0 @@ -/***************************************************************************** - * - * lb_openbc_options.h - * - * Edinburgh Soft Matter and Statistical Physics Group and - * Edinburgh Parallel Comuting Centre - * - * (c) 2021 The University of Edinburgh - * Contributing authors: - * Kevin Stratford (kevin@epcc.ed.ac.uk) - * - *****************************************************************************/ - -#ifndef LUDWIG_LB_OPENBC_OPTIONS_H -#define LUDWIG_LB_OPENBC_OPTIONS_H - -#include "pe.h" - -/* TYPES */ - -enum lb_inflow_enum {LB_INFLOW_INVALID = 0, LB_INFLOW_NONE, LB_INFLOW_MAX}; -enum lb_outflow_enum {LB_OUTFLOW_INVALID = 0, LB_OUTFLOW_NONE, LB_OUTFLOW_MAX}; - -typedef enum lb_inflow_enum lb_inflow_enum_t; -typedef enum lb_outflow_enum lb_outflow_enum_t; -typedef struct lb_openbc_options_s lb_openbc_options_t; - -struct lb_openbc_options_s { - int bctype; /* Combination of inflow/outflow? */ - int nvel; - lb_inflow_enum_t inflow; /* Inflow boundary condition type */ - lb_outflow_enum_t outflow; /* Outflow boundary condition type */ - int flow[3]; /* Flow coordinate direction (exactly 1) */ - double u0[3]; /* A velocity */ -}; - -__host__ lb_inflow_enum_t lb_openbc_options_inflow_default(void); -__host__ lb_outflow_enum_t lb_openbc_options_outflow_default(void); -__host__ lb_openbc_options_t lb_openbc_options_default(void); - -__host__ int lb_openbc_options_valid(const lb_openbc_options_t * options); -__host__ int lb_openbc_options_inflow_valid(lb_inflow_enum_t inflow); -__host__ int lb_openbc_options_outflow_valid(lb_outflow_enum_t outflow); -__host__ int lb_openbc_options_flow_valid(const int flow[3]); - -__host__ int lb_openbc_options_info(pe_t * pe, const lb_openbc_options_t *); - -#endif diff --git a/tests/unit/test_lb_bc_inflow_opts.c b/tests/unit/test_lb_bc_inflow_opts.c new file mode 100644 index 000000000..f10743536 --- /dev/null +++ b/tests/unit/test_lb_bc_inflow_opts.c @@ -0,0 +1,140 @@ +/***************************************************************************** + * + * test_lb_bc_inflow_opts.c + * + * + * Edinburgh Solft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#include +#include + +#include "pe.h" +#include "lb_bc_inflow_opts.h" + +__host__ int test_lb_bc_inflow_opts_default(void); +__host__ int test_lb_bc_inflow_opts_flow_valid(void); +__host__ int test_lb_bc_inflow_opts_valid(void); + +/***************************************************************************** + * + * test_lb_bc_inflow_opts_suite + * + *****************************************************************************/ + +__host__ int test_lb_bc_inflow_opts_suite(void) { + + pe_t * pe = NULL; + + pe_create(MPI_COMM_WORLD, PE_QUIET, &pe); + + test_lb_bc_inflow_opts_default(); + test_lb_bc_inflow_opts_flow_valid(); + test_lb_bc_inflow_opts_valid(); + + pe_info(pe, "PASS ./unit/test_lb_bc_inflow_opts\n"); + + pe_free(pe); + + return 0; +} + +/***************************************************************************** + * + * test_lb_bc_inflow_opts_default + * + *****************************************************************************/ + +__host__ int test_lb_bc_inflow_opts_default(void) { + + int isvalid = 0; + + { + lb_bc_inflow_opts_t options = lb_bc_inflow_opts_default(); + + assert(options.nvel == 19); + assert(options.flow[X] == 0); + assert(options.flow[Y] == 0); + assert(options.flow[Z] == 0); + + isvalid = lb_bc_inflow_opts_valid(options); + } + + return isvalid; +} + +/***************************************************************************** + * + * test_lb_bc_inflow_opts_flow_valid + * + *****************************************************************************/ + +__host__ int test_lb_bc_inflow_opts_flow_valid(void) { + + int isvalid = 0; + + { + int flow[3] = {0, 0, 0}; + + isvalid = lb_bc_inflow_opts_flow_valid(flow); + assert(isvalid); + } + + { + int flow[3] = {0, 1, 0}; + + isvalid = lb_bc_inflow_opts_flow_valid(flow); + assert(isvalid); + } + + { + int flow[3] = {1, 1, 0}; + + isvalid = lb_bc_inflow_opts_flow_valid(flow); + assert(!isvalid); + } + + { + int flow[3] = {1, 1, 1}; + + isvalid = lb_bc_inflow_opts_flow_valid(flow); + assert(!isvalid); + } + + return isvalid; +} + +/***************************************************************************** + * + * test_lb_bc_inflow_opts_valid + * + *****************************************************************************/ + +__host__ int test_lb_bc_inflow_opts_valid(void) { + + int ierr = 0; + + { + lb_bc_inflow_opts_t options = {.nvel = 9}; + + ierr = lb_bc_inflow_opts_valid(options); + assert(ierr); + } + + { + lb_bc_inflow_opts_t options = {}; /* Not valid */ + + ierr = lb_bc_inflow_opts_valid(options); + assert(ierr == 0); + } + + return ierr; +} + diff --git a/tests/unit/test_lb_bc_inflow_rhou.c b/tests/unit/test_lb_bc_inflow_rhou.c index baf367796..327ce8e68 100644 --- a/tests/unit/test_lb_bc_inflow_rhou.c +++ b/tests/unit/test_lb_bc_inflow_rhou.c @@ -59,7 +59,7 @@ __host__ int test_lb_bc_inflow_rhou_suite(void) { __host__ int test_lb_bc_inflow_rhou_create(pe_t * pe, cs_t * cs) { - lb_openbc_options_t options = lb_openbc_options_default(); + lb_bc_inflow_opts_t options = lb_bc_inflow_opts_default(); lb_bc_inflow_rhou_t * inflow = NULL; assert(pe); @@ -74,9 +74,9 @@ __host__ int test_lb_bc_inflow_rhou_create(pe_t * pe, cs_t * cs) { assert(inflow->super.func); assert(inflow->super.id == LB_BC_INFLOW_RHOU); - /* Check options */ + /* Check options are present */ - assert(inflow->options.inflow); + assert(lb_bc_inflow_opts_valid(inflow->options)); /* Default options given no links */ @@ -114,7 +114,8 @@ __host__ int test_lb_bc_inflow_rhou_update(pe_t * pe, cs_t * cs) { int noffset[3] = {}; double rho0 = 2.0; - lb_openbc_options_t options = {.flow = {1, 0, 0}, + lb_bc_inflow_opts_t options = {.nvel = 15, + .flow = {1, 0, 0}, .u0 = {-1.0,-2.0,-3.0}}; lb_bc_inflow_rhou_t * inflow = NULL; hydro_t * hydro = NULL; @@ -194,7 +195,7 @@ __host__ int test_lb_bc_inflow_rhou_impose(pe_t * pe, cs_t * cs) { double rho0 = 1.0; - lb_openbc_options_t options = {.nvel = NVEL, + lb_bc_inflow_opts_t options = {.nvel = 19, .flow = {1, 0, 0}, .u0 = {0.01, 0.0, 0.0}}; lb_bc_inflow_rhou_t * inflow = NULL; diff --git a/tests/unit/test_lb_bc_outflow_opts.c b/tests/unit/test_lb_bc_outflow_opts.c index ea5cb17ca..5ec9f99ad 100644 --- a/tests/unit/test_lb_bc_outflow_opts.c +++ b/tests/unit/test_lb_bc_outflow_opts.c @@ -51,7 +51,7 @@ __host__ int test_lb_bc_outflow_opts_default(void) { lb_bc_outflow_opts_t defaults = lb_bc_outflow_opts_default(); - assert(defaults.nvel == 0); + assert(defaults.nvel == 19); assert(defaults.flow[X] == 0); assert(defaults.flow[Y] == 0); assert(defaults.flow[Z] == 0); @@ -73,7 +73,7 @@ __host__ int test_lb_bc_outflow_opts_valid(void) { lb_bc_outflow_opts_t options = lb_bc_outflow_opts_default(); ierr = lb_bc_outflow_opts_valid(options); - assert(ierr == 0); + assert(ierr != 0); } { diff --git a/tests/unit/test_lb_bc_outflow_rhou.c b/tests/unit/test_lb_bc_outflow_rhou.c new file mode 100644 index 000000000..e3e97d671 --- /dev/null +++ b/tests/unit/test_lb_bc_outflow_rhou.c @@ -0,0 +1,237 @@ +/***************************************************************************** + * + * test_lb_bc_outflow_rhou.c + * + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#include +#include +#include + +#include "pe.h" +#include "cs_limits.h" +#include "lb_bc_outflow_rhou.h" + +__host__ int test_lb_bc_outflow_rhou_create(pe_t * pe, cs_t * cs); +__host__ int test_lb_bc_outflow_rhou_update(pe_t * pe, cs_t * cs); +__host__ int test_lb_bc_outflow_rhou_impose(pe_t * pe, cs_t * cs); + +/***************************************************************************** + * + * test_lb_bc_outflow_rhou_suite + * + *****************************************************************************/ + +__host__ int test_lb_bc_outflow_rhou_suite(void) { + + pe_t * pe = NULL; + cs_t * cs = NULL; + + pe_create(MPI_COMM_WORLD, PE_QUIET, &pe); + cs_create(pe, &cs); + cs_init(cs); + + test_lb_bc_outflow_rhou_create(pe, cs); + test_lb_bc_outflow_rhou_update(pe, cs); + test_lb_bc_outflow_rhou_impose(pe, cs); + + pe_info(pe, "PASS ./unit/test_lb_bc_outflow_rhou\n"); + + cs_free(cs); + pe_free(pe); + + return 0; +} + +/***************************************************************************** + * + * test_lb_bc_outflow_rhou_create + * + *****************************************************************************/ + +__host__ int test_lb_bc_outflow_rhou_create(pe_t * pe, cs_t * cs) { + + lb_bc_outflow_opts_t options = lb_bc_outflow_opts_default(); + lb_bc_outflow_rhou_t * outflow = NULL; + + assert(pe); + assert(cs); + + lb_bc_outflow_rhou_create(pe, cs, &options, &outflow); + + assert(outflow); + assert(outflow->pe == pe); + assert(outflow->cs == cs); + + assert(outflow->super.func); + assert(outflow->super.id == LB_BC_OUTFLOW_RHOU); + + assert(lb_bc_outflow_opts_valid(outflow->options)); + + assert(outflow->nlink == 0); + assert(outflow->linkp); + assert(outflow->linki); + assert(outflow->linkj); + + return 0; +} + +/***************************************************************************** + * + * test_lb_bc_outflow_rhou_update + * + *****************************************************************************/ + +__host__ int test_lb_bc_outflow_rhou_update(pe_t * pe, cs_t * cs) { + + int nlocal[3] = {}; + int ntotal[3] = {}; + int noffset[3] = {}; + + lb_bc_outflow_opts_t options = {.nvel = 9, + .flow = {0, 1, 0}, + .rho0 = 2.0}; + lb_bc_outflow_rhou_t * outflow = NULL; + hydro_t * hydro = NULL; + + assert(pe); + assert(cs); + + lb_bc_outflow_rhou_create(pe, cs, &options, &outflow); + hydro_create(pe, cs, NULL, 1, &hydro); + + /* The rho0 is fixed and comes from options.rho0, so just run update */ + + lb_bc_outflow_rhou_update(outflow, hydro); + + cs_nlocal(cs, nlocal); + cs_ntotal(cs, ntotal); + cs_nlocal_offset(cs, noffset); + + if (noffset[Y] + nlocal[Y] == ntotal[Y]) { + + int jcbound = nlocal[Y] + 1; + cs_limits_t limits = {1, nlocal[X], jcbound, jcbound, 1, nlocal[Z]}; + + for (int ic = limits.imin; ic <= limits.imax; ic++) { + for (int jc = limits.jmin; jc <= limits.jmax; jc++) { + for (int kc = limits.kmin; kc <= limits.kmax; kc++) { + int index = cs_index(cs, ic, jc, kc); + double rho = 0.0; + + hydro_rho(hydro, index, &rho); + assert(fabs(rho - options.rho0) < DBL_EPSILON); + } + } + } + } + + hydro_free(hydro); + lb_bc_outflow_rhou_free(outflow); + + return 0; +} + +/***************************************************************************** + * + * test_lb_bc_outflow_rhou_impose + * + *****************************************************************************/ + +__host__ int test_lb_bc_outflow_rhou_impose(pe_t * pe, cs_t * cs) { + + int nlocal[3] = {}; + int ntotal[3] = {}; + int noffset[3] = {}; + + lb_bc_outflow_opts_t options = {.nvel = 19, + .flow = {0, 0, 1}, + .rho0 = 3.0}; + lb_bc_outflow_rhou_t * outflow = NULL; + hydro_t * hydro = NULL; + lb_t * lb = NULL; + + double u0[3] = {0.0, 0.0, 0.01}; /* Domain outflow in z-direction */ + + assert(pe); + assert(cs); + + lb_bc_outflow_rhou_create(pe, cs, &options, &outflow); + hydro_create(pe, cs, NULL, 1, &hydro); + lb_create(pe, cs, &lb); + lb_init(lb); + + /* Set some outflow velocities in the domain */ + + cs_ntotal(cs, ntotal); + cs_nlocal(cs, nlocal); + cs_nlocal_offset(cs, noffset); + + if (noffset[Z] + nlocal[Z] == ntotal[Z]) { + + cs_limits_t limits = {1, nlocal[X], 1, nlocal[Y], nlocal[Z], nlocal[Z]}; + + for (int ic = limits.imin; ic <= limits.imax; ic++) { + for (int jc = limits.jmin; jc <= limits.jmax; jc++) { + for (int kc = limits.kmin; kc <= limits.kmax; kc++) { + int index = cs_index(cs, ic, jc, kc); + hydro_u_set(hydro, index, u0); + } + } + } + } + + /* Run update */ + /* Check the resulting distributions at the outflow */ + + lb_bc_outflow_rhou_update(outflow, hydro); + lb_bc_outflow_rhou_impose(outflow, hydro, lb); + + if (noffset[Z] + nlocal[Z] == ntotal[Z]) { + + int kcbound = nlocal[Z] + 1; + cs_limits_t limits = {1, nlocal[X], 1, nlocal[Y], kcbound, kcbound}; + + for (int ic = limits.imin; ic <= limits.imax; ic++) { + for (int jc = limits.jmin; jc <= limits.jmax; jc++) { + for (int kc = limits.kmin; kc <= limits.kmax; kc++) { + + int index = cs_index(cs, ic, jc, kc); + + for (int p = 1; p < lb->model.nvel; p++) { + + double f = 0.0; + + if (lb->model.cv[p][Z] != -1) continue; + if (noffset[X] + ic + lb->model.cv[p][X] < 1) continue; + if (noffset[Y] + jc + lb->model.cv[p][Y] < 1) continue; + if (noffset[X] + ic + lb->model.cv[p][X] > ntotal[X]) continue; + if (noffset[Y] + jc + lb->model.cv[p][Y] > ntotal[Y]) continue; + + lb_f(lb, index, p, LB_RHO, &f); + + { + double uz = u0[Z]; + double rho0 = outflow->options.rho0; + double fp = lb->model.wv[p]*rho0*(1.0 - 3.0*uz + 3.0*uz*uz); + assert(fabs(f - fp) < DBL_EPSILON); + } + } + } + } + } + } + + lb_free(lb); + hydro_free(hydro); + lb_bc_outflow_rhou_free(outflow); + + return 0; +} diff --git a/tests/unit/test_lb_openbc_options.c b/tests/unit/test_lb_openbc_options.c deleted file mode 100644 index d73989c35..000000000 --- a/tests/unit/test_lb_openbc_options.c +++ /dev/null @@ -1,211 +0,0 @@ -/***************************************************************************** - * - * test_lb_openbc_options.c - * - * - * Edinburgh Solft Matter and Statistical Physics Group and - * Edinburgh Parallel Computing Centre - * - * (c) 2021 The University of Edinburgh - * - * Contributing authors: - * Kevin Stratford (kevin@epcc.ed.ac.uk) - * - *****************************************************************************/ - -#include -#include - -#include "lb_openbc_options.h" - -__host__ int test_lb_openbc_options_inflow_default(void); -__host__ int test_lb_openbc_options_outflow_default(void); -__host__ int test_lb_openbc_options_inflow_valid(void); -__host__ int test_lb_openbc_options_outflow_valid(void); -__host__ int test_lb_openbc_options_flow_valid(void); - -/***************************************************************************** - * - * test_lb_openbc_options_suite - * - *****************************************************************************/ - -__host__ int test_lb_openbc_options_suite(void) { - - pe_t * pe = NULL; - - pe_create(MPI_COMM_WORLD, PE_QUIET, &pe); - - test_lb_openbc_options_inflow_default(); - test_lb_openbc_options_outflow_default(); - test_lb_openbc_options_inflow_valid(); - test_lb_openbc_options_outflow_valid(); - test_lb_openbc_options_flow_valid(); - - pe_info(pe, "PASS ./unit/test_lb_openbc_options\n"); - - pe_free(pe); - - return 0; -} - -/***************************************************************************** - * - * test_lb_openbc_options_inflow_default - * - *****************************************************************************/ - -__host__ int test_lb_openbc_options_inflow_default(void) { - - int isvalid = 0; - - { - lb_inflow_enum_t bctype = lb_openbc_options_inflow_default(); - assert(bctype == LB_INFLOW_NONE); - isvalid = lb_openbc_options_inflow_valid(bctype); - } - - return isvalid; -} - -/***************************************************************************** - * - * test_lb_openbc_options_outflow_default - * - *****************************************************************************/ - -__host__ int test_lb_openbc_options_outflow_default(void) { - - int isvalid = 0; - - { - lb_outflow_enum_t bctype = lb_openbc_options_outflow_default(); - - assert(bctype == LB_OUTFLOW_NONE); - isvalid = lb_openbc_options_outflow_valid(bctype); - } - - return isvalid; -} - -/***************************************************************************** - * - * test_lb_openbc_options_default - * - *****************************************************************************/ - -__host__ int test_lb_openbc_options_default(void) { - - int isvalid = 0; - - { - lb_openbc_options_t options = lb_openbc_options_default(); - - assert(options.bctype == 0); - assert(options.inflow == LB_INFLOW_NONE); - assert(options.outflow == LB_OUTFLOW_NONE); - - isvalid = lb_openbc_options_valid(&options); - } - - return isvalid; -} - - - -/***************************************************************************** - * - * test_lb_openbc_options_inflow_valid - * - *****************************************************************************/ - -__host__ int test_lb_openbc_options_inflow_valid(void) { - - int isvalid = 0; - - { - lb_inflow_enum_t bctype = LB_INFLOW_NONE; - - isvalid = lb_openbc_options_inflow_valid(bctype); - assert(isvalid); - } - - { - lb_inflow_enum_t bctype = LB_INFLOW_MAX; - - isvalid = lb_openbc_options_inflow_valid(bctype); - assert(!isvalid); - } - - return isvalid; -} - - -/***************************************************************************** - * - * test_lb_openbc_options_outflow_valid - * - *****************************************************************************/ - -__host__ int test_lb_openbc_options_outflow_valid(void) { - - int isvalid = 0; - - { - lb_outflow_enum_t bctype = LB_OUTFLOW_NONE; - - isvalid = lb_openbc_options_outflow_valid(bctype); - assert(isvalid); - } - - { - lb_outflow_enum_t bctype = LB_OUTFLOW_MAX; - - isvalid = lb_openbc_options_outflow_valid(bctype); - assert(!isvalid); - } - - return isvalid; -} - -/***************************************************************************** - * - * test_lb_openbc_options_flow_valid - * - *****************************************************************************/ - -__host__ int test_lb_openbc_options_flow_valid(void) { - - int isvalid = 0; - - { - int flow[3] = {0, 0, 0}; - - isvalid = lb_openbc_options_flow_valid(flow); - assert(isvalid); - } - - { - int flow[3] = {0, 1, 0}; - - isvalid = lb_openbc_options_flow_valid(flow); - assert(isvalid); - } - - { - int flow[3] = {1, 1, 0}; - - isvalid = lb_openbc_options_flow_valid(flow); - assert(!isvalid); - } - - { - int flow[3] = {1, 1, 1}; - - isvalid = lb_openbc_options_flow_valid(flow); - assert(!isvalid); - } - - return isvalid; -} - diff --git a/tests/unit/tests.c b/tests/unit/tests.c index 3173b124c..e4f9943e4 100644 --- a/tests/unit/tests.c +++ b/tests/unit/tests.c @@ -75,9 +75,10 @@ __host__ int tests_create() { test_lb_d3q15_suite(); test_lb_d3q19_suite(); test_lb_model_suite(); - test_lb_openbc_options_suite(); + test_lb_bc_inflow_opts_suite(); test_lb_bc_inflow_rhou_suite(); test_lb_bc_outflow_opts_suite(); + test_lb_bc_outflow_rhou_suite(); test_le_suite(); test_lubrication_suite(); test_map_suite(); diff --git a/tests/unit/tests.h b/tests/unit/tests.h index fd7465d8a..94f879250 100644 --- a/tests/unit/tests.h +++ b/tests/unit/tests.h @@ -55,9 +55,10 @@ int test_lb_d2q9_suite(void); int test_lb_d3q15_suite(void); int test_lb_d3q19_suite(void); int test_lb_model_suite(void); -int test_lb_openbc_options_suite(void); +int test_lb_bc_inflow_opts_suite(void); int test_lb_bc_inflow_rhou_suite(void); int test_lb_bc_outflow_opts_suite(void); +int test_lb_bc_outflow_rhou_suite(void); int test_le_suite(void); int test_kernel_suite(void); int test_lubrication_suite(void); From 3e3305c1f704e1420ae2d334833d0c968c52c4db Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Mon, 15 Nov 2021 15:05:41 +0000 Subject: [PATCH 047/117] Add header --- src/cs_limits.h | 23 +++++++++++++++++++++++ tests/unit/test_lb_bc_inflow_rhou.c | 22 ++++++---------------- 2 files changed, 29 insertions(+), 16 deletions(-) create mode 100644 src/cs_limits.h diff --git a/src/cs_limits.h b/src/cs_limits.h new file mode 100644 index 000000000..9a0ab98e5 --- /dev/null +++ b/src/cs_limits.h @@ -0,0 +1,23 @@ +/***************************************************************************** + * + * cs_limits.h + * + * A container (only) for a cubiodal region. + * + *****************************************************************************/ + +#ifndef LUDWIG_CS_LIMITS_H +#define LUDWIG_CS_LIMITS_H + +typedef struct cs_limits_s cs_limits_t; + +struct cs_limits_s { + int imin; + int imax; + int jmin; + int jmax; + int kmin; + int kmax; +}; + +#endif diff --git a/tests/unit/test_lb_bc_inflow_rhou.c b/tests/unit/test_lb_bc_inflow_rhou.c index 327ce8e68..b5feb29ec 100644 --- a/tests/unit/test_lb_bc_inflow_rhou.c +++ b/tests/unit/test_lb_bc_inflow_rhou.c @@ -16,6 +16,7 @@ #include #include +#include "cs_limits.h" #include "lb_bc_inflow_rhou.h" /* Tests */ @@ -90,18 +91,6 @@ __host__ int test_lb_bc_inflow_rhou_create(pe_t * pe, cs_t * cs) { return 0; } -/***************************************************************************** - * - * test_lb_bc_inflow_rhou_update - * - *****************************************************************************/ - -typedef struct limits_s { - int imin, imax; - int jmin, jmax; - int kmin, kmax; -} limits_t; - /***************************************************************************** * * test_lb_bc_inflow_rhou_update @@ -133,7 +122,7 @@ __host__ int test_lb_bc_inflow_rhou_update(pe_t * pe, cs_t * cs) { if (noffset[X] == 0) { - limits_t limits = {1, 1, 1, nlocal[Y], 1, nlocal[Z]}; + cs_limits_t limits = {1, 1, 1, nlocal[Y], 1, nlocal[Z]}; for (int ic = limits.imin; ic <= limits.imax; ic++) { for (int jc = limits.jmin; jc <= limits.jmax; jc++) { @@ -152,7 +141,7 @@ __host__ int test_lb_bc_inflow_rhou_update(pe_t * pe, cs_t * cs) { if (noffset[X] == 0) { - limits_t limits = {0, 0, 1, nlocal[Y], 1, nlocal[Z]}; + cs_limits_t limits = {0, 0, 1, nlocal[Y], 1, nlocal[Z]}; for (int ic = limits.imin; ic <= limits.imax; ic++) { for (int jc = limits.jmin; jc <= limits.jmax; jc++) { @@ -220,7 +209,7 @@ __host__ int test_lb_bc_inflow_rhou_impose(pe_t * pe, cs_t * cs) { if (noffset[X] == 0) { - limits_t limits = {1, 1, 1, nlocal[Y], 1, nlocal[Z]}; + cs_limits_t limits = {1, 1, 1, nlocal[Y], 1, nlocal[Z]}; for (int ic = limits.imin; ic <= limits.imax; ic++) { for (int jc = limits.jmin; jc <= limits.jmax; jc++) { @@ -239,7 +228,8 @@ __host__ int test_lb_bc_inflow_rhou_impose(pe_t * pe, cs_t * cs) { /* So, for each site in the boundary region, check ingoing distributions. */ if (noffset[X] == 0) { - limits_t limits = {0, 0, 1, nlocal[Y], 1, nlocal[Z]}; + + cs_limits_t limits = {0, 0, 1, nlocal[Y], 1, nlocal[Z]}; for (int ic = limits.imin; ic <= limits.imax; ic++) { for (int jc = limits.jmin; jc <= limits.jmax; jc++) { From 64ffd8407f2e520feba531c0c6ea910f0d7aded8 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Tue, 16 Nov 2021 15:12:43 +0000 Subject: [PATCH 048/117] Bug fix in ascii rho output --- src/model.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/model.c b/src/model.c index 2f3c73497..94ff29de6 100644 --- a/src/model.c +++ b/src/model.c @@ -752,6 +752,7 @@ __host__ int lb_io_rho_set(lb_t * lb, io_info_t * io_rho, int form_in, io_info_write_set(lb->io_rho, IO_FORMAT_BINARY, lb_rho_write); io_info_set_bytesize(lb->io_rho, IO_FORMAT_BINARY, sizeof(double)); io_info_write_set(lb->io_rho, IO_FORMAT_ASCII, lb_rho_write_ascii); + io_info_set_bytesize(lb->io_rho, IO_FORMAT_ASCII, 23*sizeof(char)); io_info_format_set(lb->io_rho, form_in, form_out); return 0; From 8bf2547174963122c58df2dddeaf30fcf60ca60a Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Tue, 16 Nov 2021 15:13:25 +0000 Subject: [PATCH 049/117] Store hydro->rho at collision --- src/collision.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/collision.c b/src/collision.c index 77dd2a427..ca7cf11d7 100644 --- a/src/collision.c +++ b/src/collision.c @@ -568,6 +568,10 @@ void lb_collision_mrt1_site(lb_t * lb, hydro_t * hydro, map_t * map, lb->f[LB_ADDR(_lbp.nsite, _lbp.ndist, NVEL, index0+iv, LB_RHO, p)] = fchunk[p*NSIMDVL+iv]; } } + /* density */ + for_simd_v(iv, NSIMDVL) { + hydro->rho[addr_rank0(hydro->nsite, index0+iv)] = rho[iv]; + } /* velocity */ for (ia = 0; ia < 3; ia++) { for_simd_v(iv, NSIMDVL) { From 5ae07bc8ba347599a66bf5acd3222a186244a0fa Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Tue, 16 Nov 2021 17:14:29 +0000 Subject: [PATCH 050/117] Add working open boundary and test --- src/hydro.c | 49 ++++++ src/hydro.h | 1 + src/lb_bc_inflow_rhou.c | 21 +-- src/lb_bc_inflow_rhou.h | 6 +- src/lb_bc_open_rt.c | 156 ++++++++++++++++++ src/lb_bc_open_rt.h | 28 ++++ src/ludwig.c | 38 ++++- .../d3q19-short/serial-open-ru1.inp | 69 ++++++++ .../d3q19-short/serial-open-ru1.log | 116 +++++++++++++ .../d3q19-short/serial-open-ru2.inp | 70 ++++++++ .../d3q19-short/serial-open-ru2.log | 116 +++++++++++++ 11 files changed, 654 insertions(+), 16 deletions(-) create mode 100644 src/lb_bc_open_rt.c create mode 100644 src/lb_bc_open_rt.h create mode 100644 tests/regression/d3q19-short/serial-open-ru1.inp create mode 100644 tests/regression/d3q19-short/serial-open-ru1.log create mode 100644 tests/regression/d3q19-short/serial-open-ru2.inp create mode 100644 tests/regression/d3q19-short/serial-open-ru2.log diff --git a/src/hydro.c b/src/hydro.c index 5a99bbe38..5e3c95754 100644 --- a/src/hydro.c +++ b/src/hydro.c @@ -41,6 +41,7 @@ __global__ void hydro_accumulate_kernel_v(kernel_ctxt_t * ktx, hydro_t * hydro, double fnet[3]); __global__ void hydro_correct_kernel_v(kernel_ctxt_t * ktx, hydro_t * hydro, double fnet[3]); +__global__ void hydro_rho0_kernel(int nsite, double rho0, double * rho); /***************************************************************************** @@ -526,6 +527,54 @@ __host__ int hydro_f_zero(hydro_t * obj, const double fzero[NHDIM]) { return 0; } +/***************************************************************************** + * + * hydro_rho0 + * + * Set rho uniformly everywhere; rho0 shouldn't be zero! + * + *****************************************************************************/ + +__host__ int hydro_rho0(hydro_t * obj, double rho0) { + + dim3 nblk, ntpb; + double * rho = NULL; + + assert(obj); + assert(obj->target); + + tdpAssert(tdpMemcpy(&rho, &obj->target->rho, sizeof(double *), + tdpMemcpyDeviceToHost)); + + kernel_launch_param(obj->nsite, &nblk, &ntpb); + tdpLaunchKernel(hydro_rho0_kernel, nblk, ntpb, 0, 0, obj->nsite, rho0, rho); + + tdpAssert(tdpPeekAtLastError()); + tdpAssert(tdpDeviceSynchronize()); + + return 0; +} + +/****************************************************************************** + * + * hydro_rho0_kernel + * + *****************************************************************************/ + +__global__ void hydro_rho0_kernel(int nsite, double rho0, double * rho) { + + int kindex = 0; + + assert(rho); + + for_simt_parallel(kindex, nsite, 1) { + rho[addr_rank0(nsite, kindex)] = rho0; + } + + return; +} + + /***************************************************************************** * * hydro_field_set diff --git a/src/hydro.h b/src/hydro.h index ebe1fb1f9..3f5500410 100644 --- a/src/hydro.h +++ b/src/hydro.h @@ -63,6 +63,7 @@ __host__ int hydro_lees_edwards(hydro_t * obj); __host__ int hydro_correct_momentum(hydro_t * obj); __host__ int hydro_f_zero(hydro_t * obj, const double fzero[3]); __host__ int hydro_u_zero(hydro_t * obj, const double uzero[3]); +__host__ int hydro_rho0(hydro_t * hydro, double rho0); __host__ __device__ int hydro_f_local_set(hydro_t * obj, int index, const double force[3]); diff --git a/src/lb_bc_inflow_rhou.c b/src/lb_bc_inflow_rhou.c index 6c0692b7d..53c97adcc 100644 --- a/src/lb_bc_inflow_rhou.c +++ b/src/lb_bc_inflow_rhou.c @@ -131,9 +131,6 @@ __host__ int lb_bc_inflow_rhou_init_internal(lb_bc_inflow_rhou_t * inflow) { * This assumes that the other two directions are walls, and so no * duplicates of incoming solid-fluid (bbl) links are wanted. * - * CHECK CHECK CHECK links are fluid (domain) to fluid (halo). The - * incoming distributions are then actually the complements -cv[p]. - * *****************************************************************************/ __host__ int lb_bc_inflow_init_link(lb_bc_inflow_rhou_t * inflow, @@ -185,9 +182,9 @@ __host__ int lb_bc_inflow_init_link(lb_bc_inflow_rhou_t * inflow, if (noffset[id2] + ijk[id2] > ntotal[id2]) continue; if (init == LINK_ASSIGN) { - inflow->linkp[nlink] = p; - inflow->linki[nlink] = cs_index(cs, ic, jc, kc); - inflow->linkj[nlink] = cs_index(cs, ic1, jc1, kc1); + inflow->linkp[nlink] = model.nvel - p; /* reverse */ + inflow->linki[nlink] = cs_index(cs, ic1, jc1, kc1); + inflow->linkj[nlink] = cs_index(cs, ic, jc, kc); } nlink += 1; } @@ -297,8 +294,8 @@ __host__ int lb_bc_inflow_rhou_impose(lb_bc_inflow_rhou_t * inflow, for (int n = 0; n < inflow->nlink; n++) { - int index = inflow->linkj[n]; - int8_t q = lb->model.nvel - inflow->linkp[n]; + int index = inflow->linki[n]; + int8_t p = inflow->linkp[n]; double rho = 0.0; double u[3] = {}; @@ -314,18 +311,18 @@ __host__ int lb_bc_inflow_rhou_impose(lb_bc_inflow_rhou_t * inflow, double fp = 0.0; for (int ia = 0; ia < 3; ia++) { - udotc += u[ia]*lb->model.cv[q][ia]; + udotc += u[ia]*lb->model.cv[p][ia]; for (int ib = 0; ib < 3; ib++) { double d_ab = (ia == ib); - double s_ab = lb->model.cv[q][ia]*lb->model.cv[q][ib] - cs2*d_ab; + double s_ab = lb->model.cv[p][ia]*lb->model.cv[p][ib] - cs2*d_ab; sdotq += s_ab*u[ia]*u[ib]; } } /* Here's the equilibrium */ - fp = rho*lb->model.wv[q]*(1.0 + rcs2*udotc + 0.5*rcs2*rcs2*sdotq); - lb_f_set(lb, index, q, LB_RHO, fp); + fp = rho*lb->model.wv[p]*(1.0 + rcs2*udotc + 0.5*rcs2*rcs2*sdotq); + lb_f_set(lb, index, p, LB_RHO, fp); } } diff --git a/src/lb_bc_inflow_rhou.h b/src/lb_bc_inflow_rhou.h index 0417c84e7..b3501432d 100644 --- a/src/lb_bc_inflow_rhou.h +++ b/src/lb_bc_inflow_rhou.h @@ -31,9 +31,9 @@ struct lb_bc_inflow_rhou_s { /* Boundary links */ int nlink; /* Number of links (local) */ - int8_t * linkp; /* Velocity index in LB basis (i->j) */ - int * linki; /* Fluid site in system */ - int * linkj; /* Fluid site in inflow halo boundary */ + int * linki; /* Fluid site in boundary (halo) region */ + int * linkj; /* Fluid site in domain proper */ + int8_t * linkp; /* Velocity index in lb basis (i->j) */ }; __host__ int lb_bc_inflow_rhou_create(pe_t * pe, cs_t * cs, diff --git a/src/lb_bc_open_rt.c b/src/lb_bc_open_rt.c new file mode 100644 index 000000000..818bc2283 --- /dev/null +++ b/src/lb_bc_open_rt.c @@ -0,0 +1,156 @@ +/***************************************************************************** + * + * lb_bc_open_rt.c + * + * LB open boundary condition initialisation. + * + * Currently acceptable positions: + * We must have wall in two coordinate directions (3d) + * We must have no periodic conditions at all "periodicity 0_0_0" + * The inflow/outflow direction must be in the non-wall direction. + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * + * (c) 2021 The University of Edinburgh + * + * Contibuting authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#include +#include +#include + +#include "lb_bc_open_rt.h" + +/* Available implementations */ + +#include "lb_bc_inflow_rhou.h" +#include "lb_bc_outflow_rhou.h" + +/***************************************************************************** + * + * lb_bc_open_rt + * + * As we are not generally going to have an inflow without an outflow + * (and vice-versa) these are together... + * + *****************************************************************************/ + +__host__ int lb_bc_open_rt(pe_t * pe, rt_t * rt, cs_t * cs, lb_t * lb, + lb_bc_open_t ** inflow, + lb_bc_open_t ** outflow) { + + int have_bc = 0; /* inflow/outflow required */ + int flow[3] = {}; /* flow direction */ + + assert(pe); + assert(rt); + assert(cs); + assert(lb); + + have_bc = rt_switch(rt, "lb_bc_open"); + + if (have_bc) { + int wall[3] = {}; + int periodic[3] = {}; + + /* Take flow direction from non-wall direction. */ + /* There must be D-1 walls in D dimensions */ + + rt_int_parameter_vector(rt, "boundary_walls", wall); + flow[X] = 1 - wall[X]; + flow[Y] = 1 - wall[Y]; + flow[Z] = 1 - wall[Z]; + + if (lb_bc_inflow_opts_flow_valid(flow) == 0) { + pe_fatal(pe, "Inflow/outflow requires exactly one-non wall direction\n"); + } + + /* Test periodicity. Must be (0,0,0). */ + + cs_periodic(cs, periodic); + if (periodic[X] || periodic[Y] || periodic[Z]) { + pe_fatal(pe, "Inflow/outflow requires fully non-periodic system\n"); + } + + /* Any other checks are deferred ... */ + + rt_key_required(rt, "lb_bc_inflow_type", RT_INFO); + rt_key_required(rt, "lb_bc_outflow_type", RT_INFO); + } + + /* Inflow */ + + if (have_bc) { + + char intype[BUFSIZ] = {}; + double u0[3] = {}; + + rt_string_parameter(rt, "lb_bc_inflow_type", intype, BUFSIZ/2); + rt_double_parameter_vector(rt, "lb_bc_inflow_rhou_u0", u0); + + if (strncmp(intype, "rhou", BUFSIZ) == 0) { + /* Give me a rhou inflow */ + lb_bc_inflow_rhou_t * rhou = NULL; + lb_bc_inflow_opts_t options = {.nvel = lb->model.nvel, + .flow = {flow[X], flow[Y], flow[Z]}, + .u0 = {u0[X],u0[Y],u0[Z]}}; + + /* Check options are valid */ + if (lb_bc_inflow_opts_valid(options) == 0) { + /* Print them out */ + pe_fatal(pe, "Please check inflow options and try again\n."); + } + + lb_bc_inflow_rhou_create(pe, cs, &options, &rhou); + *inflow = (lb_bc_open_t *) rhou; + printf("INFLOW %d %d %d\n", + rhou->options.flow[X], + rhou->options.flow[Y], + rhou->options.flow[Z]); + printf("INFLOW %14.7e %14.7e %14.7e\n", + rhou->options.u0[X], + rhou->options.u0[Y], + rhou->options.u0[Z]); + } + else { + /* Not recognised */ + pe_fatal(pe, "lb_bc_inflow_type not recognised\n"); + } + } + + /* Outflow */ + if (have_bc) { + + char outtype[BUFSIZ] = {}; + double rho0 = 1.0; + + rt_string_parameter(rt, "lb_bc_outflow_type", outtype, BUFSIZ/2); + rt_double_parameter(rt, "rho0", &rho0); + rt_double_parameter(rt, "lb_bc_outflow_rhou_rho0", &rho0); + + if (strncmp(outtype, "rhou", BUFSIZ) == 0) { + lb_bc_outflow_rhou_t * rhou = NULL; + lb_bc_outflow_opts_t options = {.nvel = lb->model.nvel, + .flow = {flow[X], flow[Y], flow[Z]}, + .rho0 = rho0}; + /* Check options valid */ + if (lb_bc_outflow_opts_valid(options) == 0) { + /* Print out? */ + pe_fatal(pe, "Please check outflow options and try again\n"); + } + + lb_bc_outflow_rhou_create(pe, cs, &options, &rhou); + *outflow = (lb_bc_open_t *) rhou; + } + else { + pe_fatal(pe, "lb_bc_outflow_type not recognised\n"); + } + } + + return 0; +} diff --git a/src/lb_bc_open_rt.h b/src/lb_bc_open_rt.h new file mode 100644 index 000000000..229e2e8df --- /dev/null +++ b/src/lb_bc_open_rt.h @@ -0,0 +1,28 @@ +/***************************************************************************** + * + * lb_bc_open_rt.h + * + * Open boundary condition run-time initialisation. + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#ifndef LUDWIG_LB_BC_OPEN_RT_H +#define LUDWIG_LB_BC_OPEN_RT_H + +#include "pe.h" +#include "coords.h" +#include "lb_bc_open.h" +#include "runtime.h" + +__host__ int lb_bc_open_rt(pe_t * pe, rt_t * rt, cs_t * cs, lb_t * lb, + lb_bc_open_t ** inflow, + lb_bc_open_t ** outflow); +#endif diff --git a/src/ludwig.c b/src/ludwig.c index 5fffea251..1353ead85 100644 --- a/src/ludwig.c +++ b/src/ludwig.c @@ -90,6 +90,9 @@ #include "visc.h" #include "visc_arrhenius.h" +/* Open boundary conditions */ +#include "lb_bc_open_rt.h" + /* Electrokinetics */ #include "psi.h" #include "psi_rt.h" @@ -161,6 +164,9 @@ struct ludwig_s { interact_t * interact; /* Colloid-colloid interaction handler */ bbl_t * bbl; /* Bounce-back on links boundary condition */ + lb_bc_open_t * inflow; /* Inflow open boundary conidition (fluid) */ + lb_bc_open_t * outflow; /* Outflow boundary condition (fluid) */ + stats_sigma_t * stat_sigma; /* Interfacial tension calibration */ stats_ahydro_t * stat_ah; /* Hydrodynamic radius calibration */ stats_rheo_t * stat_rheo; /* Rheology diagnostics */ @@ -238,6 +244,8 @@ static int ludwig_rt(ludwig_t * ludwig) { hydro_rt(pe, rt, cs, ludwig->le, &ludwig->hydro); visc_model_init_rt(pe, rt, ludwig); + lb_bc_open_rt(pe, rt, cs, ludwig->lb, &ludwig->inflow, &ludwig->outflow); + /* PHI I/O */ rt_int_parameter_vector(rt, "default_io_grid", io_grid_default); @@ -307,8 +315,11 @@ static int ludwig_rt(ludwig_t * ludwig) { ntstep = physics_control_timestep(ludwig->phys); if (ntstep == 0) { + double rho0 = 1.0; n = 0; lb_rt_initial_conditions(pe, rt, ludwig->lb, ludwig->phys); + physics_rho0(ludwig->phys, &rho0); + if (ludwig->hydro) hydro_rho0(ludwig->hydro, rho0); rt_int_parameter(rt, "LE_init_profile", &n); if (n != 0) lb_le_init_shear_profile(ludwig->lb, ludwig->le); @@ -576,7 +587,16 @@ void ludwig_run(const char * inputfile) { } TIMER_stop(TIMER_PHI_GRADIENTS); if (ludwig->fe_lc) fe_lc_active_stress(ludwig->fe_lc); - + + /* Update any open boundary flows (before any advection) */ + + if (ludwig->inflow) { + ludwig->inflow->func->update(ludwig->inflow, ludwig->hydro); + } + if (ludwig->outflow) { + ludwig->outflow->func->update(ludwig->outflow, ludwig->hydro); + } + /* Electrokinetics (including electro/symmetric requiring above * gradients for phi) */ @@ -788,6 +808,19 @@ void ludwig_run(const char * inputfile) { TIMER_stop(TIMER_HALO_LATTICE); + /* Open boundaries */ + + if (ludwig->inflow) { + lb_bc_open_t * inflow = ludwig->inflow; + inflow->func->update(inflow, ludwig->hydro); + inflow->func->impose(inflow, ludwig->hydro, ludwig->lb); + } + if (ludwig->outflow) { + lb_bc_open_t * outflow = ludwig->outflow; + outflow->func->update(outflow, ludwig->hydro); + outflow->func->impose(outflow, ludwig->hydro, ludwig->lb); + } + /* Colloid bounce-back applied between collision and * propagation steps. */ @@ -1052,6 +1085,9 @@ void ludwig_run(const char * inputfile) { bbl_free(ludwig->bbl); colloids_info_free(ludwig->collinfo); + if (ludwig->inflow) ludwig->inflow->func->free(ludwig->inflow); + if (ludwig->outflow) ludwig->outflow->func->free(ludwig->outflow); + if (ludwig->interact) interact_free(ludwig->interact); if (ludwig->cio) colloid_io_free(ludwig->cio); diff --git a/tests/regression/d3q19-short/serial-open-ru1.inp b/tests/regression/d3q19-short/serial-open-ru1.inp new file mode 100644 index 000000000..0f03d01b7 --- /dev/null +++ b/tests/regression/d3q19-short/serial-open-ru1.inp @@ -0,0 +1,69 @@ +############################################################################## +# +# Open boundary conditions rhou +# Smoke test +# +# 3-case in X. System is at rest and should not gain or lose mass. +# +############################################################################## + +N_cycles 1 + +############################################################################## +# +# System and MPI +# +############################################################################## + +size 24_12_12 +periodicity 0_0_0 + +############################################################################## +# +# Fluid parameters +# +############################################################################## + +viscosity 0.1 + +############################################################################## +# +# Free energy parameters +# +############################################################################### + +free_energy none + +############################################################################### +# +# Colloid parameters +# +############################################################################### + +colloid_init none + +############################################################################### +# +# Walls / boundaries +# +############################################################################### + +boundary_walls 0_1_1 +boundary_speed_bottom 0.0 +boundary_speed_top 0.0 + +lb_bc_open yes +lb_bc_inflow_type rhou +lb_bc_inflow_rhou_u0 0.0_0.0_0.0 + +lb_bc_outflow_type rhou +lb_bc_outflow_rhou_rho0 1.0 + +############################################################################### +# +# Output frequency and type +# +############################################################################### + +freq_statistics 1 +config_at_end no diff --git a/tests/regression/d3q19-short/serial-open-ru1.log b/tests/regression/d3q19-short/serial-open-ru1.log new file mode 100644 index 000000000..0c15b2843 --- /dev/null +++ b/tests/regression/d3q19-short/serial-open-ru1.log @@ -0,0 +1,116 @@ +Welcome to Ludwig v0.14.0 (Serial version running on 1 process) +Start time: Tue Nov 16 17:02:01 2021 + +Compiler: + name: Gnu 11.2.0 + version-string: 11.2.0 + +Note assertions via standard C assert() are on. + +Target thread model: None. + +Read 16 user parameters from serial-open-ru1.inp + +No free energy selected + +System details +-------------- +System size: 24 12 12 +Decomposition: 1 1 1 +Local domain: 24 12 12 +Periodic: 0 0 0 +Halo nhalo: 1 +Reorder: true +Initialised: 1 + +System properties +---------------- +Mean fluid density: 1.00000e+00 +Shear viscosity 1.00000e-01 +Bulk viscosity 1.00000e-01 +Temperature 0.00000e+00 +External body force density 0.00000e+00 0.00000e+00 0.00000e+00 +External E-field amplitude 0.00000e+00 0.00000e+00 0.00000e+00 +External E-field frequency 0.00000e+00 +External magnetic field 0.00000e+00 0.00000e+00 0.00000e+00 + +Lattice Boltzmann distributions +------------------------------- +Model: d3q19 +SIMD vector len: 1 +Number of sets: 1 +Halo type: full +Input format: binary +Output format: binary +I/O grid: 1 1 1 + +Lattice Boltzmann collision +--------------------------- +Relaxation time scheme: M10 +Hydrodynamic modes: on +Ghost modes: on +Isothermal fluctuations: off +Shear relaxation time: 8.00000e-01 +Bulk relaxation time: 8.00000e-01 +Ghost relaxation time: 1.00000e+00 +[Default] Random number seed: 7361237 + +Hydrodynamics +------------- +Hydrodynamics: on +INFLOW 1 0 0 +INFLOW 0.0000000e+00 0.0000000e+00 0.0000000e+00 + +Boundary walls +-------------- +Boundary walls: - Y Z +Boundary speed u_x (bottom): 0.0000000e+00 +Boundary speed u_x (top): 0.0000000e+00 +Boundary normal lubrication rc: 0.0000000e+00 +Wall boundary links allocated: 5664 +Memory (total, bytes): 90624 +Boundary shear initialise: 0 +Initial conditions. + +Scalars - total mean variance min max +[rho] 3456.00 1.00000000000 2.2204460e-16 1.00000000000 1.00000000000 + +Momentum - x y z +[total ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 +[fluid ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 +[walls ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 + +Starting time step loop. + +Scalars - total mean variance min max +[rho] 3456.00 1.00000000000 2.2204460e-16 1.00000000000 1.00000000000 + +Momentum - x y z +[total ] 5.6621374e-15 0.0000000e+00 0.0000000e+00 +[fluid ] 5.6621374e-15 0.0000000e+00 0.0000000e+00 +[walls ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 + +Velocity - x y z +[minimum ] 1.3877788e-17 0.0000000e+00 0.0000000e+00 +[maximum ] 1.3877788e-17 1.1754944e-38 1.1754944e-38 + +Completed cycle 1 + +Timer resolution: 1e-06 second + +Timer statistics + Section: tmin tmax total + Total: 0.014 0.014 0.014 0.013520 (1 call) + Time step loop: 0.006 0.006 0.006 0.006045 (1 call) + Propagation: 0.001 0.001 0.001 0.001431 (1 call) + Propagtn (krnl) : 0.001 0.001 0.001 0.001422 (1 call) + Collision: 0.003 0.003 0.003 0.002758 (1 call) + Collision (krnl) : 0.003 0.003 0.003 0.002740 (1 call) + Lattice halos: 0.001 0.001 0.001 0.000799 (1 call) + phi gradients: 0.000 0.000 0.000 0.000001 (1 call) + BBL: 0.001 0.001 0.001 0.000846 (1 call) + Force calculation: 0.000 0.000 0.000 0.000003 (1 call) + phi update: 0.000 0.000 0.000 0.000001 (1 call) + Free1: 0.002 0.002 0.002 0.002090 (1 call) +End time: Tue Nov 16 17:02:01 2021 +Ludwig finished normally. diff --git a/tests/regression/d3q19-short/serial-open-ru2.inp b/tests/regression/d3q19-short/serial-open-ru2.inp new file mode 100644 index 000000000..5209be6c8 --- /dev/null +++ b/tests/regression/d3q19-short/serial-open-ru2.inp @@ -0,0 +1,70 @@ +############################################################################## +# +# Open boundary conditions rhou +# Smoke test +# +# 3-case in Z. As for serial-open-ru1 but with a uniform inflow +# velocity. +# +############################################################################## + +N_cycles 10 + +############################################################################## +# +# System and MPI +# +############################################################################## + +size 12_12_24 +periodicity 0_0_0 + +############################################################################## +# +# Fluid parameters +# +############################################################################## + +viscosity 0.1 + +############################################################################## +# +# Free energy parameters +# +############################################################################### + +free_energy none + +############################################################################### +# +# Colloid parameters +# +############################################################################### + +colloid_init none + +############################################################################### +# +# Walls / boundaries +# +############################################################################### + +boundary_walls 1_1_0 +boundary_speed_bottom 0.0 +boundary_speed_top 0.0 + +lb_bc_open yes +lb_bc_inflow_type rhou +lb_bc_inflow_rhou_u0 0.0_0.0_0.003 + +lb_bc_outflow_type rhou +lb_bc_outflow_rhou_rho0 1.0 + +############################################################################### +# +# Output frequency and type +# +############################################################################### + +freq_statistics 10 +config_at_end no diff --git a/tests/regression/d3q19-short/serial-open-ru2.log b/tests/regression/d3q19-short/serial-open-ru2.log new file mode 100644 index 000000000..a4d1a2bab --- /dev/null +++ b/tests/regression/d3q19-short/serial-open-ru2.log @@ -0,0 +1,116 @@ +Welcome to Ludwig v0.14.0 (Serial version running on 1 process) +Start time: Tue Nov 16 17:03:12 2021 + +Compiler: + name: Gnu 11.2.0 + version-string: 11.2.0 + +Note assertions via standard C assert() are on. + +Target thread model: None. + +Read 16 user parameters from serial-open-ru2.inp + +No free energy selected + +System details +-------------- +System size: 12 12 24 +Decomposition: 1 1 1 +Local domain: 12 12 24 +Periodic: 0 0 0 +Halo nhalo: 1 +Reorder: true +Initialised: 1 + +System properties +---------------- +Mean fluid density: 1.00000e+00 +Shear viscosity 1.00000e-01 +Bulk viscosity 1.00000e-01 +Temperature 0.00000e+00 +External body force density 0.00000e+00 0.00000e+00 0.00000e+00 +External E-field amplitude 0.00000e+00 0.00000e+00 0.00000e+00 +External E-field frequency 0.00000e+00 +External magnetic field 0.00000e+00 0.00000e+00 0.00000e+00 + +Lattice Boltzmann distributions +------------------------------- +Model: d3q19 +SIMD vector len: 1 +Number of sets: 1 +Halo type: full +Input format: binary +Output format: binary +I/O grid: 1 1 1 + +Lattice Boltzmann collision +--------------------------- +Relaxation time scheme: M10 +Hydrodynamic modes: on +Ghost modes: on +Isothermal fluctuations: off +Shear relaxation time: 8.00000e-01 +Bulk relaxation time: 8.00000e-01 +Ghost relaxation time: 1.00000e+00 +[Default] Random number seed: 7361237 + +Hydrodynamics +------------- +Hydrodynamics: on +INFLOW 0 0 1 +INFLOW 0.0000000e+00 0.0000000e+00 3.0000000e-03 + +Boundary walls +-------------- +Boundary walls: X Y - +Boundary speed u_x (bottom): 0.0000000e+00 +Boundary speed u_x (top): 0.0000000e+00 +Boundary normal lubrication rc: 0.0000000e+00 +Wall boundary links allocated: 5664 +Memory (total, bytes): 90624 +Boundary shear initialise: 0 +Initial conditions. + +Scalars - total mean variance min max +[rho] 3456.00 1.00000000000 2.2204460e-16 1.00000000000 1.00000000000 + +Momentum - x y z +[total ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 +[fluid ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 +[walls ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 + +Starting time step loop. + +Scalars - total mean variance min max +[rho] 3459.52 1.00101995193 3.2691361e-06 1.00000000000 1.00688883987 + +Momentum - x y z +[total ] -1.3593293e-14 1.0130785e-15 2.2941291e+00 +[fluid ] -7.4107387e-15 -8.6042284e-16 1.8646524e+00 +[walls ] -6.1825545e-15 1.8735014e-15 4.2947672e-01 + +Velocity - x y z +[minimum ] -3.1215960e-04 -3.1215960e-04 -1.7347235e-17 +[maximum ] 3.1215960e-04 3.1215960e-04 3.0594611e-03 + +Completed cycle 10 + +Timer resolution: 1e-06 second + +Timer statistics + Section: tmin tmax total + Total: 0.058 0.058 0.058 0.058257 (1 call) + Time step loop: 0.005 0.005 0.051 0.005108 (10 calls) + Propagation: 0.001 0.001 0.011 0.001057 (10 calls) + Propagtn (krnl) : 0.001 0.001 0.011 0.001051 (10 calls) + Collision: 0.002 0.003 0.025 0.002493 (10 calls) + Collision (krnl) : 0.002 0.003 0.025 0.002485 (10 calls) + Lattice halos: 0.000 0.001 0.005 0.000537 (10 calls) + phi gradients: 0.000 0.000 0.000 0.000001 (10 calls) + BBL: 0.001 0.001 0.008 0.000816 (10 calls) + Force calculation: 0.000 0.000 0.000 0.000001 (10 calls) + phi update: 0.000 0.000 0.000 0.000000 (10 calls) + Free1: 0.000 0.002 0.002 0.000197 (10 calls) +End time: Tue Nov 16 17:03:12 2021 +Ludwig finished normally. From 5834b085a9d1cd0d33e51e1a34ec2b8d35ff3e73 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Thu, 18 Nov 2021 12:27:59 +0000 Subject: [PATCH 051/117] Remove extraneous output --- src/lb_bc_open_rt.c | 8 -------- tests/regression/d3q19-short/serial-open-ru1.log | 2 -- tests/regression/d3q19-short/serial-open-ru2.log | 2 -- 3 files changed, 12 deletions(-) diff --git a/src/lb_bc_open_rt.c b/src/lb_bc_open_rt.c index 818bc2283..4d217ed07 100644 --- a/src/lb_bc_open_rt.c +++ b/src/lb_bc_open_rt.c @@ -108,14 +108,6 @@ __host__ int lb_bc_open_rt(pe_t * pe, rt_t * rt, cs_t * cs, lb_t * lb, lb_bc_inflow_rhou_create(pe, cs, &options, &rhou); *inflow = (lb_bc_open_t *) rhou; - printf("INFLOW %d %d %d\n", - rhou->options.flow[X], - rhou->options.flow[Y], - rhou->options.flow[Z]); - printf("INFLOW %14.7e %14.7e %14.7e\n", - rhou->options.u0[X], - rhou->options.u0[Y], - rhou->options.u0[Z]); } else { /* Not recognised */ diff --git a/tests/regression/d3q19-short/serial-open-ru1.log b/tests/regression/d3q19-short/serial-open-ru1.log index 0c15b2843..6108b7739 100644 --- a/tests/regression/d3q19-short/serial-open-ru1.log +++ b/tests/regression/d3q19-short/serial-open-ru1.log @@ -58,8 +58,6 @@ Ghost relaxation time: 1.00000e+00 Hydrodynamics ------------- Hydrodynamics: on -INFLOW 1 0 0 -INFLOW 0.0000000e+00 0.0000000e+00 0.0000000e+00 Boundary walls -------------- diff --git a/tests/regression/d3q19-short/serial-open-ru2.log b/tests/regression/d3q19-short/serial-open-ru2.log index a4d1a2bab..d2f5969fa 100644 --- a/tests/regression/d3q19-short/serial-open-ru2.log +++ b/tests/regression/d3q19-short/serial-open-ru2.log @@ -58,8 +58,6 @@ Ghost relaxation time: 1.00000e+00 Hydrodynamics ------------- Hydrodynamics: on -INFLOW 0 0 1 -INFLOW 0.0000000e+00 0.0000000e+00 3.0000000e-03 Boundary walls -------------- From 973b12d0eaf542e22604efe39d70892fd4eacdc3 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Thu, 18 Nov 2021 12:29:24 +0000 Subject: [PATCH 052/117] Add phi open boundary conditions --- src/ludwig.c | 18 +++ src/phi_bc_inflow_fixed.c | 131 +++++++++++++++++++ src/phi_bc_inflow_fixed.h | 44 +++++++ src/phi_bc_inflow_opts.c | 63 +++++++++ src/phi_bc_inflow_opts.h | 32 +++++ src/phi_bc_open.h | 46 +++++++ src/phi_bc_open_rt.c | 132 +++++++++++++++++++ src/phi_bc_open_rt.h | 29 +++++ src/phi_bc_outflow_free.c | 135 +++++++++++++++++++ src/phi_bc_outflow_free.h | 41 ++++++ src/phi_bc_outflow_opts.c | 53 ++++++++ src/phi_bc_outflow_opts.h | 31 +++++ tests/regression/d2q9/serial-open-phi.inp | 100 ++++++++++++++ tests/regression/d2q9/serial-open-phi.log | 152 ++++++++++++++++++++++ tests/unit/test_lb_bc_outflow_rhou.c | 5 +- tests/unit/test_phi_bc_inflow_fixed.c | 129 ++++++++++++++++++ tests/unit/test_phi_bc_inflow_opts.c | 136 +++++++++++++++++++ tests/unit/test_phi_bc_outflow_free.c | 143 ++++++++++++++++++++ tests/unit/test_phi_bc_outflow_opts.c | 128 ++++++++++++++++++ tests/unit/tests.c | 4 + tests/unit/tests.h | 4 + 21 files changed, 1555 insertions(+), 1 deletion(-) create mode 100644 src/phi_bc_inflow_fixed.c create mode 100644 src/phi_bc_inflow_fixed.h create mode 100644 src/phi_bc_inflow_opts.c create mode 100644 src/phi_bc_inflow_opts.h create mode 100644 src/phi_bc_open.h create mode 100644 src/phi_bc_open_rt.c create mode 100644 src/phi_bc_open_rt.h create mode 100644 src/phi_bc_outflow_free.c create mode 100644 src/phi_bc_outflow_free.h create mode 100644 src/phi_bc_outflow_opts.c create mode 100644 src/phi_bc_outflow_opts.h create mode 100644 tests/regression/d2q9/serial-open-phi.inp create mode 100644 tests/regression/d2q9/serial-open-phi.log create mode 100644 tests/unit/test_phi_bc_inflow_fixed.c create mode 100644 tests/unit/test_phi_bc_inflow_opts.c create mode 100644 tests/unit/test_phi_bc_outflow_free.c create mode 100644 tests/unit/test_phi_bc_outflow_opts.c diff --git a/src/ludwig.c b/src/ludwig.c index 1353ead85..70a5e4cc0 100644 --- a/src/ludwig.c +++ b/src/ludwig.c @@ -92,6 +92,7 @@ /* Open boundary conditions */ #include "lb_bc_open_rt.h" +#include "phi_bc_open_rt.h" /* Electrokinetics */ #include "psi.h" @@ -166,6 +167,8 @@ struct ludwig_s { lb_bc_open_t * inflow; /* Inflow open boundary conidition (fluid) */ lb_bc_open_t * outflow; /* Outflow boundary condition (fluid) */ + phi_bc_open_t * phi_inflow; /* Inflow (composition phi) */ + phi_bc_open_t * phi_outflow; /* Outflow (composition phi) */ stats_sigma_t * stat_sigma; /* Interfacial tension calibration */ stats_ahydro_t * stat_ah; /* Hydrodynamic radius calibration */ @@ -245,6 +248,7 @@ static int ludwig_rt(ludwig_t * ludwig) { visc_model_init_rt(pe, rt, ludwig); lb_bc_open_rt(pe, rt, cs, ludwig->lb, &ludwig->inflow, &ludwig->outflow); + phi_bc_open_rt(pe, rt, cs, &ludwig->phi_inflow, &ludwig->phi_outflow); /* PHI I/O */ @@ -569,6 +573,18 @@ void ludwig_run(const char * inputfile) { field_halo(ludwig->phi); TIMER_stop(TIMER_PHI_HALO); + /* Boundary conditions on phi after halo and + * before gradient calculation. */ + + if (ludwig->phi_inflow) { + phi_bc_open_t * inflow = ludwig->phi_inflow; + inflow->func->update(inflow, ludwig->phi); + } + if (ludwig->phi_outflow) { + phi_bc_open_t * outflow = ludwig->phi_outflow; + outflow->func->update(outflow, ludwig->phi); + } + field_grad_compute(ludwig->phi_grad); } @@ -1087,6 +1103,8 @@ void ludwig_run(const char * inputfile) { if (ludwig->inflow) ludwig->inflow->func->free(ludwig->inflow); if (ludwig->outflow) ludwig->outflow->func->free(ludwig->outflow); + if (ludwig->phi_inflow) ludwig->phi_inflow->func->free(ludwig->phi_inflow); + if (ludwig->phi_outflow) ludwig->phi_outflow->func->free(ludwig->phi_outflow); if (ludwig->interact) interact_free(ludwig->interact); if (ludwig->cio) colloid_io_free(ludwig->cio); diff --git a/src/phi_bc_inflow_fixed.c b/src/phi_bc_inflow_fixed.c new file mode 100644 index 000000000..f939ec648 --- /dev/null +++ b/src/phi_bc_inflow_fixed.c @@ -0,0 +1,131 @@ +/***************************************************************************** + * + * phi_bc_inflow_fixed.c + * + * A fixed inflow boundary condition which sets a uniformly constant + * phi_0 at the boundary region (to the current depth of the halo). + * + * This is intended to propagate into the compution of the gradient + * in the boundary region (grad phi ~ 0 and \nabla^2 phi ~ 0) which + * should represent a constant chemical potential, and a constant + * stress on the fluid. + * + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + ****************************************************************************/ + +#include +#include + +#include "phi_bc_inflow_fixed.h" + +static const phi_bc_open_vtable_t vt_ = { + (phi_bc_open_free_ft) phi_bc_inflow_fixed_free, + (phi_bc_open_update_ft) phi_bc_inflow_fixed_update +}; + +/***************************************************************************** + * + * phi_bc_inflow_fixed_create + * + *****************************************************************************/ + +__host__ int phi_bc_inflow_fixed_create(pe_t * pe, cs_t * cs, + const phi_bc_inflow_opts_t * options, + phi_bc_inflow_fixed_t ** inflow) { + + phi_bc_inflow_fixed_t * bc = NULL; + + assert(pe); + assert(cs); + assert(options); + assert(inflow); + + bc = (phi_bc_inflow_fixed_t *) calloc(1, sizeof(phi_bc_inflow_fixed_t)); + assert(bc); + if (bc == NULL) pe_fatal(pe, "Failed to allocate phi_bc_inflow_fixed_t\n"); + + /* Pointers and superclass */ + + bc->pe = pe; + bc->cs = cs; + + bc->super.func = &vt_; + bc->super.id = PHI_BC_INFLOW_FIXED; + + bc->options = *options; + + *inflow = bc; + + return 0; +} + +/***************************************************************************** + * + * phi_bc_inflow_fixed_free + * + *****************************************************************************/ + +__host__ int phi_bc_inflow_fixed_free(phi_bc_inflow_fixed_t * inflow) { + + assert(inflow); + + free(inflow); + + return 0; +} + +/***************************************************************************** + * + * phi_bc_inflow_fixed_update + * + *****************************************************************************/ + +__host__ int phi_bc_inflow_fixed_update(phi_bc_inflow_fixed_t * inflow, + field_t * phi) { + int id = -1; + int nhalo = 0; + int nlocal[3] = {}; + int noffset[3] = {}; + cs_t * cs = NULL; + + assert(inflow); + assert(phi); + + /* Set in inflow region being X, Y, or Z. */ + + if (inflow->options.flow[X]) id = X; + if (inflow->options.flow[Y]) id = Y; + if (inflow->options.flow[Z]) id = Z; + + cs = inflow->cs; + cs_nlocal(cs, nlocal); + cs_nlocal_offset(cs, noffset); + cs_nhalo(cs, &nhalo); + + if (noffset[id] == 0) { + + /* The inflow region covers the halo only in the flow direction. */ + + int imin[3] = {1, 1, 1}; + int imax[3] = {nlocal[X], nlocal[Y], nlocal[Z]}; + + imin[id] = 1 - nhalo; + imax[id] = 0; + + for (int ic = imin[X]; ic <= imax[X]; ic++) { + for (int jc = imin[Y]; jc <= imax[Y]; jc++) { + for (int kc = imin[Z]; kc <= imax[Z]; kc++) { + int index = cs_index(inflow->cs,ic, jc, kc); + field_scalar_set(phi, index, inflow->options.phi0); + } + } + } + } + + return 0; +} diff --git a/src/phi_bc_inflow_fixed.h b/src/phi_bc_inflow_fixed.h new file mode 100644 index 000000000..b7e9bf347 --- /dev/null +++ b/src/phi_bc_inflow_fixed.h @@ -0,0 +1,44 @@ +/***************************************************************************** + * + * phi_bc_inflow_fixed.h + * + * Composition inflow boundary condition. + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#ifndef LUDWIG_PHI_BC_INFLOW_FIXED_H +#define LUDWIG_PHI_BC_INFLOW_FIXED_H + +#include "phi_bc_open.h" +#include "phi_bc_inflow_opts.h" + +typedef struct phi_bc_inflow_fixed_s phi_bc_inflow_fixed_t; + +/* Inflow boundary condition */ + +struct phi_bc_inflow_fixed_s { + + phi_bc_open_t super; /* Superclass block */ + pe_t * pe; /* Parallel environment */ + cs_t * cs; /* Coordinate system */ + phi_bc_inflow_opts_t options; /* Parameters */ + phi_bc_inflow_fixed_t * target; /* Device pointer */ + +}; + +__host__ int phi_bc_inflow_fixed_create(pe_t * pe, cs_t * cs, + const phi_bc_inflow_opts_t * options, + phi_bc_inflow_fixed_t ** inflow); +__host__ int phi_bc_inflow_fixed_free(phi_bc_inflow_fixed_t * inflow); +__host__ int phi_bc_inflow_fixed_update(phi_bc_inflow_fixed_t * inflow, + field_t * phi); + +#endif diff --git a/src/phi_bc_inflow_opts.c b/src/phi_bc_inflow_opts.c new file mode 100644 index 000000000..3e178ded4 --- /dev/null +++ b/src/phi_bc_inflow_opts.c @@ -0,0 +1,63 @@ +/***************************************************************************** + * + * phi_bc_inflow_opts.c + * + * Inflow options for composition open boundary condition. + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcced.ac.uk) + * + *****************************************************************************/ + +#include "phi_bc_inflow_opts.h" + +/***************************************************************************** + * + * phi_bc_inflow_opts_default + * + *****************************************************************************/ + +phi_bc_inflow_opts_t phi_bc_inflow_opts_default(void) { + + phi_bc_inflow_opts_t options = {}; /* Uninterestingly, NULL */ + + return options; +} + +/***************************************************************************** + * + * phi_bc_inflow_opts_valid + * + *****************************************************************************/ + +int phi_bc_inflow_opts_valid(phi_bc_inflow_opts_t options) { + + int valid = 0; /* Invalid */ + + /* No condition on phi0 */ + valid = phi_bc_inflow_opts_flow_valid(options.flow); + + return valid; +} + +/***************************************************************************** + * + * phi_bc_inflow_opts_flow_valid + * + *****************************************************************************/ + +int phi_bc_inflow_opts_flow_valid(const int flow[3]) { + + int valid = 0; /* Invalid */ + int sum = flow[0] + flow[1] + flow[2]; + + /* No flow is ok; otherwise one direction only. */ + valid = (sum == 0 || sum == 1); + + return valid; +} diff --git a/src/phi_bc_inflow_opts.h b/src/phi_bc_inflow_opts.h new file mode 100644 index 000000000..fb090f223 --- /dev/null +++ b/src/phi_bc_inflow_opts.h @@ -0,0 +1,32 @@ +/***************************************************************************** + * + * phi_bc_inflow_opts.h + * + * Composition boundary condition options/parameters. + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#ifndef LUDWIG_PHI_BC_INFLOW_OPTS_H +#define LUDWIG_PHI_BC_INFLOW_OPTS_H + +typedef struct phi_bc_inflow_opts_s phi_bc_inflow_opts_t; + +struct phi_bc_inflow_opts_s { + double phi0; /* Fixed value of phi at boundary */ + int flow[3]; /* Flow direction */ +}; + +phi_bc_inflow_opts_t phi_bc_inflow_opts_default(void); + +int phi_bc_inflow_opts_valid(phi_bc_inflow_opts_t options); +int phi_bc_inflow_opts_flow_valid(const int flow[3]); + +#endif diff --git a/src/phi_bc_open.h b/src/phi_bc_open.h new file mode 100644 index 000000000..b807abb49 --- /dev/null +++ b/src/phi_bc_open.h @@ -0,0 +1,46 @@ +/***************************************************************************** + * + * phi_bc_open.h + * + * Compositional order parameter boundary condition (abstract type). + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#ifndef LUDWIG_PHI_BC_OPEN_H +#define LUDWIG_PHI_BC_OPEN_H + +#include "field.h" + +typedef struct phi_bc_open_vtable_s phi_bc_open_vtable_t; +typedef struct phi_bc_open_s phi_bc_open_t; + +typedef int (* phi_bc_open_free_ft) (phi_bc_open_t * bc); +typedef int (* phi_bc_open_update_ft) (phi_bc_open_t * bc, field_t * phi); + +struct phi_bc_open_vtable_s { + phi_bc_open_free_ft free; /* Desctructor */ + phi_bc_open_update_ft update; /* Update */ +}; + +/* Implementations */ + +typedef enum phi_bc_open_enum {PHI_BC_INVALID, + PHI_BC_INFLOW_FIXED, + PHI_BC_OUTFLOW_FREE, + PHI_BC_MAX} phi_bc_open_enum_t; +/* Superclass block */ + +struct phi_bc_open_s { + const phi_bc_open_vtable_t * func; /* function table */ + phi_bc_open_enum_t id; /* unique type identifier */ +}; + +#endif diff --git a/src/phi_bc_open_rt.c b/src/phi_bc_open_rt.c new file mode 100644 index 000000000..372918907 --- /dev/null +++ b/src/phi_bc_open_rt.c @@ -0,0 +1,132 @@ +/***************************************************************************** + * + * phi_bc_open_rt.c + * + * Generate paired instance of inflow and outflow boundary conditions + * for composition. + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#include +#include + +#include "phi_bc_open_rt.h" + + +/* Available implementations */ + +#include "phi_bc_inflow_fixed.h" +#include "phi_bc_outflow_free.h" + +/***************************************************************************** + * + * phi_bc_open_rt + * + * A factory method to generate both inflow and outflow (there must + * be either none or both) from user input. + * + *****************************************************************************/ + +__host__ int phi_bc_open_rt(pe_t * pe, rt_t * rt, cs_t * cs, + phi_bc_open_t ** inflow, + phi_bc_open_t ** outflow) { + + int have_bc = 0; /* inflow/outflow required? */ + int flow[3] = {}; /* flow direction (one only, or none) */ + + assert(pe); + assert(cs); + assert(rt); + assert(inflow); + assert(outflow); + + have_bc = rt_switch(rt, "phi_bc_open"); + + if (have_bc) { + int wall[3] = {}; + int periodic[3] = {}; + + /* Take flow direction from non-wall direction */ + + rt_int_parameter_vector(rt, "boundary_walls", wall); + flow[X] = 1 - wall[X]; + flow[Y] = 1 - wall[Y]; + flow[Z] = 1 - wall[Z]; + + if (phi_bc_inflow_opts_flow_valid(flow) == 0) { + pe_fatal(pe, "Inflow/outflow requires exactly one open direction\n"); + } + + cs_periodic(cs, periodic); + if (periodic[X] || periodic[Y] || periodic[Z]) { + pe_fatal(pe, "Inflow/outflow requires fully non-periodic system\n"); + } + + rt_key_required(rt, "phi_bc_inflow_type", RT_INFO); + rt_key_required(rt, "phi_bc_outflow_type", RT_INFO); + } + + /* Inflow */ + + if (have_bc) { + char intype[BUFSIZ] = {}; + double phib = -999.999; + + rt_string_parameter(rt, "phi_bc_inflow_type", intype, BUFSIZ); + rt_double_parameter(rt, "phi_bc_inflow_fixed_phib", &phib); + + if (strncmp(intype, "fixed", BUFSIZ) == 0) { + /* A fixed-type inflow */ + phi_bc_inflow_fixed_t * bc = NULL; + phi_bc_inflow_opts_t options = {.phi0 = phib, + .flow = {flow[X], flow[Y], flow[Z]}}; + + if (phi_bc_inflow_opts_valid(options) == 0) { + /* Further diagnostic information. */ + pe_fatal(pe, "Please check phi_bc_inflow options\n"); + } + + phi_bc_inflow_fixed_create(pe, cs, &options, &bc); + *inflow = (phi_bc_open_t *) bc; + } + else { + pe_info(pe, "phi_bc_inflow_type not recognised: %s\n", intype); + pe_fatal(pe, "Please check and try again.\n"); + } + } + + /* Outflow */ + + if (have_bc) { + + char outtype[BUFSIZ] = {}; + + rt_string_parameter(rt, "phi_bc_outflow_type", outtype, BUFSIZ); + + if (strncmp(outtype, "free", BUFSIZ) == 0) { + phi_bc_outflow_free_t * bc = NULL; + phi_bc_outflow_opts_t options = {.flow = {flow[X], flow[Y], flow[Z]}}; + + /* Check options valid */ + if (phi_bc_outflow_opts_valid(options) == 0) { + pe_fatal(pe, "phi_bc_outflow_fixed options not valid\n"); + } + + phi_bc_outflow_free_create(pe, cs, &options, &bc); + *outflow = (phi_bc_open_t *) bc; + } + else { + pe_fatal(pe, "phi_bc_outflow_type not recognised: %s\n", outflow); + } + } + + return 0; +} diff --git a/src/phi_bc_open_rt.h b/src/phi_bc_open_rt.h new file mode 100644 index 000000000..02702331f --- /dev/null +++ b/src/phi_bc_open_rt.h @@ -0,0 +1,29 @@ +/***************************************************************************** + * + * phi_bc_open_rt.h + * + * Composition open boundaries. See phi_bc_open_rt.c for details. + * + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford + * + *****************************************************************************/ + +#ifndef LUDWIG_PHI_BC_OPEN_RT_H +#define LUDWIG_PHI_BC_OPEN_RT_H + +#include "pe.h" +#include "coords.h" +#include "phi_bc_open.h" +#include "runtime.h" + +__host__ int phi_bc_open_rt(pe_t * pe, rt_t * rt, cs_t * cs, + phi_bc_open_t ** inflow, + phi_bc_open_t ** outflow); +#endif diff --git a/src/phi_bc_outflow_free.c b/src/phi_bc_outflow_free.c new file mode 100644 index 000000000..d10912e35 --- /dev/null +++ b/src/phi_bc_outflow_free.c @@ -0,0 +1,135 @@ +/***************************************************************************** + * + * phi_bc_outflow_free.c + * + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#include +#include + +#include "phi_bc_outflow_free.h" + +static const phi_bc_open_vtable_t vt_ = { + (phi_bc_open_free_ft) phi_bc_outflow_free_free, + (phi_bc_open_update_ft) phi_bc_outflow_free_update +}; + +/***************************************************************************** + * + * phi_bc_outflow_free_create + * + *****************************************************************************/ + +__host__ int phi_bc_outflow_free_create(pe_t * pe, cs_t * cs, + const phi_bc_outflow_opts_t * options, + phi_bc_outflow_free_t ** outflow) { + phi_bc_outflow_free_t * bc = NULL; + + assert(pe); + assert(cs); + assert(options); + assert(outflow); + + bc = (phi_bc_outflow_free_t *) calloc(1, sizeof(phi_bc_outflow_free_t)); + assert(bc); + if (bc == NULL) pe_fatal(pe, "calloc phi_bc_outflow_free_t failed\n"); + + /* Pointers */ + bc->pe = pe; + bc->cs = cs; + + if (phi_bc_outflow_opts_valid(*options) == 0) { + pe_fatal(pe, "Internal error: phi_bc_outflow_opts not valid\n"); + } + bc->options = *options; + + bc->super.func = &vt_; + bc->super.id = PHI_BC_OUTFLOW_FREE; + + *outflow = bc; + + return 0; +} + +/***************************************************************************** + * + * phi_bc_outflow_free_free + * + *****************************************************************************/ + +__host__ int phi_bc_outflow_free_free(phi_bc_outflow_free_t * outflow) { + + assert(outflow); + + free(outflow); + + return 0; +} + +/***************************************************************************** + * + * phi_bc_outflow_free_update + * + *****************************************************************************/ + +__host__ int phi_bc_outflow_free_update(phi_bc_outflow_free_t * outflow, + field_t * phi) { + int id = -1; + int nhalo = -1; + int nlocal[3] = {}; + int ntotal[3] = {}; + int noffset[3] = {}; + cs_t * cs = NULL; + + assert(outflow); + assert(phi); + + if (outflow->options.flow[X] == 1) id = X; + if (outflow->options.flow[Y] == 1) id = Y; + if (outflow->options.flow[Z] == 1) id = Z; + + cs = outflow->cs; + cs_ntotal(cs, ntotal); + cs_nlocal(cs, nlocal); + cs_nlocal_offset(cs, noffset); + cs_nhalo(cs, &nhalo); + + if (noffset[id] + nlocal[id] == ntotal[id]) { + /* Set halo region e.g., phi(x > L_x, y, z) = phi(x = L_x, y, z) */ + /* Slightly convoluted to allow x, y, or z direction. */ + + int imin[3] = {1, 1, 1}; + int imax[3] = {nlocal[X], nlocal[Y], nlocal[Z]}; + + imin[id] = nlocal[id]; + imax[id] = nlocal[id]; + + for (int ic = imin[X]; ic <= imax[X]; ic++) { + for (int jc = imin[Y]; jc <= imax[Y]; jc++) { + for (int kc = imin[Z]; kc <= imax[Z]; kc++) { + int index = cs_index(cs, ic, jc, kc); + double phi0 = 0.0; + field_scalar(phi, index, &phi0); /* Domain value */ + for (int nh = 1; nh <= nhalo; nh++) { + int di[3] = {nh*outflow->options.flow[X], + nh*outflow->options.flow[Y], + nh*outflow->options.flow[Z]}; + index = cs_index(cs, ic + di[X], jc + di[Y], kc + di[Z]); + field_scalar_set(phi, index, phi0); + } + } + } + } + } + + return 0; +} diff --git a/src/phi_bc_outflow_free.h b/src/phi_bc_outflow_free.h new file mode 100644 index 000000000..880db6da7 --- /dev/null +++ b/src/phi_bc_outflow_free.h @@ -0,0 +1,41 @@ +/***************************************************************************** + * + * phi_bc_outflow_free.h + * + * An outflow boundary conditions. + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#ifndef LUDWIG_PHI_BC_OUTFLOW_FREE_H +#define LUDWIG_PHI_BC_OUTFLOW_FREE_H + +#include "phi_bc_open.h" +#include "phi_bc_outflow_opts.h" + +typedef struct phi_bc_outflow_free_s phi_bc_outflow_free_t; + +struct phi_bc_outflow_free_s { + phi_bc_open_t super; /* Superclass block */ + pe_t * pe; /* Parallel environment */ + cs_t * cs; /* Coordinate system */ + phi_bc_outflow_opts_t options; /* Parameters */ + + phi_bc_outflow_free_t * target; /* Device copy */ +}; + +__host__ int phi_bc_outflow_free_create(pe_t * pe, cs_t * cs, + const phi_bc_outflow_opts_t * options, + phi_bc_outflow_free_t ** outflow); +__host__ int phi_bc_outflow_free_update(phi_bc_outflow_free_t * outflow, + field_t * phi); +__host__ int phi_bc_outflow_free_free(phi_bc_outflow_free_t * outflow); + +#endif diff --git a/src/phi_bc_outflow_opts.c b/src/phi_bc_outflow_opts.c new file mode 100644 index 000000000..30686a109 --- /dev/null +++ b/src/phi_bc_outflow_opts.c @@ -0,0 +1,53 @@ +/***************************************************************************** + * + * phi_bc_outflow_opts.c + * + *****************************************************************************/ + +#include + +#include "phi_bc_outflow_opts.h" + +/***************************************************************************** + * + * phi_bc_outflow_opts_default + * + *****************************************************************************/ + +phi_bc_outflow_opts_t phi_bc_outflow_opts_default(void) { + + phi_bc_outflow_opts_t options = {}; + + return options; +} + +/***************************************************************************** + * + * phi_bc_outflow_opts_valid + * + *****************************************************************************/ + +int phi_bc_outflow_opts_valid(phi_bc_outflow_opts_t options) { + + int isvalid = 0; /* Invalid */ + + isvalid = phi_bc_outflow_opts_flow_valid(options.flow); + + return isvalid; +} + +/***************************************************************************** + * + * phi_bc_outflow_opts_flow_valid + * + *****************************************************************************/ + +int phi_bc_outflow_opts_flow_valid(const int flow[3]) { + + int isvalid = 0; /* Invalid */ + int sum = flow[0] + flow[1] + flow[2]; + + isvalid = (sum == 0) || (sum == 1); + + return isvalid; +} diff --git a/src/phi_bc_outflow_opts.h b/src/phi_bc_outflow_opts.h new file mode 100644 index 000000000..967d17fc8 --- /dev/null +++ b/src/phi_bc_outflow_opts.h @@ -0,0 +1,31 @@ +/***************************************************************************** + * + * phi_bc_outflow_opts.h + * + * Composition outflow boundary condition options. + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#ifndef LUDWIG_PHI_BC_OUTFLOW_OPTS_H +#define LUDWIG_PHI_BC_OUTFLOW_OPTS_H + +typedef struct phi_bc_outflow_opts_s phi_bc_outflow_opts_t; + +struct phi_bc_outflow_opts_s { + int flow[3]; /* Flow direction. */ +}; + +phi_bc_outflow_opts_t phi_bc_outflow_opts_default(void); + +int phi_bc_outflow_opts_valid(phi_bc_outflow_opts_t options); +int phi_bc_outflow_opts_flow_valid(const int flow[3]); + +#endif diff --git a/tests/regression/d2q9/serial-open-phi.inp b/tests/regression/d2q9/serial-open-phi.inp new file mode 100644 index 000000000..d54648e6b --- /dev/null +++ b/tests/regression/d2q9/serial-open-phi.inp @@ -0,0 +1,100 @@ +############################################################################## +# +# Open boundary conditions in both fluid and composition +# +# A slightly artificial test in which we place a drop +# (centre phi = -1) in the centre of a 2-d system and +# advect it out of the right hand side. +# +# The fluid is initialised with constant velocity, which +# matches the imposed input boundary condition. +# +# The drop takes about 6000 steps to be completely removed +# from the domain, which ends up uniformly phi = +1. +# +# For the purposes of this test, we only run 10 steps. +# +############################################################################## + +N_cycles 10 + +############################################################################## +# +# System and MPI +# +############################################################################## + +size 80_40_1 +grid 2_2_1 +periodicity 0_0_0 + +############################################################################## +# +# Fluid parameters +# +############################################################################## + +viscosity 0.1 + +distribution_initialisation 3d_uniform_u +distribution_uniform_u 0.01_0.0_0.0 + +############################################################################## +# +# Free energy parameters +# +############################################################################### + +free_energy symmetric + +symmetric_a -0.0625 +symmetric_b 0.0625 +symmetric_kappa 0.04 + +phi_initialisation drop +phi_init_drop_radius 8.0 +phi_init_drop_amplitude 1.0 + +mobility 0.1 +fd_gradient_calculation 2d_tomita_fluid + +############################################################################### +# +# Colloid parameters +# +############################################################################### + +colloid_init none + +############################################################################### +# +# Walls / boundaries +# +############################################################################### + +boundary_walls 0_1_1 +boundary_speed_bottom 0.0 +boundary_speed_top 0.0 + +lb_bc_open yes +lb_bc_inflow_type rhou +lb_bc_inflow_rhou_u0 0.01_0.0_0.0 + +lb_bc_outflow_type rhou +lb_bc_outflow_rhou_rho0 1.0 + +phi_bc_open yes +phi_bc_inflow_type fixed +phi_bc_inflow_fixed_phib +1.0 + +phi_bc_outflow_type free + +############################################################################### +# +# Output frequency and type +# +############################################################################### + +freq_statistics 10 +freq_phi 100 +config_at_end no diff --git a/tests/regression/d2q9/serial-open-phi.log b/tests/regression/d2q9/serial-open-phi.log new file mode 100644 index 000000000..ee535d89d --- /dev/null +++ b/tests/regression/d2q9/serial-open-phi.log @@ -0,0 +1,152 @@ +Welcome to Ludwig v0.14.0 (Serial version running on 1 process) +Start time: Thu Nov 18 11:47:58 2021 + +Compiler: + name: Gnu 11.2.0 + version-string: 11.2.0 + +Note assertions via standard C assert() are on. + +Target thread model: None. + +Read 32 user parameters from serial-open-phi.inp + +System details +-------------- +System size: 80 40 1 +Decomposition: 1 1 1 +Local domain: 80 40 1 +Periodic: 0 0 0 +Halo nhalo: 2 +Reorder: true +Initialised: 1 + +Free energy details +------------------- + +Symmetric phi^4 free energy selected. + +Parameters: +Bulk parameter A = -6.25000e-02 +Bulk parameter B = 6.25000e-02 +Surface penalty kappa = 4.00000e-02 +Surface tension = 4.71405e-02 +Interfacial width = 1.13137e+00 + +Using Cahn-Hilliard finite difference solver. +Mobility M = 1.00000e-01 +Order parameter noise = off +Force calculation: divergence method + +System properties +---------------- +Mean fluid density: 1.00000e+00 +Shear viscosity 1.00000e-01 +Bulk viscosity 1.00000e-01 +Temperature 0.00000e+00 +External body force density 0.00000e+00 0.00000e+00 0.00000e+00 +External E-field amplitude 0.00000e+00 0.00000e+00 0.00000e+00 +External E-field frequency 0.00000e+00 +External magnetic field 0.00000e+00 0.00000e+00 0.00000e+00 + +Lattice Boltzmann distributions +------------------------------- +Model: d2q9 +SIMD vector len: 1 +Number of sets: 1 +Halo type: full +Input format: binary +Output format: binary +I/O grid: 1 1 1 + +Lattice Boltzmann collision +--------------------------- +Relaxation time scheme: M10 +Hydrodynamic modes: on +Ghost modes: on +Isothermal fluctuations: off +Shear relaxation time: 8.00000e-01 +Bulk relaxation time: 8.00000e-01 +Ghost relaxation time: 1.00000e+00 +[Default] Random number seed: 7361237 + +Hydrodynamics +------------- +Hydrodynamics: on + +Order parameter I/O +------------------- +Order parameter I/O format: +I/O decomposition: 1 1 1 + +Advection scheme order: 1 (default) +Initialising droplet radius: 8.0000000e+00 +Initialising droplet amplitude: 1.0000000e+00 + +Boundary walls +-------------- +Boundary walls: - Y Z +Boundary speed u_x (bottom): 0.0000000e+00 +Boundary speed u_x (top): 0.0000000e+00 +Boundary normal lubrication rc: 0.0000000e+00 +Wall boundary links allocated: 480 +Memory (total, bytes): 7680 +Boundary shear initialise: 0 + +Initial distribution: 3d uniform desnity/velocity +Density: 1.0000000e+00 +Velocity: 1.0000000e-02 0.0000000e+00 0.0000000e+00 + +Gradient calculation: 2d_tomita_fluid +Initial conditions. + +Scalars - total mean variance min max +[rho] 3200.00 1.00000000000 0.0000000e+00 1.00000000000 1.00000000000 +[phi] 2.7928338e+03 8.7276057e-01 2.0274235e-01 -9.9999651e-01 1.0000000e+00 + +Momentum - x y z +[total ] 3.2000000e+01 0.0000000e+00 0.0000000e+00 +[fluid ] 3.2000000e+01 0.0000000e+00 0.0000000e+00 +[walls ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 + +Starting time step loop. + +Scalars - total mean variance min max +[rho] 3200.09 1.00002739061 9.3509479e-06 0.99481135726 1.01392358365 +[phi] 2.7928350e+03 8.7276095e-01 2.0154281e-01 -1.0030607e+00 1.0027681e+00 + +Free energies - timestep f v f/v f_s1 fs_s2 +[fe] 10 -4.7838937700e+01 3.2000000000e+03 -1.4949668031e-02 0.0000000000e+00 0.0000000000e+00 + +Momentum - x y z +[total ] 3.2068535e+01 1.9290125e-15 0.0000000e+00 +[fluid ] 3.0263827e+01 5.0067189e-04 0.0000000e+00 +[walls ] 1.8047079e+00 -5.0067189e-04 0.0000000e+00 + +Velocity - x y z +[minimum ] 2.8443251e-03 -6.4426101e-03 0.0000000e+00 +[maximum ] 1.6515746e-02 6.4426101e-03 1.1754944e-38 + +Completed cycle 10 + +Timer resolution: 1e-06 second + +Timer statistics + Section: tmin tmax total + Total: 0.166 0.166 0.166 0.165952 (1 call) + Time step loop: 0.015 0.018 0.157 0.015683 (10 calls) + Propagation: 0.002 0.003 0.023 0.002265 (10 calls) + Propagtn (krnl) : 0.002 0.003 0.023 0.002259 (10 calls) + Collision: 0.005 0.006 0.050 0.004985 (10 calls) + Collision (krnl) : 0.005 0.006 0.050 0.004979 (10 calls) + Lattice halos: 0.001 0.002 0.013 0.001320 (10 calls) + phi gradients: 0.000 0.001 0.005 0.000459 (10 calls) + phi halos: 0.000 0.000 0.003 0.000343 (10 calls) + BBL: 0.000 0.000 0.001 0.000050 (10 calls) + Force calculation: 0.003 0.004 0.031 0.003059 (10 calls) + phi update: 0.003 0.004 0.031 0.003135 (10 calls) + Advectn (krnl) : 0.001 0.001 0.008 0.000781 (10 calls) + Advectn BCS (krnl) : 0.001 0.001 0.008 0.000831 (10 calls) + Free1: 0.000 0.001 0.001 0.000150 (10 calls) +End time: Thu Nov 18 11:47:58 2021 +Ludwig finished normally. diff --git a/tests/unit/test_lb_bc_outflow_rhou.c b/tests/unit/test_lb_bc_outflow_rhou.c index e3e97d671..71228fa3a 100644 --- a/tests/unit/test_lb_bc_outflow_rhou.c +++ b/tests/unit/test_lb_bc_outflow_rhou.c @@ -147,6 +147,8 @@ __host__ int test_lb_bc_outflow_rhou_update(pe_t * pe, cs_t * cs) { __host__ int test_lb_bc_outflow_rhou_impose(pe_t * pe, cs_t * cs) { + int ierr = 0; + int nlocal[3] = {}; int ntotal[3] = {}; int noffset[3] = {}; @@ -222,6 +224,7 @@ __host__ int test_lb_bc_outflow_rhou_impose(pe_t * pe, cs_t * cs) { double rho0 = outflow->options.rho0; double fp = lb->model.wv[p]*rho0*(1.0 - 3.0*uz + 3.0*uz*uz); assert(fabs(f - fp) < DBL_EPSILON); + if (fabs(f - fp) > DBL_EPSILON) ierr += 1; } } } @@ -233,5 +236,5 @@ __host__ int test_lb_bc_outflow_rhou_impose(pe_t * pe, cs_t * cs) { hydro_free(hydro); lb_bc_outflow_rhou_free(outflow); - return 0; + return ierr; } diff --git a/tests/unit/test_phi_bc_inflow_fixed.c b/tests/unit/test_phi_bc_inflow_fixed.c new file mode 100644 index 000000000..f47afa5a9 --- /dev/null +++ b/tests/unit/test_phi_bc_inflow_fixed.c @@ -0,0 +1,129 @@ +/***************************************************************************** + * + * test_phi_bc_inflow_fixed.c + * + *****************************************************************************/ + +#include +#include +#include + +#include "phi_bc_inflow_fixed.h" + +__host__ int test_phi_bc_inflow_fixed_create(pe_t * pe, cs_t * cs); +__host__ int test_phi_bc_inflow_fixed_update(pe_t * pe, cs_t * cs); + +/***************************************************************************** + * + * test_phi_bc_inflow_fixed_suite + * + *****************************************************************************/ + +__host__ int test_phi_bc_inflow_fixed_suite(void) { + + pe_t * pe = NULL; + cs_t * cs = NULL; + + pe_create(MPI_COMM_WORLD, PE_QUIET, &pe); + cs_create(pe, &cs); + cs_init(cs); + + test_phi_bc_inflow_fixed_create(pe, cs); + test_phi_bc_inflow_fixed_update(pe, cs); + + pe_info(pe, "PASS ./unit/test_phi_bc_inflow_fixed\n"); + + cs_free(cs); + pe_free(pe); + + return 0; +} + +/***************************************************************************** + * + * test_phi_bc_inflow_fixed_create + * + *****************************************************************************/ + +__host__ int test_phi_bc_inflow_fixed_create(pe_t * pe, cs_t * cs) { + + phi_bc_inflow_opts_t options = {.phi0 = 1.0, .flow = {1,0,0}}; + phi_bc_inflow_fixed_t * inflow = NULL; + + assert(pe); + assert(cs); + + phi_bc_inflow_fixed_create(pe, cs, &options, &inflow); + assert(inflow); + + assert(inflow->options.phi0 == options.phi0); /* Really equal */ + assert(inflow->options.flow[0] == options.flow[0]); + assert(inflow->options.flow[1] == options.flow[1]); + assert(inflow->options.flow[2] == options.flow[2]); + + assert(inflow->super.func); + assert(inflow->super.id == PHI_BC_INFLOW_FIXED); + + phi_bc_inflow_fixed_free(inflow); + + return 0; +} + +/***************************************************************************** + * + * test_phi_bc_inflow_fixed_update + * + *****************************************************************************/ + +__host__ int test_phi_bc_inflow_fixed_update(pe_t * pe, cs_t * cs) { + + int noffset[3] = {}; + phi_bc_inflow_opts_t options = {.phi0 = 999.999, .flow = {1,0,0}}; + phi_bc_inflow_fixed_t * inflow = NULL; + field_t * phi = NULL; + + assert(pe); + assert(cs); + + field_create(pe, cs, 1, "phi", &phi); + field_init(phi, 1, NULL); + assert(phi); + + phi_bc_inflow_fixed_create(pe, cs, &options, &inflow); + /* Run the update */ + { + phi_bc_open_t * super = (phi_bc_open_t *) inflow; + super->func->update(super, phi); + } + + cs_nlocal_offset(cs, noffset); + + if (noffset[X] == 0) { + /* Check x-inflow region */ + int nhalo = 0; + int nlocal[3] = {}; + + cs_nhalo(cs, &nhalo); + cs_nlocal(cs, nlocal); + + for (int ic = 1 - nhalo; ic <= 0; ic++) { + for (int jc = 1; jc <= nlocal[Y]; jc++) { + for (int kc = 1; kc <= nlocal[Z]; kc++) { + int index = cs_index(cs, ic, jc, kc); + double phibc = 0.0; + field_scalar(phi, index, &phibc); + assert(fabs(phibc - inflow->options.phi0) < DBL_EPSILON); + } + } + } + } + + { + phi_bc_open_t * super = (phi_bc_open_t *) inflow; + super->func->free(super); + } + field_free(phi); + + return 0; +} + diff --git a/tests/unit/test_phi_bc_inflow_opts.c b/tests/unit/test_phi_bc_inflow_opts.c new file mode 100644 index 000000000..0ef663b76 --- /dev/null +++ b/tests/unit/test_phi_bc_inflow_opts.c @@ -0,0 +1,136 @@ +/***************************************************************************** + * + * test_phi_bc_inflow_opts.c + * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#include +#include +#include + +#include "pe.h" +#include "phi_bc_inflow_opts.h" + +__host__ int test_phi_bc_inflow_opts_default(void); +__host__ int test_phi_bc_inflow_opts_valid(void); +__host__ int test_phi_bc_inflow_opts_flow_valid(void); + +/***************************************************************************** + * + * test_phi_bc_inflow_opts_suite + * + *****************************************************************************/ + +__host__ int test_phi_bc_inflow_opts_suite(void) { + + pe_t * pe = NULL; + + pe_create(MPI_COMM_WORLD, PE_QUIET, &pe); + + test_phi_bc_inflow_opts_default(); + test_phi_bc_inflow_opts_valid(); + test_phi_bc_inflow_opts_flow_valid(); + + pe_info(pe, "PASS ./unit/test_phi_bc_inflow_opts\n"); + pe_free(pe); + + return 0; +} + +/***************************************************************************** + * + * test_phi_bc_inflow_opts_default + * + *****************************************************************************/ + +__host__ int test_phi_bc_inflow_opts_default(void) { + + int isvalid = 0; + phi_bc_inflow_opts_t options = phi_bc_inflow_opts_default(); + + assert(fabs(options.phi0 - 0.0) < DBL_EPSILON); + assert(options.flow[0] == 0); + assert(options.flow[1] == 0); + assert(options.flow[2] == 0); + + isvalid = phi_bc_inflow_opts_valid(options); + assert(isvalid); + + return isvalid; +} + +/***************************************************************************** + * + * test_phi_bc_inflow_opts_valid + * + *****************************************************************************/ + +__host__ int test_phi_bc_inflow_opts_valid(void) { + + int isvalid = 0; + + { + phi_bc_inflow_opts_t options = {.phi0 = 0.0, .flow = {1,0,0}}; /* valid */ + isvalid = phi_bc_inflow_opts_valid(options); + assert(isvalid); + } + + { + phi_bc_inflow_opts_t options = {.phi0 = 0.0, .flow = {1,1,1}}; /* not */ + isvalid = phi_bc_inflow_opts_valid(options); + assert(isvalid == 0); + } + + return isvalid; +} + +/***************************************************************************** + * + * test_phi_bc_inflow_opts_flow_valid + * + *****************************************************************************/ + +__host__ int test_phi_bc_inflow_opts_flow_valid(void) { + + int isvalid = 0; + + { + int flow[3] = {0, 0, 0}; + isvalid = phi_bc_inflow_opts_flow_valid(flow); + assert(isvalid); + } + + { + int flow[3] = {1, 0, 0}; + isvalid = phi_bc_inflow_opts_flow_valid(flow); + assert(isvalid); + } + + { + int flow[3] = {0, 1, 0}; + isvalid = phi_bc_inflow_opts_flow_valid(flow); + assert(isvalid); + } + + { + int flow[3] = {0, 0, 1}; + isvalid = phi_bc_inflow_opts_flow_valid(flow); + assert(isvalid); + } + + { + int flow[3] = {1, 0, 1}; + isvalid = phi_bc_inflow_opts_flow_valid(flow); + assert(isvalid == 0); + } + + return isvalid; +} diff --git a/tests/unit/test_phi_bc_outflow_free.c b/tests/unit/test_phi_bc_outflow_free.c new file mode 100644 index 000000000..12964c548 --- /dev/null +++ b/tests/unit/test_phi_bc_outflow_free.c @@ -0,0 +1,143 @@ +/***************************************************************************** + * + * test_phi_bc_outflow_free.c + * + *****************************************************************************/ + +#include +#include +#include + +#include "pe.h" +#include "phi_bc_outflow_free.h" + +__host__ int test_phi_bc_outflow_free_create(pe_t * pe, cs_t * cs); +__host__ int test_phi_bc_outflow_free_update(pe_t * pe, cs_t * cs); + +/***************************************************************************** + * + * test_phi_bc_outflow_free_suite + * + *****************************************************************************/ + +__host__ int test_phi_bc_outflow_free_suite(void) { + + pe_t * pe = NULL; + cs_t * cs = NULL; + + pe_create(MPI_COMM_WORLD, PE_QUIET, &pe); + cs_create(pe, &cs); + cs_init(cs); + + test_phi_bc_outflow_free_create(pe, cs); + test_phi_bc_outflow_free_update(pe, cs); + + pe_info(pe, "PASS ./unit/phi_bc_outflow_free\n"); + cs_free(cs); + pe_free(pe); + + return 0; +} + +/***************************************************************************** + * + * test_phi_bc_outflow_free_create + * + *****************************************************************************/ + +__host__ int test_phi_bc_outflow_free_create(pe_t * pe, cs_t * cs) { + + phi_bc_outflow_opts_t options = {.flow = {1,0,0}}; + phi_bc_outflow_free_t * outflow = NULL; + + assert(pe); + assert(cs); + + phi_bc_outflow_free_create(pe, cs, &options, &outflow); + assert(outflow); + + assert(outflow->options.flow[X] == options.flow[X]); + assert(outflow->options.flow[Y] == options.flow[Y]); + assert(outflow->options.flow[Z] == options.flow[Z]); + + assert(outflow->super.func); + assert(outflow->super.id == PHI_BC_OUTFLOW_FREE); + + phi_bc_outflow_free_free(outflow); + + return 0; +} + +/***************************************************************************** + * + * test_phi_bc_outflow_free_update + * + *****************************************************************************/ + +__host__ int test_phi_bc_outflow_free_update(pe_t * pe, cs_t * cs) { + + int nhalo = -1; + int nlocal[3] = {}; + int ntotal[3] = {}; + int noffset[3] = {}; + + phi_bc_outflow_opts_t options = {.flow = {1,0,0}}; + phi_bc_outflow_free_t * outflow = NULL; + field_t * phi = NULL; + + assert(pe); + assert(cs); + + field_create(pe, cs, 1, "phi", &phi); + field_init(phi, 1, NULL); + + /* Provide some initial conditions in the domain proper, + * with some artificial data. */ + + cs_ntotal(cs, ntotal); + cs_nlocal(cs, nlocal); + cs_nlocal_offset(cs, noffset); + cs_nhalo(cs, &nhalo); + + { + int ic = nlocal[X]; + for (int jc = 1; jc <= nlocal[Y]; jc++) { + for (int kc = 1; kc <= nlocal[Z]; kc++) { + int index = cs_index(cs, ic, jc, kc); + field_scalar_set(phi, index, 1.0*index); + } + } + } + + /* Run the update */ + phi_bc_outflow_free_create(pe, cs, &options, &outflow); + { + phi_bc_open_t * bc = (phi_bc_open_t *) outflow; + bc->func->update(bc, phi); + } + + /* Check */ + if (noffset[X] + nlocal[X] == ntotal[X]) { + for (int ic = nlocal[X] + 1; ic <= nlocal[X] + nhalo; ic++) { + for (int jc = 1; jc <= nlocal[Y]; jc++) { + for (int kc = 1; kc <= nlocal[Z]; kc++) { + int index0 = cs_index(cs, nlocal[X], jc, kc); + int index1 = cs_index(cs, ic, jc, kc); + double phi0 = 0.0; + double phi1 = 0.0; + field_scalar(phi, index0, &phi0); + field_scalar(phi, index1, &phi1); + assert(fabs(phi1 - phi0) < DBL_EPSILON); + } + } + } + } + + { + phi_bc_open_t * bc = (phi_bc_open_t *) outflow; + bc->func->free(bc); + } + field_free(phi); + + return 0; +} diff --git a/tests/unit/test_phi_bc_outflow_opts.c b/tests/unit/test_phi_bc_outflow_opts.c new file mode 100644 index 000000000..e9011c1e2 --- /dev/null +++ b/tests/unit/test_phi_bc_outflow_opts.c @@ -0,0 +1,128 @@ +/***************************************************************************** + * + * test_phi_bc_outflow_opts.c + * + * + * + *****************************************************************************/ + +#include + +#include "pe.h" +#include "phi_bc_outflow_opts.h" + +__host__ int test_phi_bc_outflow_opts_default(void); +__host__ int test_phi_bc_outflow_opts_valid(void); +__host__ int test_phi_bc_outflow_opts_flow_valid(void); + +/***************************************************************************** + * + * test_phi_bc_outflow_opts_suite + * + *****************************************************************************/ + +__host__ int test_phi_bc_outflow_opts_suite(void) { + + pe_t * pe = NULL; + + pe_create(MPI_COMM_WORLD, PE_QUIET, &pe); + + test_phi_bc_outflow_opts_default(); + test_phi_bc_outflow_opts_valid(); + test_phi_bc_outflow_opts_flow_valid(); + + pe_info(pe, "PASS ./unit/phi_bc_outflow_opts\n"); + pe_free(pe); + + return 0; +} + +/***************************************************************************** + * + * test_phi_bc_outflow_opts_default + * + *****************************************************************************/ + +__host__ int test_phi_bc_outflow_opts_default(void) { + + int isvalid = 0; + + phi_bc_outflow_opts_t options = phi_bc_outflow_opts_default(); + + assert(options.flow[0] == 0); + assert(options.flow[1] == 0); + assert(options.flow[2] == 0); + + isvalid = phi_bc_outflow_opts_valid(options); + assert(isvalid); + + return isvalid; +} + +/***************************************************************************** + * + * test_phi_bc_outflow_opts_valid + * + *****************************************************************************/ + +__host__ int test_phi_bc_outflow_opts_valid(void) { + + int isvalid = 0; + + { + phi_bc_outflow_opts_t options = {.flow = {1, 0, 0}}; + isvalid = phi_bc_outflow_opts_valid(options); + assert(isvalid); + } + + { + phi_bc_outflow_opts_t options = {.flow = {1, 1, 0}}; + isvalid = phi_bc_outflow_opts_valid(options); + assert(isvalid == 0); + } + + return isvalid; +} + +/***************************************************************************** + * + * test_phi_bc_outlfow_opts_flow_valid + * + *****************************************************************************/ + +__host__ int test_phi_bc_outflow_opts_flow_valid(void) { + + int isvalid = 0; + + { + int flow[3] = {0, 0, 0}; + isvalid = phi_bc_outflow_opts_flow_valid(flow); + assert(isvalid); + } + + { + int flow[3] = {1, 0, 0}; + isvalid = phi_bc_outflow_opts_flow_valid(flow); + assert(isvalid); + } + + { + int flow[3] = {0, 1, 0}; + isvalid = phi_bc_outflow_opts_flow_valid(flow); + assert(isvalid); + } + + { + int flow[3] = {0, 0, 1}; + isvalid = phi_bc_outflow_opts_flow_valid(flow); + assert(isvalid); + } + + { + int flow[3] = {1, 1, 1}; + isvalid = phi_bc_outflow_opts_flow_valid(flow); + assert(isvalid == 0); + } + + return isvalid; +} diff --git a/tests/unit/tests.c b/tests/unit/tests.c index e4f9943e4..204a4160c 100644 --- a/tests/unit/tests.c +++ b/tests/unit/tests.c @@ -89,6 +89,10 @@ __host__ int tests_create() { test_pair_ss_cut_suite(); test_pair_ss_cut_ij_suite(); test_pair_yukawa_suite(); + test_phi_bc_inflow_opts_suite(); + test_phi_bc_inflow_fixed_suite(); + test_phi_bc_outflow_opts_suite(); + test_phi_bc_outflow_free_suite(); test_polar_active_suite(); test_psi_suite(); test_lb_prop_suite(); diff --git a/tests/unit/tests.h b/tests/unit/tests.h index 94f879250..c59c700ab 100644 --- a/tests/unit/tests.h +++ b/tests/unit/tests.h @@ -75,6 +75,10 @@ int test_pe_suite(void); int test_phi_ch_suite(void); int test_polar_active_suite(void); int test_lb_prop_suite(void); +int test_phi_bc_inflow_opts_suite(void); +int test_phi_bc_inflow_fixed_suite(void); +int test_phi_bc_outflow_opts_suite(void); +int test_phi_bc_outflow_free_suite(void); int test_psi_suite(void); int test_psi_sor_suite(void); int test_random_suite(void); From d8b2f400b6aa88c6db9531b51dfa39eb6ab8dfcc Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Thu, 18 Nov 2021 12:46:00 +0000 Subject: [PATCH 053/117] Bug in printf arg fix --- src/phi_bc_open_rt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/phi_bc_open_rt.c b/src/phi_bc_open_rt.c index 372918907..7f2bf034a 100644 --- a/src/phi_bc_open_rt.c +++ b/src/phi_bc_open_rt.c @@ -124,7 +124,7 @@ __host__ int phi_bc_open_rt(pe_t * pe, rt_t * rt, cs_t * cs, *outflow = (phi_bc_open_t *) bc; } else { - pe_fatal(pe, "phi_bc_outflow_type not recognised: %s\n", outflow); + pe_fatal(pe, "phi_bc_outflow_type not recognised: %s\n", outtype); } } From 87e7b655f9aaa7c22c9983db52bc52ecd73ac636 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Thu, 25 Nov 2021 10:19:38 +0000 Subject: [PATCH 054/117] Clear compiler warning on new line --- src/cahn_hilliard_stats.c | 8 ++++++-- src/stats_distribution.c | 4 +++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/cahn_hilliard_stats.c b/src/cahn_hilliard_stats.c index 2b102e6ce..988b08148 100644 --- a/src/cahn_hilliard_stats.c +++ b/src/cahn_hilliard_stats.c @@ -271,7 +271,9 @@ __global__ void cahn_stats_kahan_sum_kernel(kernel_ctxt_t * ktx, field_t * phi, /* Final result */ - while (atomicCAS(&(stats->sum1.lock), 0, 1) != 0); + while (atomicCAS(&(stats->sum1.lock), 0, 1) != 0) + ; + __threadfence(); kahan_add(&stats->sum1, sum); @@ -344,7 +346,9 @@ __global__ void cahn_stats_klein_sum_kernel(kernel_ctxt_t * ktx, field_t * phi, /* Final result */ - while (atomicCAS(&(stats->sum2.lock), 0, 1) != 0); + while (atomicCAS(&(stats->sum2.lock), 0, 1) != 0) + ; + __threadfence(); klein_add(&stats->sum2, sum); diff --git a/src/stats_distribution.c b/src/stats_distribution.c index 99d4030e4..f753b8a43 100644 --- a/src/stats_distribution.c +++ b/src/stats_distribution.c @@ -331,7 +331,9 @@ __global__ void distribution_gm_kernel(kernel_ctxt_t * ktx, lb_t * lb, /* Final result */ - while (atomicCAS(&(gm[X].lock), 0, 1) != 0); + while (atomicCAS(&(gm[X].lock), 0, 1) != 0) + ; + __threadfence(); kahan_add(&gm[X], sumx); From b91a25c32321ae1b604d8c4e583718256bae6b87 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Thu, 25 Nov 2021 10:22:01 +0000 Subject: [PATCH 055/117] Fix minor type problems --- src/symmetric.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/symmetric.c b/src/symmetric.c index 04e61c765..46d8c294b 100644 --- a/src/symmetric.c +++ b/src/symmetric.c @@ -460,7 +460,7 @@ __host__ int fe_symm_theta_to_h(double theta, double * h) { z = csqrt(4.0*cpow(a1, 2)/a3 + a3 + 1.0/a3 - 2.0); /* May not quite make DBL_EPSILON depending on argument ... */ - if (fabs(cimag(z) > 2.0*DBL_EPSILON)) ierr = -1; + if (fabs(cimag(z)) > 2.0*DBL_EPSILON) ierr = -1; *h = creal(z); @@ -488,13 +488,13 @@ __host__ int fe_symm_h_to_costheta(double h, double * costheta) { int ierr = 0; - if (abs(h) > 1.0) { + if (fabs(h) > 1.0) { ierr = -1; *costheta = -999.999; } else { *costheta = 0.5*(-pow(1.0 - h, 1.5) + pow(1.0 + h, 1.5)); - if (abs(h) > sqrt(2.0*sqrt(3.0) - 3.0)) ierr = -1; + if (fabs(h) > sqrt(2.0*sqrt(3.0) - 3.0)) ierr = -1; } return ierr; From 20917b50dde7db2cd278215899027ff4f2365549 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Thu, 25 Nov 2021 10:22:20 +0000 Subject: [PATCH 056/117] Add lapse timer --- src/timer.c | 23 +++++++++++++++++++++++ src/timer.h | 2 ++ 2 files changed, 25 insertions(+) diff --git a/src/timer.c b/src/timer.c index 75346db24..364364bcf 100644 --- a/src/timer.c +++ b/src/timer.c @@ -122,6 +122,29 @@ void TIMER_start(const int t_id) { return; } +/***************************************************************************** + * + * timer_lapse + * + * Return lapsed time (seconds) since previous call (or start). + * + *****************************************************************************/ + +double timer_lapse(const int id) { + + double tlapse = -999.999; + + assert(tiemr[id].active); + + { + double tnow = MPI_Wtime(); + + tlapse = tnow - timer[id].t_start; + timer[id].t_start = tnow; + } + + return tlapse; +} /**************************************************************************** * diff --git a/src/timer.h b/src/timer.h index f3183df80..5f06e0c93 100644 --- a/src/timer.h +++ b/src/timer.h @@ -27,6 +27,8 @@ __host__ void TIMER_start(const int); __host__ void TIMER_stop(const int); __host__ void TIMER_statistics(void); +__host__ double timer_lapse(const int); + enum timer_id {TIMER_TOTAL = 0, TIMER_STEPS, TIMER_PROPAGATE, From 19f4bc87642d554a7d9787b6ef4c9c6e5d4dc800 Mon Sep 17 00:00:00 2001 From: kevinstratford Date: Thu, 25 Nov 2021 10:35:17 +0000 Subject: [PATCH 057/117] Correct typo in assertion --- src/timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/timer.c b/src/timer.c index 364364bcf..662b6d269 100644 --- a/src/timer.c +++ b/src/timer.c @@ -134,7 +134,7 @@ double timer_lapse(const int id) { double tlapse = -999.999; - assert(tiemr[id].active); + assert(timer[id].active); { double tnow = MPI_Wtime(); From 27dc050590adfc142a73747463ea0818e0f3026a Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Sun, 28 Nov 2021 19:28:33 +0000 Subject: [PATCH 058/117] Remove unused input key --- tests/regression/d3q19-extra/serial-ah01-125.inp | 1 - tests/regression/d3q19-extra/serial-auto-c01.inp | 1 - tests/regression/d3q19-extra/serial-auto-c02.inp | 1 - tests/regression/d3q19-extra/serial-auto-c03.inp | 1 - tests/regression/d3q19-extra/serial-auto-c04.inp | 1 - 5 files changed, 5 deletions(-) diff --git a/tests/regression/d3q19-extra/serial-ah01-125.inp b/tests/regression/d3q19-extra/serial-ah01-125.inp index 55d397dd5..04c9703b1 100644 --- a/tests/regression/d3q19-extra/serial-ah01-125.inp +++ b/tests/regression/d3q19-extra/serial-ah01-125.inp @@ -54,7 +54,6 @@ colloid_gravity 0.0_0.0_0.0 # ############################################################################### -boundary_walls_on no periodicity 1_1_1 ############################################################################### diff --git a/tests/regression/d3q19-extra/serial-auto-c01.inp b/tests/regression/d3q19-extra/serial-auto-c01.inp index 43834dc34..7855ac2f8 100644 --- a/tests/regression/d3q19-extra/serial-auto-c01.inp +++ b/tests/regression/d3q19-extra/serial-auto-c01.inp @@ -50,7 +50,6 @@ colloid_gravity 0.0_0.0_0.0 # ############################################################################### -boundary_walls_on no periodicity 1_1_1 ############################################################################### diff --git a/tests/regression/d3q19-extra/serial-auto-c02.inp b/tests/regression/d3q19-extra/serial-auto-c02.inp index ad926e47d..f25f4d0cb 100644 --- a/tests/regression/d3q19-extra/serial-auto-c02.inp +++ b/tests/regression/d3q19-extra/serial-auto-c02.inp @@ -50,7 +50,6 @@ colloid_gravity 0.0_0.0_0.0 # ############################################################################### -boundary_walls_on no periodicity 1_1_1 ############################################################################### diff --git a/tests/regression/d3q19-extra/serial-auto-c03.inp b/tests/regression/d3q19-extra/serial-auto-c03.inp index cec5f197d..919db7412 100644 --- a/tests/regression/d3q19-extra/serial-auto-c03.inp +++ b/tests/regression/d3q19-extra/serial-auto-c03.inp @@ -50,7 +50,6 @@ colloid_rebuild_freq 1 # ############################################################################### -boundary_walls_on no periodicity 1_1_1 ############################################################################### diff --git a/tests/regression/d3q19-extra/serial-auto-c04.inp b/tests/regression/d3q19-extra/serial-auto-c04.inp index c386cc123..11a6b0cfa 100644 --- a/tests/regression/d3q19-extra/serial-auto-c04.inp +++ b/tests/regression/d3q19-extra/serial-auto-c04.inp @@ -50,7 +50,6 @@ colloid_rebuild_freq 10 # ############################################################################### -boundary_walls_on no periodicity 1_1_1 ############################################################################### From 15089b89aa12afbf92b70b765b09161c04bf192b Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Sun, 28 Nov 2021 19:31:51 +0000 Subject: [PATCH 059/117] Remove tedious round-of failure --- tests/regression/d3q19-extra/serial-auto-c01.log | 2 +- tests/regression/d3q19-extra/serial-auto-c02.log | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/regression/d3q19-extra/serial-auto-c01.log b/tests/regression/d3q19-extra/serial-auto-c01.log index 318f7b3cb..229876b5d 100644 --- a/tests/regression/d3q19-extra/serial-auto-c01.log +++ b/tests/regression/d3q19-extra/serial-auto-c01.log @@ -85,7 +85,7 @@ Scalars - total mean variance min max Momentum - x y z [total ] 2.2158700e+00 0.0000000e+00 0.0000000e+00 -[fluid ] 3.6371878e-12 0.0000000e+00 0.0000000e+00 +[fluid ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 [colloids] 2.2158700e+00 0.0000000e+00 0.0000000e+00 Starting time step loop. diff --git a/tests/regression/d3q19-extra/serial-auto-c02.log b/tests/regression/d3q19-extra/serial-auto-c02.log index 32ec371a0..88cce079d 100644 --- a/tests/regression/d3q19-extra/serial-auto-c02.log +++ b/tests/regression/d3q19-extra/serial-auto-c02.log @@ -85,7 +85,7 @@ Scalars - total mean variance min max Momentum - x y z [total ] 2.2158700e+00 0.0000000e+00 0.0000000e+00 -[fluid ] 3.6371878e-12 0.0000000e+00 0.0000000e+00 +[fluid ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 [colloids] 2.2158700e+00 0.0000000e+00 0.0000000e+00 Starting time step loop. From 89a4dc5ec5898b7c5738becfe118c1ef31725614 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Sun, 28 Nov 2021 19:32:14 +0000 Subject: [PATCH 060/117] New tests for symmetric_lb noise --- .../d3q19-extra/serial-spin-lb3.inp | 93 +++++++++++++ .../d3q19-extra/serial-spin-lb3.log | 131 ++++++++++++++++++ .../d3q19-extra/serial-spin-lb4.inp | 93 +++++++++++++ .../d3q19-extra/serial-spin-lb4.log | 131 ++++++++++++++++++ 4 files changed, 448 insertions(+) create mode 100644 tests/regression/d3q19-extra/serial-spin-lb3.inp create mode 100644 tests/regression/d3q19-extra/serial-spin-lb3.log create mode 100644 tests/regression/d3q19-extra/serial-spin-lb4.inp create mode 100644 tests/regression/d3q19-extra/serial-spin-lb4.log diff --git a/tests/regression/d3q19-extra/serial-spin-lb3.inp b/tests/regression/d3q19-extra/serial-spin-lb3.inp new file mode 100644 index 000000000..7a957c2c5 --- /dev/null +++ b/tests/regression/d3q19-extra/serial-spin-lb3.inp @@ -0,0 +1,93 @@ +############################################################################## +# +# Spinodal LB smoke test (+ density fluctuations) +# +# Here the ghost noise is on, and we see that the fluid reaches +# the expected temperature after around 50 time steps. +# +# Note this is doubling as a test of the somewhat separate noise +# implmentation required for the symmetric_lb collision case. +# +############################################################################## + +############################################################################## +# +# Run duration +# +############################################################################### + +N_cycles 50 + +############################################################################## +# +# System +# +############################################################################## + +size 32_32_32 +grid 2_2_2 + +############################################################################## +# +# Fluid parameters +# +############################################################################## + +viscosity 0.0625 + +lb_fluctuations yes +lb_ghost_modes yes +temperature 0.00003333333333333 + +############################################################################## +# +# Free energy parameters +# +############################################################################### + +free_energy symmetric_lb + +A -0.00625 +B 0.00625 +K 0.004 + +phi0 0.0 +phi_initialisation spinodal +mobility 3.75 +fd_gradient_calculation 3d_27pt_fluid + +############################################################################### +# +# Colloid parameters +# +############################################################################### + +colloid_init no_colloids + +############################################################################### +# +# Periodic conditions / boundaries +# +############################################################################### + +boundary_walls 0_0_0 +periodicity 1_1_1 + +############################################################################### +# +# Output frequency and type +# +############################################################################### + +freq_statistics 50 +config_at_end no + +############################################################################### +# +# Miscellaneous +# +# random_seed +ve integer is the random number generator seed +# +############################################################################### + +random_seed 8361235 diff --git a/tests/regression/d3q19-extra/serial-spin-lb3.log b/tests/regression/d3q19-extra/serial-spin-lb3.log new file mode 100644 index 000000000..0ed8119b8 --- /dev/null +++ b/tests/regression/d3q19-extra/serial-spin-lb3.log @@ -0,0 +1,131 @@ +Welcome to Ludwig v0.14.0 (Serial version running on 1 process) +Start time: Sun Nov 28 09:50:53 2021 + +Compiler: + name: Gnu 10.2.0 + version-string: 10.2.0 + +Note assertions via standard C assert() are on. + +Target thread model: OpenMP. +OpenMP threads: 1; maximum number of threads: 8. + +Read 21 user parameters from serial-spin-lb3.inp + +System details +-------------- +System size: 32 32 32 +Decomposition: 1 1 1 +Local domain: 32 32 32 +Periodic: 1 1 1 +Halo nhalo: 1 +Reorder: true +Initialised: 1 + +Free energy details +------------------- + +Symmetric phi^4 free energy selected. + +Parameters: +Bulk parameter A = -6.25000e-03 +Bulk parameter B = 6.25000e-03 +Surface penalty kappa = 4.00000e-03 +Surface tension = 4.71405e-03 +Interfacial width = 1.13137e+00 + +Using full lattice Boltzmann solver for Cahn-Hilliard: +Mobility M = 3.75000e+00 + +System properties +---------------- +Mean fluid density: 1.00000e+00 +Shear viscosity 6.25000e-02 +Bulk viscosity 6.25000e-02 +Temperature 3.33333e-05 +External body force density 0.00000e+00 0.00000e+00 0.00000e+00 +External E-field amplitude 0.00000e+00 0.00000e+00 0.00000e+00 +External E-field frequency 0.00000e+00 +External magnetic field 0.00000e+00 0.00000e+00 0.00000e+00 + +Lattice Boltzmann distributions +------------------------------- +Model: d3q19 +SIMD vector len: 1 +Number of sets: 2 +Halo type: full +Input format: binary +Output format: binary +I/O grid: 1 1 1 + +Lattice Boltzmann collision +--------------------------- +Relaxation time scheme: M10 +Hydrodynamic modes: on +Ghost modes: on +Isothermal fluctuations: on +Shear relaxation time: 6.87500e-01 +Bulk relaxation time: 6.87500e-01 +Ghost relaxation time: 1.00000e+00 +[User ] Random number seed: 8361235 + +Hydrodynamics +------------- +Hydrodynamics: on + +Order parameter I/O +------------------- +Order parameter I/O format: +I/O decomposition: 1 1 1 +Initialising phi for spinodal +Gradient calculation: 3d_27pt_fluid +Initial conditions. + +Scalars - total mean variance min max +[rho] 32768.00 1.00000000000 2.2204460e-16 1.00000000000 1.00000000000 +[phi] -5.9892076e+00 -1.8277611e-04 8.3100414e-04 -4.9989121e-02 4.9997941e-02 + +Momentum - x y z +[total ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 +[fluid ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 + +Starting time step loop. + +Scalars - total mean variance min max +[rho] 32768.00 1.00000000000 9.9597356e-05 0.95230376702 1.04087652512 +[phi] -5.9892076e+00 -1.8277611e-04 3.6853965e-04 -4.7965671e-02 4.5798476e-02 + +Free energy density - timestep total fluid +[fed] 50 -9.8117268521e-07 -9.8117268521e-07 + +Momentum - x y z +[total ] 4.8055310e-14 -1.9560742e-14 -4.0339260e-14 +[fluid ] 4.8055310e-14 -1.9560742e-14 -4.0339260e-14 + +Velocity - x y z +[minimum ] -2.2498220e-02 -2.2167032e-02 -2.4382195e-02 +[maximum ] 2.5669501e-02 2.4492983e-02 2.5988498e-02 + +Isothermal fluctuations +[eqipart.] 3.3924567e-05 3.3410483e-05 3.2749954e-05 +[measd/kT] 1.0008500e-04 1.0000000e-04 + +Completed cycle 50 + +Timer resolution: 1e-06 second + +Timer statistics + Section: tmin tmax total + Total: 3.942 3.942 3.942 3.941857 (1 call) + Time step loop: 0.076 0.079 3.842 0.076850 (50 calls) + Propagation: 0.016 0.017 0.815 0.016303 (50 calls) + Propagtn (krnl) : 0.016 0.017 0.815 0.016299 (50 calls) + Collision: 0.040 0.041 2.027 0.040546 (50 calls) + Collision (krnl) : 0.040 0.041 2.027 0.040542 (50 calls) + Lattice halos: 0.004 0.005 0.192 0.003834 (50 calls) + phi gradients: 0.015 0.016 0.772 0.015430 (50 calls) + phi halos: 0.000 0.000 0.009 0.000190 (50 calls) + BBL: 0.000 0.000 0.000 0.000001 (50 calls) + Free1: 0.000 0.044 0.045 0.000890 (50 calls) +End time: Sun Nov 28 09:50:57 2021 +Ludwig finished normally. diff --git a/tests/regression/d3q19-extra/serial-spin-lb4.inp b/tests/regression/d3q19-extra/serial-spin-lb4.inp new file mode 100644 index 000000000..0f386d8a0 --- /dev/null +++ b/tests/regression/d3q19-extra/serial-spin-lb4.inp @@ -0,0 +1,93 @@ +############################################################################## +# +# Spinodal LB smoke test (+ density fluctuations) +# +# Here the ghost noise is off and while the equipartition is +# reasonable, the measured temperature will reach only about +# 40% of the expected value (however long one runs for). +# +# cf serial-spin-lb3.inp +# +############################################################################## + +############################################################################## +# +# Run duration +# +############################################################################### + +N_cycles 50 + +############################################################################## +# +# System +# +############################################################################## + +size 32_32_32 +grid 2_2_2 + +############################################################################## +# +# Fluid parameters +# +############################################################################## + +viscosity 0.0625 + +lb_fluctuations yes +lb_ghost_modes off +temperature 0.00003333333333333 + +############################################################################## +# +# Free energy parameters +# +############################################################################### + +free_energy symmetric_lb + +A -0.00625 +B 0.00625 +K 0.004 + +phi0 0.0 +phi_initialisation spinodal +mobility 3.75 +fd_gradient_calculation 3d_27pt_fluid + +############################################################################### +# +# Colloid parameters +# +############################################################################### + +colloid_init no_colloids + +############################################################################### +# +# Periodic conditions / boundaries +# +############################################################################### + +boundary_walls 0_0_0 +periodicity 1_1_1 + +############################################################################### +# +# Output frequency and type +# +############################################################################### + +freq_statistics 50 +config_at_end no + +############################################################################### +# +# Miscellaneous +# +# random_seed +ve integer is the random number generator seed +# +############################################################################### + +random_seed 8361235 diff --git a/tests/regression/d3q19-extra/serial-spin-lb4.log b/tests/regression/d3q19-extra/serial-spin-lb4.log new file mode 100644 index 000000000..2125b996e --- /dev/null +++ b/tests/regression/d3q19-extra/serial-spin-lb4.log @@ -0,0 +1,131 @@ +Welcome to Ludwig v0.14.0 (Serial version running on 1 process) +Start time: Sun Nov 28 09:51:00 2021 + +Compiler: + name: Gnu 10.2.0 + version-string: 10.2.0 + +Note assertions via standard C assert() are on. + +Target thread model: OpenMP. +OpenMP threads: 1; maximum number of threads: 8. + +Read 21 user parameters from serial-spin-lb4.inp + +System details +-------------- +System size: 32 32 32 +Decomposition: 1 1 1 +Local domain: 32 32 32 +Periodic: 1 1 1 +Halo nhalo: 1 +Reorder: true +Initialised: 1 + +Free energy details +------------------- + +Symmetric phi^4 free energy selected. + +Parameters: +Bulk parameter A = -6.25000e-03 +Bulk parameter B = 6.25000e-03 +Surface penalty kappa = 4.00000e-03 +Surface tension = 4.71405e-03 +Interfacial width = 1.13137e+00 + +Using full lattice Boltzmann solver for Cahn-Hilliard: +Mobility M = 3.75000e+00 + +System properties +---------------- +Mean fluid density: 1.00000e+00 +Shear viscosity 6.25000e-02 +Bulk viscosity 6.25000e-02 +Temperature 3.33333e-05 +External body force density 0.00000e+00 0.00000e+00 0.00000e+00 +External E-field amplitude 0.00000e+00 0.00000e+00 0.00000e+00 +External E-field frequency 0.00000e+00 +External magnetic field 0.00000e+00 0.00000e+00 0.00000e+00 + +Lattice Boltzmann distributions +------------------------------- +Model: d3q19 +SIMD vector len: 1 +Number of sets: 2 +Halo type: full +Input format: binary +Output format: binary +I/O grid: 1 1 1 + +Lattice Boltzmann collision +--------------------------- +Relaxation time scheme: M10 +Hydrodynamic modes: on +Ghost modes: off +Isothermal fluctuations: on +Shear relaxation time: 6.87500e-01 +Bulk relaxation time: 6.87500e-01 +Ghost relaxation time: 1.00000e+00 +[User ] Random number seed: 8361235 + +Hydrodynamics +------------- +Hydrodynamics: on + +Order parameter I/O +------------------- +Order parameter I/O format: +I/O decomposition: 1 1 1 +Initialising phi for spinodal +Gradient calculation: 3d_27pt_fluid +Initial conditions. + +Scalars - total mean variance min max +[rho] 32768.00 1.00000000000 2.2204460e-16 1.00000000000 1.00000000000 +[phi] -5.9892076e+00 -1.8277611e-04 8.3100414e-04 -4.9989121e-02 4.9997941e-02 + +Momentum - x y z +[total ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 +[fluid ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 + +Starting time step loop. + +Scalars - total mean variance min max +[rho] 32768.00 1.00000000000 4.4472565e-05 0.97222445743 1.03062534838 +[phi] -5.9892076e+00 -1.8277611e-04 3.6967262e-04 -4.8035217e-02 4.5935574e-02 + +Free energy density - timestep total fluid +[fed] 50 -9.8415186845e-07 -9.8415186845e-07 + +Momentum - x y z +[total ] -2.1035257e-14 -2.3689384e-14 -2.0754232e-14 +[fluid ] -2.1035257e-14 -2.3689384e-14 -2.0754232e-14 + +Velocity - x y z +[minimum ] -1.5523149e-02 -1.6441568e-02 -1.7255303e-02 +[maximum ] 1.4837300e-02 1.5602961e-02 1.4439107e-02 + +Isothermal fluctuations +[eqipart.] 1.3442637e-05 1.3529021e-05 1.3636680e-05 +[measd/kT] 4.0608338e-05 1.0000000e-04 + +Completed cycle 50 + +Timer resolution: 1e-06 second + +Timer statistics + Section: tmin tmax total + Total: 3.864 3.864 3.864 3.864059 (1 call) + Time step loop: 0.075 0.079 3.765 0.075298 (50 calls) + Propagation: 0.016 0.017 0.815 0.016301 (50 calls) + Propagtn (krnl) : 0.016 0.017 0.815 0.016297 (50 calls) + Collision: 0.039 0.041 1.941 0.038821 (50 calls) + Collision (krnl) : 0.039 0.041 1.941 0.038817 (50 calls) + Lattice halos: 0.004 0.005 0.198 0.003956 (50 calls) + phi gradients: 0.015 0.018 0.774 0.015485 (50 calls) + phi halos: 0.000 0.000 0.010 0.000192 (50 calls) + BBL: 0.000 0.000 0.000 0.000001 (50 calls) + Free1: 0.000 0.045 0.045 0.000905 (50 calls) +End time: Sun Nov 28 09:51:04 2021 +Ludwig finished normally. From 222024448db379fea1be1a5a476738823b7ed7aa Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Sun, 28 Nov 2021 19:34:25 +0000 Subject: [PATCH 061/117] Update for re-ordered basis modes and removel of normaliser macro --- tests/regression/d3q15/serial-auto-c02.log | 54 +++++++++++----------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/tests/regression/d3q15/serial-auto-c02.log b/tests/regression/d3q15/serial-auto-c02.log index 202fe2110..73b463f1d 100644 --- a/tests/regression/d3q15/serial-auto-c02.log +++ b/tests/regression/d3q15/serial-auto-c02.log @@ -1,13 +1,14 @@ -Welcome to Ludwig v0.12.0 (Serial version running on 1 process) +Welcome to Ludwig v0.14.0 (Serial version running on 1 process) +Start time: Sun Nov 28 14:32:35 2021 Compiler: - name: Gnu 8.3.0 - version-string: 8.3.0 + name: Gnu 10.2.0 + version-string: 10.2.0 Note assertions via standard C assert() are on. Target thread model: OpenMP. -OpenMP threads: 1; maximum number of threads: 8. +OpenMP threads: 4; maximum number of threads: 8. Read 19 user parameters from serial-auto-c02.inp @@ -99,24 +100,24 @@ Starting time step loop. Particle statistics: Colloid velocities - x y z -[minimum ] 1.5741429e-03 3.2021352e-04 5.3377305e-05 -[maximum ] 1.5741429e-03 3.2021352e-04 5.3377305e-05 +[minimum ] 1.4881073e-03 6.7332719e-04 3.6013312e-04 +[maximum ] 1.4881073e-03 6.7332719e-04 3.6013312e-04 Scalars - total mean variance min max -[rho] 262091.00 1.00000000000 6.3703576e-05 0.96213689906 1.03959549410 +[rho] 262091.00 1.00000000000 6.4064446e-05 0.96202674719 1.03595590460 Momentum - x y z -[total ] 2.2158700e+00 9.6530423e-14 1.1303458e-13 -[fluid ] 2.1514140e+00 -2.1867298e-02 2.7869905e-03 -[colloids] 6.4456004e-02 2.1867298e-02 -2.7869905e-03 +[total ] 2.2158700e+00 -9.6939817e-14 -1.2368492e-13 +[fluid ] 2.1487449e+00 -1.1155369e-02 3.4718117e-03 +[colloids] 6.7125115e-02 1.1155369e-02 -3.4718117e-03 Velocity - x y z -[minimum ] -2.1751566e-02 -1.9954185e-02 -2.1269819e-02 -[maximum ] 2.0767195e-02 2.0259589e-02 2.0499669e-02 +[minimum ] -2.1568802e-02 -2.1780724e-02 -1.9997759e-02 +[maximum ] 1.9986172e-02 2.1046628e-02 2.0458309e-02 Isothermal fluctuations -[eqipart.] 2.1320218e-05 2.1241282e-05 2.1225165e-05 -[measd/kT] 6.3786664e-05 6.3999990e-05 +[eqipart.] 2.1287978e-05 2.1267119e-05 2.1190731e-05 +[measd/kT] 6.3745828e-05 6.3999990e-05 Completed cycle 40 @@ -124,19 +125,20 @@ Timer resolution: 1e-06 second Timer statistics Section: tmin tmax total - Total: 10.340 10.340 10.340 10.340438 (1 call) - Time step loop: 0.247 0.253 9.952 0.248801 (40 calls) - Propagation: 0.050 0.052 2.023 0.050571 (40 calls) - Propagtn (krnl) : 0.050 0.052 2.023 0.050569 (40 calls) - Collision: 0.168 0.170 6.738 0.168448 (40 calls) - Collision (krnl) : 0.168 0.170 6.738 0.168442 (40 calls) - Lattice halos: 0.006 0.008 0.495 0.006184 (80 calls) + Total: 3.603 3.603 3.603 3.602769 (1 call) + Time step loop: 0.076 0.087 3.100 0.077512 (40 calls) + Propagation: 0.012 0.017 0.510 0.012755 (40 calls) + Propagtn (krnl) : 0.012 0.017 0.510 0.012749 (40 calls) + Collision: 0.050 0.055 2.029 0.050728 (40 calls) + Collision (krnl) : 0.050 0.055 2.029 0.050713 (40 calls) + Lattice halos: 0.002 0.005 0.204 0.002555 (80 calls) phi gradients: 0.000 0.000 0.000 0.000000 (40 calls) - Forces: 0.000 0.000 0.002 0.000045 (40 calls) - Rebuild: 0.005 0.006 0.201 0.005037 (40 calls) - BBL: 0.006 0.007 0.249 0.006232 (40 calls) - Particle halos: 0.000 0.000 0.006 0.000161 (40 calls) + Forces: 0.000 0.000 0.002 0.000051 (40 calls) + Rebuild: 0.005 0.006 0.198 0.004948 (40 calls) + BBL: 0.002 0.002 0.080 0.001993 (40 calls) + Particle halos: 0.000 0.000 0.012 0.000304 (40 calls) Force calculation: 0.000 0.000 0.000 0.000000 (40 calls) phi update: 0.000 0.000 0.000 0.000000 (40 calls) - Free1: 0.000 0.205 0.205 0.001707 (120 calls) + Free1: 0.000 0.257 0.258 0.002146 (120 calls) +End time: Sun Nov 28 14:32:38 2021 Ludwig finished normally. From 048b6bdfa327a97a444eb546c7c7e15e844af960 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Sun, 28 Nov 2021 19:36:35 +0000 Subject: [PATCH 062/117] Correct d3q27 draft basis --- src/lb_d3q27.c | 131 +++++++++++++++++++++++++++++++++++++++++++++++++ src/lb_d3q27.h | 14 +++--- 2 files changed, 137 insertions(+), 8 deletions(-) diff --git a/src/lb_d3q27.c b/src/lb_d3q27.c index ded3328c5..6c98c6587 100644 --- a/src/lb_d3q27.c +++ b/src/lb_d3q27.c @@ -20,6 +20,8 @@ #include "lb_d3q27.h" +static int lb_d3q27_matrix_ma(lb_model_t * model); + /***************************************************************************** * * lb_d3q27_create @@ -35,10 +37,14 @@ int lb_d3q27_create(lb_model_t * model) { model->nvel = NVEL_D3Q27; model->cv = (int8_t (*)[3]) calloc(NVEL_D3Q27, sizeof(int8_t[3])); model->wv = (double *) calloc(NVEL_D3Q27, sizeof(double)); + model->na = (double *) calloc(NVEL_D3Q27, sizeof(double)); + model->ma = (double **) calloc(NVEL_D3Q27, sizeof(double *)); model->cs2 = 1.0/3.0; if (model->cv == NULL) goto err; if (model->wv == NULL) goto err; + if (model->na == NULL) goto err; + if (model->ma == NULL) goto err; { LB_CV_D3Q27(cv); @@ -52,6 +58,27 @@ int lb_d3q27_create(lb_model_t * model) { } } + /* Matrix elements */ + + model->ma[0] = (double *) calloc(NVEL_D3Q27*NVEL_D3Q27, sizeof(double)); + if (model->ma[0] == NULL) goto err; + + for (int p = 1; p < model->nvel; p++) { + model->ma[p] = model->ma[p-1] + NVEL_D3Q27; + } + + lb_d3q27_matrix_ma(model); + + /* Normalisers: Compute weighted inner product ... */ + + for (int p = 0; p < model->nvel; p++) { + double sum = 0.0; + for (int ia = 0; ia < model->nvel; ia++) { + sum += model->wv[ia]*model->ma[p][ia]*model->ma[p][ia]; + } + model->na[p] = 1.0/sum; + } + return 0; err: @@ -60,3 +87,107 @@ int lb_d3q27_create(lb_model_t * model) { return -1; } + +/***************************************************************************** + * + * lb_d3q27_matrix_ma + * + * Hydrodynamic modes: + * + * Being zeroth, first and second order Hermite polynomials in + * three diemnsions: + * + * [0] rho H_i 1 + * [1] rho u_x H_ix rho c_ix + * [2] rho u_y H_iy rho c_iy + * [3] rho u_z H_iy rho c_iz + * [4] S_xx H_ixx c_ix c_ix - c_s^2 + * [5] S_xy H_ixy c_ix c_iy + * [6] S_xz H_ixz c_ix c_iz + * [7] S_yy H_iyy c_iy c_iy - c_s^2 + * [8] S_yz H_iyz c_iy c_iz + * [9] S_zz H_izz c_iz c_iz - c_s^2 + * + * Non-hydrodynamic modes: + * + * Six 3rd order polynomials H_ixxy, etc + * [10] H_ixxy (c_ix c_ix - cs2) c_iy + * [11] H_ixxz (c_ix c_ix - cs2) c_iz + * [12] H_iyyx (c_iy c_iy - cs2) c_ix + * [13] H_iyyz ... + * [14] H_izzx ... + * [15] H_izzy ... + * + * One 3rd order polynomial + * [16] H_ixyz c_ix c_iy c_iz + * + * Three 4th order polynomials H_ixxyy, etc + * [17] H_ixxyy (c_ix c_ix - cs2)*(c_iy c_iy - cs2) + * [18] H_iyyzz (c_iy c_iy - cs2)*(c_iz c_iz - cs2) + * [19] H_izzxx ... + * + * Four 4th order polynomials H_ixxyz, etc (ORTHOGONALISED against H_i) + * [20] H_ixxyz c_ix c_ix c_iy c_iz - cs2 c_iy c_iz - cs4 + * [21] H_iyyzx ... + * [22] H_izzxy ... + * + * Three 5th order polynomials H_ixxyyz, etc + * [23] H_ixxyyz H_ixxyy c_iz + * [24] H_iyyzzx H_iyyzz c_ix + * [25] H_izzxxy H_izzxx c_iy + * + * Finally, one sixth order polynomial + * [26] H_ixxyyzz H_ixxyy (c_iz c_iz - cs2) + * + * + * See, e.g., Coreixas et al. PRE 96 033306 (2017) for a broad + * description of construction of models from Hermite tensors. + * + *****************************************************************************/ + +static int lb_d3q27_matrix_ma(lb_model_t * model) { + + assert(model); + assert(model->ma); + assert(model->ma[0]); + + for (int p = 0; p < model->nvel; p++) { + + double cs2 = model->cs2; + + double rho = 1.0; + double cx = rho*model->cv[p][X]; + double cy = rho*model->cv[p][Y]; + double cz = rho*model->cv[p][Z]; + + model->ma[ 0][p] = rho; + model->ma[ 1][p] = cx; + model->ma[ 2][p] = cy; + model->ma[ 3][p] = cz; + model->ma[ 4][p] = cx*cx - cs2; + model->ma[ 5][p] = cx*cy; + model->ma[ 6][p] = cx*cz; + model->ma[ 7][p] = cy*cy - cs2; + model->ma[ 8][p] = cy*cz; + model->ma[ 9][p] = cz*cz - cs2; + model->ma[10][p] = 3.0*(cx*cx - cs2)*cy; + model->ma[11][p] = 3.0*(cx*cx - cs2)*cz; + model->ma[12][p] = 3.0*(cy*cy - cs2)*cz; + model->ma[13][p] = 3.0*(cy*cy - cs2)*cx; + model->ma[14][p] = 3.0*(cz*cz - cs2)*cx; + model->ma[15][p] = 3.0*(cz*cz - cs2)*cy; + model->ma[16][p] = cx*cy*cz; + model->ma[17][p] = 9.0*(cx*cx - cs2)*(cy*cy - cs2); + model->ma[18][p] = 9.0*(cy*cy - cs2)*(cz*cz - cs2); + model->ma[19][p] = 9.0*(cz*cz - cs2)*(cx*cx - cs2); + model->ma[20][p] = 9.0*(cx*cx*cy*cz - cs2*cy*cz + cs2*cs2) - 1.0; + model->ma[21][p] = 9.0*(cy*cy*cz*cx - cs2*cz*cx + cs2*cs2) - 1.0; + model->ma[22][p] = 9.0*(cz*cz*cx*cy - cs2*cx*cy + cs2*cs2) - 1.0; + model->ma[23][p] = 9.0*(cx*cx - cs2)*(cy*cy - cs2)*cz; + model->ma[24][p] = 9.0*(cy*cy - cs2)*(cz*cz - cs2)*cx; + model->ma[25][p] = 9.0*(cz*cz - cs2)*(cx*cx - cs2)*cy; + model->ma[26][p] = 27.0*(cx*cx - cs2)*(cy*cy - cs2)*(cz*cz - cs2); + } + + return 0; +} diff --git a/src/lb_d3q27.h b/src/lb_d3q27.h index 387040af7..57ba4da65 100644 --- a/src/lb_d3q27.h +++ b/src/lb_d3q27.h @@ -20,7 +20,7 @@ #include "lb_model.h" -/* Velocity set, weights. */ +/* Velocity set and weights. */ enum {NVEL_D3Q27 = 27}; @@ -31,16 +31,14 @@ enum {NVEL_D3Q27 = 27}; { 0, 1,-1}, { 0, 1, 0}, { 0, 1, 1}, { 1,-1,-1}, { 1,-1, 0}, { 1,-1, 1}, \ { 1, 0,-1}, { 1, 0, 0}, { 1, 0, 1}, { 1, 1,-1}, { 1, 1, 0}, { 1, 1, 1}}; -/* Weights: |0| = 64 |1| = 16 |2| = 1 |3| = 4. All / 216 */ +/* Weights: |0| = 64 |1| = 16 |2| = 4 |3| = 1. All over 216. */ #define LB_WEIGHTS_D3Q27(wv) const double wv[NVEL_D3Q27] = { 64.0/216.0, \ - 4.0/216.0, 1.0/216.0, 4.0/216.0, 1.0/216.0, 16.0/216.0, 1.0/216.0, \ - 4.0/216.0, 1.0/216.0, 4.0/216.0, 1.0/216.0, 16.0/216.0, 1.0/216.0, \ + 1.0/216.0, 4.0/216.0, 1.0/216.0, 4.0/216.0, 16.0/216.0, 4.0/216.0, \ + 1.0/216.0, 4.0/216.0, 1.0/216.0, 4.0/216.0, 16.0/216.0, 4.0/216.0, \ 16.0/216.0, 16.0/216.0, \ - 1.0/216.0, 16.0/216.0, 1.0/216.0, 4.0/216.0, 1.0/216.0, 4.0/216.0, \ - 1.0/216.0, 16.0/216.0, 1.0/216.0, 4.0/216.0, 1.0/216.0, 4.0/216.0}; - -/* Normalisers TBC */ + 4.0/216.0, 16.0/216.0, 4.0/216.0, 1.0/216.0, 4.0/216.0, 1.0/216.0, \ + 4.0/216.0, 16.0/216.0, 4.0/216.0, 1.0/216.0, 4.0/216.0, 1.0/216.0}; int lb_d3q27_create(lb_model_t * model); From 3b62c6f9532f66f7424e647534788da67423c4a3 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Sun, 28 Nov 2021 19:38:09 +0000 Subject: [PATCH 063/117] Compute normalisers at runtime; write basis out in terms of polynomials --- src/lb_d2q9.c | 76 ++++++++++++++++++++++++++++++++++++++------------- src/lb_d2q9.h | 22 ++++++--------- 2 files changed, 65 insertions(+), 33 deletions(-) diff --git a/src/lb_d2q9.c b/src/lb_d2q9.c index 241ec013d..bc27730ad 100644 --- a/src/lb_d2q9.c +++ b/src/lb_d2q9.c @@ -49,14 +49,12 @@ int lb_d2q9_create(lb_model_t * model) { { LB_CV_D2Q9(cv); LB_WEIGHTS_D2Q9(wv); - LB_NORMALISERS_D2Q9(na); for (int p = 0; p < model->nvel; p++) { for (int ia = 0; ia < 3; ia++) { model->cv[p][ia] = cv[p][ia]; } model->wv[p] = wv[p]; - model->na[p] = na[p]; } } @@ -70,6 +68,16 @@ int lb_d2q9_create(lb_model_t * model) { lb_d2q9_matrix_ma(model); + /* Normalisers */ + + for (int p = 0; p < model->nvel; p++) { + double sum = 0.0; + for (int ia = 0; ia < model->nvel; ia++) { + sum += model->wv[ia]*model->ma[p][ia]*model->ma[p][ia]; + } + model->na[p] = 1.0/sum; + } + return 0; err: @@ -83,13 +91,42 @@ int lb_d2q9_create(lb_model_t * model) { * * lb_d2q9_matrix_ma * - * Hydrodynamic modes as usual 1 + NDIM + NDIM*(NDIM+1)/2. + * The rows of the transformation matrix are as follows. + * + * Hydrodynamic modes + * + * These correspond to zeroth, first and second order Hermite polynomials + * in two dimensions: + * + * [0] rho H_i 1 + * [1] rho u_x H_ix rho c_ix + * [2] rho u_y H_iy rho c_iy + * [3] S_xx H_ixx c_ix c_ix - c_s^2 + * [4] S_xy H_ixy c_ix c_iy + * [5] S_yy H_iyy c_iy c_iy - c_s^2 * - * One scalar ghost mode, plus associated vector + * Non-hydrodynamic modes (two third order, and one fourth order polynomial) * - * chi = 1/2 (9c^4 - 15c^2 + 2) eigenvector ma[6] - * jchi_x = chi c_x eigenvector ma[7] - * jchi_y = ch1 c_y eigenvector ma[8] + * [7] chi c_x H_iyyx (c_iy c_iy - c_s^2) c_ix + * [8] chi c_y H_ixxy (c_ix c_ix - c_s^2) c_iy + * [6] chi H_ixxyy (c_ix c_ix - c_s^2)(c_iy c_iy - c_s^2) + * + * Historically, this basis was introduced for the purposes of consistent + * isothermal fluctuations see Adhikari et al. 2005 following the a mode + * description e.g., d'Humieres et al. + * Originally, the ghost modes were written in slightly different form + * (cf. Dellar 2002), one scalar and one vector mode: + * + * [6] chi = 1/2 (9c^4 - 15c^2 + 2) + * [7] jchi_x = chi c_ix + * [8] jchi_y = ch1 c_iy + * + * with c^2 = c_ix*c_ix + c_iy*c_iy. These are the same as those above in the + * discrete picture (see note on order below). + * + * For a more recent analysis of basis sets and their expansion in + * terms of the Hermite tensors, see, e.g., Coreixas et al. + * PRE 96 033306 (2017). * *****************************************************************************/ @@ -105,25 +142,26 @@ static int lb_d2q9_matrix_ma(lb_model_t * model) { assert(model->cv[p][Z] == 0); + double cs2 = model->cs2; + double rho = 1.0; double cx = rho*model->cv[p][X]; double cy = rho*model->cv[p][Y]; - double sxx = cx*cx - model->cs2; - double sxy = cx*cy; - double syy = cy*cy - model->cs2; - - double cs2 = cx*cx + cy*cy; - double chi = 0.5*(9.0*cs2*cs2 - 15.0*cs2 + 2); model->ma[0][p] = rho; model->ma[1][p] = cx; model->ma[2][p] = cy; - model->ma[3][p] = sxx; - model->ma[4][p] = sxy; - model->ma[5][p] = syy; - model->ma[6][p] = chi; - model->ma[7][p] = chi*cx; - model->ma[8][p] = chi*cy; + model->ma[3][p] = cx*cx - cs2; + model->ma[4][p] = cx*cy; + model->ma[5][p] = cy*cy - cs2; + + /* This labelling 7,8,6 is retained to keep results relating to + * fluctuations numerically the same as those in the original + * description discussed above. */ + + model->ma[7][p] = 6.0*(cy*cy - cs2)*cx; + model->ma[8][p] = 6.0*(cx*cx - cs2)*cy; + model->ma[6][p] = 9.0*(cx*cx - cs2)*(cy*cy - cs2); } return 0; diff --git a/src/lb_d2q9.h b/src/lb_d2q9.h index b993ad9b8..e3812d7ac 100644 --- a/src/lb_d2q9.h +++ b/src/lb_d2q9.h @@ -19,26 +19,20 @@ #include "lb_model.h" -/* Velocity set, weights, and normalisers. */ +/* Velocity set and weights. */ enum {NVEL_D2Q9 = 9}; -#define LB_CV_D2Q9(cv) const int8_t cv[NVEL_D2Q9][3] = { \ - { 0, 0, 0}, \ - { 1, 1, 0}, { 1, 0, 0}, \ - { 1, -1, 0}, { 0, 1, 0}, \ - { 0, -1, 0}, {-1, 1, 0}, \ - {-1, 0, 0}, {-1, -1, 0}}; +#define LB_CV_D2Q9(cv) const int8_t cv[NVEL_D2Q9][3] = { \ + { 0, 0, 0}, \ + { 1, 1, 0}, { 1, 0, 0}, { 1, -1, 0}, { 0, 1, 0}, \ + { 0, -1, 0}, {-1, 1, 0}, {-1, 0, 0}, {-1, -1, 0}}; -#define LB_WEIGHTS_D2Q9(wv) const double wv[NVEL_D2Q9] = { \ - 16.0/36.0, \ - 1.0/36.0, 4.0/36.0, 1.0/36.0, 4.0/36.0, \ +#define LB_WEIGHTS_D2Q9(wv) const double wv[NVEL_D2Q9] = { \ + 16.0/36.0, \ + 1.0/36.0, 4.0/36.0, 1.0/36.0, 4.0/36.0, \ 4.0/36.0, 1.0/36.0, 4.0/36.0, 1.0/36.0}; -#define LB_NORMALISERS_D2Q9(norm) const double norm[NVEL_D2Q9] = { \ - 1.0, 3.0, 3.0, 9.0/2.0, 9.0, 9.0/2.0, 1.0/4.0, 3.0/8.0, 3.0/8.0}; - - int lb_d2q9_create(lb_model_t * model); #endif From ab6b989652e6a9ca162e71458094436e39ac8d45 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Sun, 28 Nov 2021 19:38:53 +0000 Subject: [PATCH 064/117] Re-organise basis; compute normalisers at run time --- src/lb_d3q15.c | 96 +++++++++++++++++++++++++++++++++++--------------- src/lb_d3q15.h | 7 +--- 2 files changed, 69 insertions(+), 34 deletions(-) diff --git a/src/lb_d3q15.c b/src/lb_d3q15.c index e29c239b5..26808b04f 100644 --- a/src/lb_d3q15.c +++ b/src/lb_d3q15.c @@ -50,14 +50,12 @@ int lb_d3q15_create(lb_model_t * model) { { LB_CV_D3Q15(cv); LB_WEIGHTS_D3Q15(wv); - LB_NORMALISERS_D3Q15(na); for (int p = 0; p < model->nvel; p++) { for (int ia = 0; ia < 3; ia++) { model->cv[p][ia] = cv[p][ia]; } model->wv[p] = wv[p]; - model->na[p] = na[p]; } } @@ -71,6 +69,16 @@ int lb_d3q15_create(lb_model_t * model) { lb_d3q15_matrix_ma(model); + /* Normalisers */ + + for (int p = 0; p < model->nvel; p++) { + double sum = 0.0; + for(int ia = 0; ia < model->nvel; ia++) { + sum += model->wv[ia]*model->ma[p][ia]*model->ma[p][ia]; + } + model->na[p] = 1.0/sum; + } + return 0; err: @@ -84,12 +92,52 @@ int lb_d3q15_create(lb_model_t * model) { * * lb_d3q15_matrix_ma * - * Hydrodynamic modes as usual 1 + NDIM + NDIM*(NDIM+1)/2 + * Hydrodynamic modes + * + * These correspond to zeroth, first and second order Hermite polynomials + * in three dimensions: + * + * [0] rho H_i 1 + * [1] rho u_x H_ix rho c_ix + * [2] rho u_y H_iy rho c_iy + * [3] rho u_z H_iz rho c_iz + * [4] S_xx H_ixx c_ix c_ix - cs^2 + * [5] S_xy H_ixy c_ix c_iy + * [6] S_xz H_ixz c_ix c_iz + * [7] S_yy H_iyy c_iy c_iy - cs^2 + * [8] S_yz H_iyz c_iy c_iz + * [9] S_zz H_izz c_iz c_iz - cs^2 + * + * Non-hydrodynamic modes * - * Two scalar ghost modes chi1 mnd chi2 and one vector jchi1: + * One 3rd order polynomial H_ixyz + * Three 3rd order polynomials H_izzx, H_ixxy, H_iyyz + * One 4th order polynomial H_ixxyy (orthogonalised against H_izz) * - * chi1 = 0.5*(-3.0*cs^2*cs^2 + 9.0*cs^2 - 4.0) mode[10] - * chi2 = cx*cy*cz mode[14] + * [10] H_ixyz + * [11] H_izzx + * [12] H_ixxy + * [13] H_iyyz + * [14] H_ixxyy + * + * Note that the third order polynomials H_ixxx etc are not admitted in + * this single speed model. The fourth order polynomial may be replaced + * by H_iyyzz or H_ixxzz (they are all the same when orthogonalised). + * + * This basis was first introduced for purposes of studying isothermal + * fluctuations, see Adhikari et al. 2005. At that time, the + * non-hydrodynamic modes were written slightly differerntly, + * with two scalar ghost modes chi1 and chi2 and one vector: + * + * [10] 0.5*(-3.0*c^2*c^2 + 9.0*c^2 - 4.0) "chi1" + * [11] chi1 c_ix + * [12] ch11 c_iy + * [13] chi1 c_iz + * [14] c_ix c_iy c_iz "chi2" + * + * where c^2 = cx*cx + cy*cy + cz*cz. + * It can be confirmed that these discrete non-hydrodynamic modes are + * the same as those above (to within a factor of -1 for chi1). * *****************************************************************************/ @@ -101,37 +149,29 @@ static int lb_d3q15_matrix_ma(lb_model_t * model) { for (int p = 0; p < model->nvel; p++) { + double cs2 = model->cs2; + double rho = 1.0; double cx = rho*model->cv[p][X]; double cy = rho*model->cv[p][Y]; double cz = rho*model->cv[p][Z]; - double sxx = cx*cx - model->cs2; - double sxy = cx*cy; - double sxz = cx*cz; - double syy = cy*cy - model->cs2; - double syz = cy*cz; - double szz = cz*cz - model->cs2; - - double cs2 = cx*cx + cy*cy + cz*cz; - double chi1 = 0.5*(-3.0*cs2*cs2 + 9.0*cs2 - 4.0); - double chi2 = cx*cy*cz; - model->ma[ 0][p] = rho; model->ma[ 1][p] = cx; model->ma[ 2][p] = cy; model->ma[ 3][p] = cz; - model->ma[ 4][p] = sxx; - model->ma[ 5][p] = sxy; - model->ma[ 6][p] = sxz; - model->ma[ 7][p] = syy; - model->ma[ 8][p] = syz; - model->ma[ 9][p] = szz; - model->ma[10][p] = chi1; - model->ma[11][p] = chi1*cx; - model->ma[12][p] = chi1*cy; - model->ma[13][p] = chi1*cz; - model->ma[14][p] = chi2; + model->ma[ 4][p] = cx*cx - cs2; + model->ma[ 5][p] = cx*cy; + model->ma[ 6][p] = cx*cz; + model->ma[ 7][p] = cy*cy - cs2; + model->ma[ 8][p] = cy*cz; + model->ma[ 9][p] = cz*cz - cs2; + + model->ma[10][p] = cx*cy*cz; + model->ma[11][p] = 3.0*(cz*cz - cs2)*cx; + model->ma[12][p] = 3.0*(cx*cx - cs2)*cy; + model->ma[13][p] = 3.0*(cy*cy - cs2)*cz; + model->ma[14][p] = 9.0*(cx*cx - cs2)*(cy*cy - cs2) - 3.0*(cz*cz - cs2); } return 0; diff --git a/src/lb_d3q15.h b/src/lb_d3q15.h index c1374fca7..4023c5bbc 100644 --- a/src/lb_d3q15.h +++ b/src/lb_d3q15.h @@ -16,7 +16,7 @@ #include "lb_model.h" -/* Velocity set, weights, and normalisers */ +/* Velocity set and weights.*/ enum {NVEL_D3Q15 = 15}; @@ -32,11 +32,6 @@ enum {NVEL_D3Q15 = 15}; 1.0/72.0, 1.0/72.0, 8.0/72.0, 1.0/72.0, 1.0/72.0, 8.0/72.0, 8.0/72.0, \ 8.0/72.0, 8.0/72.0, 1.0/72.0, 1.0/72.0, 8.0/72.0, 1.0/72.0, 1.0/72.0 }; -#define LB_NORMALISERS_D3Q15(norm) const double norm[NVEL_D3Q15] = { \ - 1.0, 3.0, 3.0, 3.0, 9.0/2.0, 9.0, 9.0, 9.0/2.0, 9.0, 9.0/2.0, \ - 0.5, 1.5, 1.5, 1.5, 9.0}; - - int lb_d3q15_create(lb_model_t * model); #endif From 670e6617ff82c16f4d539b823ed15e0c85966fac Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Sun, 28 Nov 2021 19:39:21 +0000 Subject: [PATCH 065/117] Compute nornalisers at run time --- src/lb_d3q19.c | 26 +++++++++++++++++--------- src/lb_d3q19.h | 10 +--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/lb_d3q19.c b/src/lb_d3q19.c index 8fafea132..4d88904d9 100644 --- a/src/lb_d3q19.c +++ b/src/lb_d3q19.c @@ -49,14 +49,12 @@ int lb_d3q19_create(lb_model_t * model) { { LB_CV_D3Q19(cv); LB_WEIGHTS_D3Q19(wv); - LB_NORMALISERS_D3Q19(na); for (int p = 0; p < model->nvel; p++) { for (int ia = 0; ia < 3; ia++) { model->cv[p][ia] = cv[p][ia]; } model->wv[p] = wv[p]; - model->na[p] = na[p]; } } @@ -71,6 +69,16 @@ int lb_d3q19_create(lb_model_t * model) { lb_d3q19_matrix_ma(model); + /* Normalisers */ + + for (int p = 0; p < model->nvel; p++) { + double wip = 0.0; + for (int ia = 0; ia < model->nvel; ia++) { + wip += model->wv[ia]*model->ma[p][ia]*model->ma[p][ia]; + } + model->na[p] = 1.0/wip; + } + return 0; err: @@ -88,9 +96,9 @@ int lb_d3q19_create(lb_model_t * model) { * * There are three scalar ghost modes: * - * chi1 (2cs^2 - 3)(3c_z^2 - cs^2) mode[10] - * chi2 (2cs^2 - 3)(c_y^2 - c_x^2) mode[14] - * chi3 3cs^4 - 6cs^2 + 1 mode[18] + * chi1 (2c^2 - 3)(3c_z^2 - c^2) mode[10] + * chi2 (2c^2 - 3)(c_y^2 - c_x^2) mode[14] + * chi3 3c^4 - 6c^2 + 1 mode[18] * * and two associated vectors jchi1 and jchi2. * @@ -115,10 +123,10 @@ static int lb_d3q19_matrix_ma(lb_model_t * model) { double syz = cy*cz; double szz = cz*cz - model->cs2; - double cs2 = cx*cx + cy*cy + cz*cz; - double chi1 = (2.0*cs2 - 3.0)*(3.0*cz*cz - cs2); - double chi2 = (2.0*cs2 - 3.0)*(cy*cy - cx*cx); - double chi3 = 3.0*cs2*cs2 - 6.0*cs2 + 1; + double c2 = cx*cx + cy*cy + cz*cz; + double chi1 = (2.0*c2 - 3.0)*(3.0*cz*cz - c2); + double chi2 = (2.0*c2 - 3.0)*(cy*cy - cx*cx); + double chi3 = 3.0*c2*c2 - 6.0*c2 + 1; model->ma[ 0][p] = rho; model->ma[ 1][p] = cx; diff --git a/src/lb_d3q19.h b/src/lb_d3q19.h index dd0c89b5d..8410c130c 100644 --- a/src/lb_d3q19.h +++ b/src/lb_d3q19.h @@ -19,7 +19,7 @@ #include "lb_model.h" -/* Velocity set, weights, and normalisers. */ +/* Velocity set and weights. */ enum {NVEL_D3Q19 = 19}; @@ -37,14 +37,6 @@ enum {NVEL_D3Q19 = 19}; 1.0/36.0, 2.0/36.0, 2.0/36.0, 1.0/36.0, 2.0/36.0, 1.0/36.0, 1.0/36.0, \ 1.0/36.0, 2.0/36.0, 1.0/36.0, 1.0/36.0}; -#define LB_NORMALISERS_D3Q19(na) const double na[NVEL_D3Q19] = { \ - 1.0, \ - 3.0, 3.0, 3.0, \ - 9.0/2.0, 9.0, 9.0, 9.0/2.0, 9.0, 9.0/2.0, \ - 3.0/4.0, 3.0/2.0, 3.0/2.0, 3.0/2.0, \ - 9.0/4.0, 9.0/2.0, 9.0/2.0, 9.0/2.0, \ - 1.0/2.0}; - int lb_d3q19_create(lb_model_t * model); #endif From 8749a5ee2c689898985433292904853a6fd1143b Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Sun, 28 Nov 2021 19:40:00 +0000 Subject: [PATCH 066/117] Add initial tests for d3q27 --- tests/unit/test_lb_model.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tests/unit/test_lb_model.c b/tests/unit/test_lb_model.c index d204ea178..fb0c58c85 100644 --- a/tests/unit/test_lb_model.c +++ b/tests/unit/test_lb_model.c @@ -11,7 +11,7 @@ * (c) 2021 The University of Edinburgh * * Contributing authors: - * Kevin Stratford (kevin@epcc.ed.ac.uk) + * Kevin Stratford (kevin@epcc.ed.ac.uk) * *****************************************************************************/ @@ -45,6 +45,7 @@ int test_lb_model_suite(void) { test_lb_model_create(9); test_lb_model_create(15); test_lb_model_create(19); + test_lb_model_create(27); pe_info(pe, "PASS ./unit/test_lb_model\n"); @@ -157,6 +158,7 @@ int test_lb_model_wv(const lb_model_t * model) { sumcv[Y] += model->cv[p][Y]; sumcv[Z] += model->cv[p][Z]; } + /* This can be close... may require 2*epsilon */ assert(fabs(sumwv - 1.0) <= DBL_EPSILON); assert(fabs(sumcv[X] - 0.0) <= DBL_EPSILON); @@ -239,6 +241,7 @@ int test_lb_model_ma(const lb_model_t * model) { assert(model); /* Check normalisers \sum_p na[i]*wv[p]*ma[i][p]*ma[j][p] = dij. */ + /* The modes must all be orthonormal wrt one another. */ for (int i = 0; i < model->nvel; i++) { for (int j = 0; j < model->nvel; j++) { @@ -248,9 +251,12 @@ int test_lb_model_ma(const lb_model_t * model) { double ** ma = model->ma; sum += model->na[i]*model->wv[p]*ma[i][p]*ma[j][p]; } - /* Just too tight to make DBL_EPSILON ... */ - assert(fabs(sum - dij) < 2*DBL_EPSILON); - ierr += (fabs(sum - dij) > 2*DBL_EPSILON); + + /* Too tight to make DBL_EPSILON ... */ + /* although d2q9, d3q15, d3q19 will make 2*DBL_EPISLON */ + + assert(fabs(sum - dij) < 5.0*DBL_EPSILON); + ierr += (fabs(sum - dij) > 5.0*DBL_EPSILON); } } From 9dc9b653b0508cbccd3d43200fc599221c27d28d Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Sun, 28 Nov 2021 19:40:31 +0000 Subject: [PATCH 067/117] Remove normaliser macro and related refactoring --- src/collision.c | 54 ++++++++++++++++++++++++++++++---------------- src/collision_rt.c | 20 ++++++++++++++++- src/lb_model_s.h | 6 +++--- src/model.c | 4 ++++ src/model.h | 3 --- 5 files changed, 61 insertions(+), 26 deletions(-) diff --git a/src/collision.c b/src/collision.c index ca7cf11d7..f6b560501 100644 --- a/src/collision.c +++ b/src/collision.c @@ -56,6 +56,7 @@ int lb_collision_binary(lb_t * lb, hydro_t * hydro, noise_t * noise, static __host__ __device__ void lb_collision_fluctuations(lb_t * lb, noise_t * noise, int index, + double kt, double shat[3][3], double ghat[NVEL]); int lb_collision_noise_var_set(lb_t * lb, noise_t * noise); static __host__ int lb_collision_parameters_commit(lb_t * lb, visc_t * visc); @@ -110,7 +111,8 @@ __host__ __device__ int lb_relaxation_time_ghosts(lb_t * lb, __host__ __device__ double lb_fluctuations_var_eta(double tau, double kt); __host__ __device__ double lb_fluctuations_var_bulk(double tau, double kt); -__host__ __device__ int lb_fluctuations_var_ghost(double * rtau, double kt, +__host__ __device__ int lb_fluctuations_var_ghost(double * rna, double * rtau, + double kt, double * var); __host__ __device__ int lb_fluctuations_stress(noise_t * noise, int index, @@ -507,7 +509,8 @@ void lb_collision_mrt1_site(lb_t * lb, hydro_t * hydro, map_t * map, for (ia = 0; ia < NVEL; ia++) { rtau_ghost_tmp[ia] = rtau_ghost[ia][iv]; } - lb_fluctuations_var_ghost(rtau_ghost_tmp, _cp.kt, var_ghost); + lb_fluctuations_var_ghost(lb->param->rna, + rtau_ghost_tmp, _cp.kt, var_ghost); lb_fluctuations_ghosts(noise, index0 + iv, var_ghost, ghat1); for (ia = 0; ia < NVEL; ia++) { ghat[ia][iv] = ghat1[ia]; @@ -890,7 +893,7 @@ __device__ void lb_collision_mrt2_site(lb_t * lb, hydro_t * hydro, double shat1[3][3]; double ghat1[NVEL]; - lb_collision_fluctuations(lb, noise, index0 + iv, shat1, ghat1); + lb_collision_fluctuations(lb, noise, index0 + iv, _cp.kt, shat1, ghat1); for (ia = 0; ia < 3; ia++) { for (ib = 0; ib < 3; ib++) { @@ -1573,9 +1576,7 @@ __host__ int lb_collision_noise_var_set(lb_t * lb, noise_t * noise) { double kt; double tau_s; double tau_b; - double tau_g; LB_RCS2_DOUBLE(rcs2); - LB_NORMALISERS_DOUBLE(na); physics_t * phys = NULL; @@ -1601,14 +1602,6 @@ __host__ int lb_collision_noise_var_set(lb_t * lb, noise_t * noise) { sqrt(kt)*sqrt(2.0/9.0)*sqrt((tau_b + tau_b - 1.0)/(tau_b*tau_b)); lb->param->var_shear = sqrt(kt)*sqrt(1.0/9.0)*sqrt((tau_s + tau_s - 1.0)/(tau_s*tau_s)); - - /* Noise variances */ - - for (p = NHYDRO; p < NVEL; p++) { - tau_g = 1.0/lb->param->rtau[p]; - lb->param->var_noise[p] = - sqrt(kt/na[p])*sqrt((tau_g + tau_g - 1.0)/(tau_g*tau_g)); - } } if (lb->param->isghost == LB_GHOST_OFF) { @@ -1617,7 +1610,6 @@ __host__ int lb_collision_noise_var_set(lb_t * lb, noise_t * noise) { /* Eliminate ghost modes and ghost mode noise */ for (p = NHYDRO; p < NVEL; p++) { lb->param->rtau[p] = 1.0; - lb->param->var_noise[p] = 0.0; } } @@ -1663,16 +1655,18 @@ __host__ int lb_collision_relaxation_times(lb_t * lb, double * tau) { * the current lattice site index. * * There are NDIM*(NDIM+1)/2 independent stress modes, and - * NVEL - NHYDRO ghost modes. + * NVEL - NHYDRO ghost modes (computed using kt explicitly). * *****************************************************************************/ static __host__ __device__ void lb_collision_fluctuations(lb_t * lb, noise_t * noise, int index, + double kt, double shat[3][3], double ghat[NVEL]) { int ia; double tr; double random[NNOISE_MAX]; + LB_RCS2_DOUBLE(rcs2); assert(lb); assert(lb->param); @@ -1737,7 +1731,11 @@ static __host__ __device__ noise_reap_n(noise, index, NVEL-NHYDRO, random); for (ia = NHYDRO; ia < NVEL; ia++) { - ghat[ia] = lb->param->var_noise[ia]*random[ia - NHYDRO]; + /* Remember further normalisation of kT = rcs2*kt */ + double tau = 1.0/lb->param->rtau[ia]; + double rna = lb->param->rna[ia]; + double var = sqrt(rna*rcs2*kt)*sqrt((tau + tau - 1.0)/(tau*tau)); + ghat[ia] = var*random[ia - NHYDRO]; } } @@ -1791,13 +1789,16 @@ __host__ __device__ double lb_fluctuations_var_bulk(double tau, double kt) { * Variances for ghost mode noise for modes with inverse relaxation * times rtau and temperature kt. * + * Also depends on the reciprocal of the normalisers rna[] for the + * current model. + * *****************************************************************************/ -__host__ __device__ int lb_fluctuations_var_ghost(double * rtau, double kt, +__host__ __device__ int lb_fluctuations_var_ghost(double * rna, double * rtau, + double kt, double * var) { int p; LB_RCS2_DOUBLE(rcs2); - LB_NORMALISERS_DOUBLE(norm); assert(rtau); assert(kt >= 0.0); @@ -1807,7 +1808,7 @@ __host__ __device__ int lb_fluctuations_var_ghost(double * rtau, double kt, for (p = NHYDRO; p < NVEL; p++) { double tau_g = 1.0/rtau[p]; - var[p] = sqrt(kt/norm[p])*sqrt((tau_g + tau_g - 1.0)/(tau_g*tau_g)); + var[p] = sqrt(kt*rna[p])*sqrt((tau_g + tau_g - 1.0)/(tau_g*tau_g)); } return 0; @@ -1881,6 +1882,21 @@ __host__ __device__ int lb_fluctuations_stress(noise_t * noise, int index, return 0; } +/***************************************************************************** + * + * lb_fluctuations_ghosts + * + * Note. Beacuse the random numbers are just assigned to the modes + * on the basis of order of appearance in M^a, the order of the + * ghost modes is significant here. + * + * If the order of the modes is changed, the then random number + * would have to be re-assigned in the new order to recover exactly + * the same numerical results. (In the long-run, the statistics + * are no different - the labelling cannot have any physical effect.) + * + *****************************************************************************/ + __host__ __device__ int lb_fluctuations_ghosts(noise_t * noise, int index, double * var_ghost, double ghat[NVEL]) { diff --git a/src/collision_rt.c b/src/collision_rt.c index c1e397c55..efabbec5c 100644 --- a/src/collision_rt.c +++ b/src/collision_rt.c @@ -47,6 +47,8 @@ int collision_run_time(pe_t * pe, rt_t * rt, lb_t * lb, noise_t * noise) { assert(rt); assert(lb); + /* Prefer "lb_fluctuations" in the future */ + p = rt_string_parameter(rt, "isothermal_fluctuations", tmp, BUFSIZ); if (p == 1 && strcmp(tmp, "on") == 0) { @@ -54,6 +56,13 @@ int collision_run_time(pe_t * pe, rt_t * rt, lb_t * lb, noise_t * noise) { noise_present_set(noise, NOISE_RHO, noise_on); } + p = rt_switch(rt, "lb_fluctuations"); + + if (p == 1) { + noise_on = 1; + noise_present_set(noise, NOISE_RHO, noise_on); + } + /* Relaxation time scheme (default M10) */ strcpy(relax, "M10"); @@ -76,7 +85,15 @@ int collision_run_time(pe_t * pe, rt_t * rt, lb_t * lb, noise_t * noise) { } } - /* Ghost modes */ + /* Ghost modes (prefer "lb_ghost_modes" in future) */ + + p = rt_key_required(rt, "lb_ghost_modes", RT_NONE); /* p = 0 if present */ + + if (p == 0) { + nghost = rt_switch(rt, "lb_ghost_modes"); + if (nghost == 0) lb_collision_ghost_modes_off(lb); + } + else { p = rt_string_parameter(rt, "ghost_modes", tmp, BUFSIZ); nghost = 1; @@ -85,6 +102,7 @@ int collision_run_time(pe_t * pe, rt_t * rt, lb_t * lb, noise_t * noise) { lb_collision_ghost_modes_off(lb); } + } lb_collision_relaxation_times(lb, tau); pe_info(pe, "\n"); diff --git a/src/lb_model_s.h b/src/lb_model_s.h index a4bf9f20c..a2da1124a 100644 --- a/src/lb_model_s.h +++ b/src/lb_model_s.h @@ -7,7 +7,7 @@ * Edinburgh Soft Matter and Statistical Physics Group and * Edinburgh Parallel Computing Centre * - * (c) 2014-2020 The University of Edinburgh + * (c) 2014-2021 The University of Edinburgh * * Contributing authors: * Kevin Stratford (kevin@epcc.ed.ac.uk) @@ -34,7 +34,7 @@ struct lb_collide_param_s { double var_shear; double eta_bulk; double var_bulk; - double var_noise[NVEL]; + double rna[NVEL]; /* reciprocal of normaliser[p] */ double rtau[NVEL]; double wv[NVEL]; double q[NVEL][3][3]; @@ -50,7 +50,7 @@ struct lb_data_s { pe_t * pe; /* parallel environment */ cs_t * cs; /* coordinate system */ - lb_model_t model; /* Current model information */ + lb_model_t model; /* Current LB model information */ halo_swap_t * halo; /* halo swap driver */ io_info_t * io_info; /* Distributions */ io_info_t * io_rho; /* Fluid density (here; could be hydrodynamics...) */ diff --git a/src/model.c b/src/model.c index 94ff29de6..37f257ebb 100644 --- a/src/model.c +++ b/src/model.c @@ -354,6 +354,10 @@ static int lb_model_param_init(lb_t * lb) { } } + for (ia = 0; ia < NVEL; ia++) { + lb->param->rna[ia] = 1.0/lb->model.na[ia]; + } + for (ia = 0; ia < NVEL; ia++) { for (ib = 0; ib < NVEL; ib++) { lb->param->ma[ia][ib] = lb->model.ma[ia][ib]; diff --git a/src/model.h b/src/model.h index d83926797..3604be0db 100644 --- a/src/model.h +++ b/src/model.h @@ -30,7 +30,6 @@ enum {NDIM = NDIM9, CVZBLOCK = CVZBLOCK9}; #define LB_CV(cv) LB_CV_D2Q9(cv) -#define LB_NORMALISERS_DOUBLE(n) LB_NORMALISERS_D2Q9(n) #endif @@ -44,7 +43,6 @@ enum {NDIM = NDIM15, CVZBLOCK = CVZBLOCK15}; #define LB_CV(cv) LB_CV_D3Q15(cv) -#define LB_NORMALISERS_DOUBLE(n) LB_NORMALISERS_D3Q15(n) #endif @@ -59,7 +57,6 @@ enum {NDIM = NDIM19, CVZBLOCK = CVZBLOCK19}; #define LB_CV(cv) LB_CV_D3Q19(cv) -#define LB_NORMALISERS_DOUBLE(n) LB_NORMALISERS_D3Q19(n) #endif From 0af93fd4e236837093af6330555db44c1681b902 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Mon, 29 Nov 2021 14:51:38 +0000 Subject: [PATCH 068/117] Allow MPI_STATUS(ES)_IGNORE --- mpi_s/mpi.h | 2 ++ mpi_s/mpi_serial.c | 5 ----- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/mpi_s/mpi.h b/mpi_s/mpi.h index 83e3b54b1..1c9e8648c 100644 --- a/mpi_s/mpi.h +++ b/mpi_s/mpi.h @@ -37,6 +37,8 @@ typedef struct { int MPI_TAG; } MPI_Status; +#define MPI_STATUS_IGNORE ((MPI_Status *) 0) +#define MPI_STATUSES_IGNORE ((MPI_Status *) 0) /* MPI_Aint is a signed integer. Prefer intmax_t over intptr_t as the latter is optional in the standard. */ diff --git a/mpi_s/mpi_serial.c b/mpi_s/mpi_serial.c index 2e0821df9..701ec475a 100644 --- a/mpi_s/mpi_serial.c +++ b/mpi_s/mpi_serial.c @@ -290,7 +290,6 @@ int MPI_Recv(void * buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status * status) { assert(buf); - assert(status); printf("MPI_Recv should not be called in serial.\n"); exit(0); @@ -383,7 +382,6 @@ int MPI_Waitall(int count, MPI_Request * requests, MPI_Status * statuses) { assert(count >= 0); assert(requests); - assert(statuses); return MPI_SUCCESS; } @@ -401,7 +399,6 @@ int MPI_Waitany(int count, MPI_Request requests[], int * index, assert(count >= 0); assert(requests); assert(index); - assert(statuses); return MPI_SUCCESS; } @@ -417,7 +414,6 @@ int MPI_Probe(int source, int tag, MPI_Comm comm, MPI_Status * status) { assert(source == 0); assert(mpi_is_valid_comm(comm)); - assert(status); printf("MPI_Probe should not be called in serial\n"); exit(0); @@ -440,7 +436,6 @@ int MPI_Sendrecv(void * sendbuf, int sendcount, MPI_Datatype sendtype, assert(dest == source); assert(recvbuf); assert(recvcount == sendcount); - assert(status); printf("MPI_Sendrecv should not be called in serial\n"); exit(0); From c9c79ea0ba0698975e0bc752226f99b650c6a962 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Mon, 29 Nov 2021 14:52:54 +0000 Subject: [PATCH 069/117] Unwind dependency on blue phase --- src/phi_force_stress.c | 69 ------------------------------------------ src/phi_force_stress.h | 3 -- 2 files changed, 72 deletions(-) diff --git a/src/phi_force_stress.c b/src/phi_force_stress.c index 855de767c..1f004a005 100644 --- a/src/phi_force_stress.c +++ b/src/phi_force_stress.c @@ -25,7 +25,6 @@ #include "kernel.h" #include "pth_s.h" #include "phi_force_stress.h" -#include "blue_phase.h" __global__ void pth_kernel(kernel_ctxt_t * ktx, pth_t * pth, fe_t * fe); __global__ void pth_kernel_v(kernel_ctxt_t * ktx, pth_t * pth, fe_t * fe); @@ -335,74 +334,6 @@ __global__ void pth_kernel_a_v(kernel_ctxt_t * ktx, pth_t * pth, fe_t * fe) { return; } -/***************************************************************************** - * - * pth_bulk_stress_compute - * - * Compute the stress from bulk FE terms everywhere and store. - * - *****************************************************************************/ - -__host__ int pth_bulk_stress_compute(pth_t * pth, fe_lc_t * fe) { - - int ic, jc, kc; - int index,nlocal[3]; - double sth[3][3]; - - assert(pth); - assert(fe); - - cs_nlocal(pth->cs, nlocal); - - for (ic = 1; ic <= nlocal[X]; ic++) { - for (jc = 1; jc <= nlocal[Y]; jc++) { - for (kc = 1; kc <= nlocal[Z]; kc++) { - - index = cs_index(pth->cs, ic, jc, kc); - fe_lc_bulk_stress(fe, index, sth); - pth_stress_set(pth, index, sth); - - } - } - } - - return 0; -} - -/***************************************************************************** - * - * pth_gradient_stress_compute - * - * Compute the stress from gradient FE terms everywhere and store. - * - *****************************************************************************/ - -__host__ int pth_gradient_stress_compute(pth_t * pth, fe_lc_t * fe) { - - int ic, jc, kc; - int index,nlocal[3]; - double sth[3][3]; - - assert(pth); - assert(fe); - - cs_nlocal(pth->cs, nlocal); - - for (ic = 1; ic <= nlocal[X]; ic++) { - for (jc = 1; jc <= nlocal[Y]; jc++) { - for (kc = 1; kc <= nlocal[Z]; kc++) { - - index = cs_index(pth->cs, ic, jc, kc); - fe_lc_grad_stress(fe, index, sth); - pth_stress_set(pth, index, sth); - - } - } - } - - return 0; -} - /***************************************************************************** * * phi_force_stress_set diff --git a/src/phi_force_stress.h b/src/phi_force_stress.h index 7ee06473f..37bbb5c40 100644 --- a/src/phi_force_stress.h +++ b/src/phi_force_stress.h @@ -20,7 +20,6 @@ #include "pe.h" #include "coords.h" #include "free_energy.h" -#include "blue_phase.h" enum {PTH_METHOD_NO_FORCE, PTH_METHOD_DIVERGENCE, PTH_METHOD_GRADMU, PTH_METHOD_STRESS_ONLY}; @@ -31,8 +30,6 @@ __host__ int pth_create(pe_t * pe, cs_t * cs, int method, pth_t ** pth); __host__ int pth_free(pth_t * pth); __host__ int pth_memcpy(pth_t * pth, tdpMemcpyKind flag); __host__ int pth_stress_compute(pth_t * pth, fe_t * fe); -__host__ int pth_bulk_stress_compute(pth_t * pth, fe_lc_t * fe); -__host__ int pth_gradient_stress_compute(pth_t * pth, fe_lc_t * fe); __host__ __device__ void pth_stress(pth_t * pth, int index, double p[3][3]); __host__ __device__ void pth_stress_set(pth_t * pth, int index, double p[3][3]); From ea6464a00ce8f5b44627e2eab23697cfc2edcab0 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Mon, 29 Nov 2021 15:05:30 +0000 Subject: [PATCH 070/117] Minor fix --- tests/unit/test_fe_symmetric.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/test_fe_symmetric.c b/tests/unit/test_fe_symmetric.c index 7e14d1109..0a7499798 100644 --- a/tests/unit/test_fe_symmetric.c +++ b/tests/unit/test_fe_symmetric.c @@ -72,7 +72,7 @@ int test_fe_symm_theta_to_h(pe_t * pe) { ierr += fe_symm_theta_to_h(theta, &h); assert(ierr == 0); - assert(fabs(h - sqrt(2.0*sqrt(3.0) - 3.0)) < DBL_EPSILON); + assert(fabs(h - sqrt(2.0*sqrt(3.0) - 3.0)) < 2.0*DBL_EPSILON); } return ierr; From 629c6292c8344efa5ad9faeb79e0eaec2857dbdd Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Mon, 29 Nov 2021 15:05:59 +0000 Subject: [PATCH 071/117] Add colloid diagnostic output for forces --- src/bbl.c | 14 +- src/colloid_sums.c | 60 +++++- src/colloid_sums.h | 5 +- src/colloids.h | 27 +++ src/ludwig.c | 12 +- src/stats_colloid_force_split.c | 319 ++++++++++++++++++++++++++++++++ src/stats_colloid_force_split.h | 23 +++ 7 files changed, 453 insertions(+), 7 deletions(-) create mode 100644 src/stats_colloid_force_split.c create mode 100644 src/stats_colloid_force_split.h diff --git a/src/bbl.c b/src/bbl.c index 44dab3c0d..b035184d7 100644 --- a/src/bbl.c +++ b/src/bbl.c @@ -913,27 +913,35 @@ int bbl_update_colloids(bbl_t * bbl, wall_t * wall, colloids_info_t * cinfo) { /* Record the actual hydrodynamic force on the particle */ - pc->force[X] = pc->f0[X] + pc->diagnostic.fhydro[X] = pc->f0[X] -(pc->zeta[0]*pc->s.v[X] + pc->zeta[1]*pc->s.v[Y] + pc->zeta[2]*pc->s.v[Z] + pc->zeta[3]*pc->s.w[X] + pc->zeta[4]*pc->s.w[Y] + pc->zeta[5]*pc->s.w[Z]); - pc->force[Y] = pc->f0[Y] + pc->diagnostic.fhydro[Y] = pc->f0[Y] -(pc->zeta[ 1]*pc->s.v[X] + pc->zeta[ 6]*pc->s.v[Y] + pc->zeta[ 7]*pc->s.v[Z] + pc->zeta[ 8]*pc->s.w[X] + pc->zeta[ 9]*pc->s.w[Y] + pc->zeta[10]*pc->s.w[Z]); - pc->force[Z] = pc->f0[Z] + pc->diagnostic.fhydro[Z] = pc->f0[Z] -(pc->zeta[ 2]*pc->s.v[X] + pc->zeta[ 7]*pc->s.v[Y] + pc->zeta[11]*pc->s.v[Z] + pc->zeta[12]*pc->s.w[X] + pc->zeta[13]*pc->s.w[Y] + pc->zeta[14]*pc->s.w[Z]); + + /* Copy non-hydrodynamic contribution for the diagnostic record. */ + + pc->diagnostic.fnonhy[X] = pc->force[X]; + pc->diagnostic.fnonhy[Y] = pc->force[Y]; + pc->diagnostic.fnonhy[Z] = pc->force[Z]; + + /* Next colloid */ } /* As the lubrication force is based on the updated velocity, but diff --git a/src/colloid_sums.c b/src/colloid_sums.c index 7f8105ef0..754f3e3f5 100644 --- a/src/colloid_sums.c +++ b/src/colloid_sums.c @@ -73,11 +73,12 @@ static int colloid_sums_m3(colloid_sum_t * sum, int, int, int, int); static int colloid_sums_m4(colloid_sum_t * sum, int, int, int, int); static int colloid_sums_m5(colloid_sum_t * sum, int, int, int, int); static int colloid_sums_m6(colloid_sum_t * sum, int, int, int, int); +static int colloid_sums_m7(colloid_sum_t * sum, int, int, int, int); /* Message sizes (doubles) */ /* NULL is a dummy zero size */ -static const int msize_[COLLOID_SUM_MAX] = {0, 10, 35, 7, 4, 6, 7}; +static const int msize_[COLLOID_SUM_MAX] = {0, 10, 35, 7, 4, 6, 7, 10}; /* The following are used for internal communication */ @@ -381,6 +382,7 @@ static int colloid_sums_process(colloid_sum_t * sum, int dim) { if (sum->mtype == COLLOID_SUM_SUBGRID) mloader_forw = colloid_sums_m4; if (sum->mtype == COLLOID_SUM_CONSERVATION) mloader_forw = colloid_sums_m5; if (sum->mtype == COLLOID_SUM_FORCE_EXT_ONLY) mloader_forw = colloid_sums_m6; + if (sum->mtype == COLLOID_SUM_DIAGNOSTIC) mloader_forw = colloid_sums_m7; assert(mloader_forw); mloader_back = mloader_forw; @@ -796,3 +798,59 @@ static int colloid_sums_m6(colloid_sum_t * sum, int ic, int jc, int kc, return npart; } + +/***************************************************************************** + * + * colloid_sums_m7 + * + * Diagnostic quantities. + * + * Currently only stress terms require a sum here. Other forces + * are computed as a result of the dynamics, where an appropriate + * sum should have already taken place. + * + *****************************************************************************/ + +static int colloid_sums_m7(colloid_sum_t * sum, int ic, int jc, int kc, + int noff) { + + int n, npart; + int ia; + int index; + colloid_t * pc; + + n = sum->msize*noff; + npart = 0; + colloids_info_cell_list_head(sum->cinfo, ic, jc, kc, &pc); + + for (; pc; pc = pc->next) { + + if (sum->mload == MESSAGE_LOAD) { + sum->send[n++] = 1.0*pc->s.index; + for (ia = 0; ia < 3; ia++) { + sum->send[n++] = pc->diagnostic.fsbulk[ia]; + sum->send[n++] = pc->diagnostic.fsgrad[ia]; + sum->send[n++] = pc->diagnostic.fschem[ia]; + } + assert(n == (noff + npart + 1)*sum->msize); + } + else { + /* unload and check incoming index (a fatal error) */ + index = (int) sum->recv[n++]; + if (index != pc->s.index) { + pe_fatal(sum->pe, "Sum mismatch m7 (%d)\n", index); + } + + for (ia = 0; ia < 3; ia++) { + pc->diagnostic.fsbulk[ia] += sum->recv[n++]; + pc->diagnostic.fsgrad[ia] += sum->recv[n++]; + pc->diagnostic.fschem[ia] += sum->recv[n++]; + } + assert(n == (noff + npart + 1)*sum->msize); + } + + npart++; + } + + return npart; +} diff --git a/src/colloid_sums.h b/src/colloid_sums.h index 01043cd77..16749a09d 100644 --- a/src/colloid_sums.h +++ b/src/colloid_sums.h @@ -6,7 +6,7 @@ * Edinburgh Soft Matter and Statistical Physics Group and * Edinburgh Parallel Computing Centre * - * (c) 2010-2020 The University of Edinburgh + * (c) 2010-2021 The University of Edinburgh * * Contributing authors: * Kevin Stratford (kevin@epcc.ed.ac.uk) @@ -28,7 +28,8 @@ typedef enum colloid_sum_enum_type { COLLOID_SUM_SUBGRID = 4, COLLOID_SUM_CONSERVATION = 5, COLLOID_SUM_FORCE_EXT_ONLY = 6, - COLLOID_SUM_MAX = 7} colloid_sum_enum_t; + COLLOID_SUM_DIAGNOSTIC = 7, + COLLOID_SUM_MAX = 8} colloid_sum_enum_t; int colloid_sums_create(colloids_info_t * cinfo, colloid_sum_t ** psum); void colloid_sums_free(colloid_sum_t * sum); diff --git a/src/colloids.h b/src/colloids.h index b0dded11b..363e66f56 100644 --- a/src/colloids.h +++ b/src/colloids.h @@ -21,6 +21,29 @@ #include "colloid.h" #include "colloid_link.h" +/* Auxiliary for diagnostic quantities (for output) */ + +typedef struct colloid_diagnostic_s colloid_diagnostic_t; + +struct colloid_diagnostic_s { + + int index; /* Copy of particle index for identification. */ + double ftotal[3]; /* Net force on particle (all contributions) */ + double fhydro[3]; /* Hydrodynamic force on particle */ + double fsbulk[3]; /* Bulk stress (divergence) contribution */ + double fsgrad[3]; /* Gradient stress (divergence) contribution */ + double fschem[3]; /* Total "chemical" stress contribution (is fd2 + fd3) */ + double finter[3]; /* External field/interaction contribution */ + double fnonhy[3]; /* Total non-hydrodynamic (interpendent of fd0-fd1) */ + + /* Might want to split external field / conservative interaction + * contributions. A separate wall contribution for lubrication + * corrections is missing; it should currently appear in the + * hydrodynamic contribution. */ +}; + +/* Colloid structure */ + typedef struct colloid colloid_t; struct colloid { @@ -49,6 +72,10 @@ struct colloid { double fex[3]; /* External forces (non-fluid) on particle */ double tex[3]; /* External torques on particle */ + /* Diagnostic utilities (all for current time step) */ + + colloid_diagnostic_t diagnostic; + /* Pointers */ colloid_link_t * lnk; /* Pointer to the list of links defining surface */ diff --git a/src/ludwig.c b/src/ludwig.c index 5fffea251..619c3f046 100644 --- a/src/ludwig.c +++ b/src/ludwig.c @@ -102,6 +102,7 @@ /* Statistics */ #include "stats_colloid.h" +#include "stats_colloid_force_split.h" #include "stats_turbulent.h" #include "stats_surfactant.h" #include "stats_rheology.h" @@ -714,7 +715,12 @@ void ludwig_run(const char * inputfile) { ludwig->hydro, ludwig->map, ludwig->wall); } } - + /* OLIVER: + You need this, only at statistics steps... + stats_colloid_force_split_update(ludwig->collinfo, + ludwig->fe, ludwig->map, + ludwig->q, ludwig->q_grad); + */ TIMER_stop(TIMER_FORCE_CALCULATION); @@ -940,6 +946,10 @@ void ludwig_run(const char * inputfile) { field_memcpy(ludwig->q, tdpMemcpyDeviceToHost); field_grad_memcpy(ludwig->q_grad, tdpMemcpyDeviceToHost); stats_field_info(ludwig->q, ludwig->map); + /* OLIVER: + You need this for diagnostic output + stats_colloid_force_split_output(ludwig->collinfo, step); + */ } if (ludwig->psi) { diff --git a/src/stats_colloid_force_split.c b/src/stats_colloid_force_split.c new file mode 100644 index 000000000..d365844a3 --- /dev/null +++ b/src/stats_colloid_force_split.c @@ -0,0 +1,319 @@ +/***************************************************************************** + * + * stats_colloid_force_split.c + * + * Diagnostic computation of various components of the total force on + * a colloid. In the context of liquid crystal free energy. + * + * + * Contributing authors: + * Oliver Henrich (o.henrich@strath.ac.uk) + * Kevin Stratford (kevin@epcc.ed.ac.uk) + * + *****************************************************************************/ + +#include +#include + +#include "pe.h" +#include "pth_s.h" +#include "model.h" +#include "blue_phase.h" +#include "colloid_sums.h" +#include "phi_force_stress.h" +#include "stats_colloid_force_split.h" + +enum {FSBULK, FSGRAD, FSCHEM}; /* Identify different components */ + +typedef int (*fe_lc_str_ft)(fe_lc_t * fe, int inde, double s[3][3]); + +int colloid_force_from_pth(colloid_t * pc, pth_t * pth, double f[3]); +int stat_stress_compute(pth_t * pth, fe_t * fe, fe_lc_str_ft stress); +int stat_colloids_force(colloids_info_t * cinfo, pth_t * pth, int contrib); +int stat_diagnostic_write(colloid_diagnostic_t * array, int count, FILE * fp); + +/***************************************************************************** + * + * stats_colloid_force_split_update + * + * Compute the current breakdown in stresses on the colloid. + * This should be called before the Beris-Edwards update in + * the time step, so that a consistent Q_ab is available. + * + * The resulting diagnostic quantities are stored until the + * output stage is required (assumed to be at the end of + * the time step. + * + *****************************************************************************/ + +int stats_colloid_force_split_update(colloids_info_t * cinfo, fe_t * fe, + map_t * map, + field_t * q, field_grad_t * q_grad) { + pth_t * pth = NULL; + pe_t * pe = NULL; + cs_t * cs = NULL; + + pe = q->pe; + cs = q->cs; + + pth_create(pe, cs, PTH_METHOD_DIVERGENCE, &pth); + + /* Total stress */ + stat_stress_compute(pth, fe, fe_lc_stress); + stat_colloids_force(cinfo, pth, FSCHEM); + + /* Bulk stress */ + stat_stress_compute(pth, fe, fe_lc_bulk_stress); + stat_colloids_force(cinfo, pth, FSBULK); + + /* Gradient stress */ + stat_stress_compute(pth, fe, fe_lc_grad_stress); + stat_colloids_force(cinfo, pth, FSGRAD); + + pth_free(pth); + + return 0; +} + +/***************************************************************************** + * + * stats_colloid_force_split_output + * + * As we only expect this once in a while, there's a relatively simple + * (aka naive) mechanism for output. + * + *****************************************************************************/ + +int stats_colloid_force_split_output(colloids_info_t * cinfo, int timestep) { + + pe_t * pe = NULL; + + colloid_diagnostic_t * buf = NULL; + MPI_Comm comm = MPI_COMM_NULL; + int count = 0; + int sz = sizeof(colloid_diagnostic_t); + + assert(cinfo); + assert(timestep >= 0); + + pe = cinfo->pe; + + /* Run halo_sum on diagnostic quantities */ + + colloid_sums_halo(cinfo, COLLOID_SUM_DIAGNOSTIC); + + /* Everyone count local colloids and form a send buffer. */ + + colloids_info_nlocal(cinfo, &count); + + buf = (colloid_diagnostic_t *) malloc(count*sz); + assert(buf); + if (buf == NULL) pe_fatal(pe, "Diagnostic buffer malloc fail\n"); + + { + int nb = 0; + colloid_t * pc = NULL; + colloids_info_local_head(cinfo, &pc); + for ( ; pc; pc = pc->nextlocal) { + pc->diagnostic.index = pc->s.index; /* Record the index */ + buf[nb++] = pc->diagnostic; + } + assert(nb == count); + } + + /* Communicate */ + pe_mpi_comm(pe, &comm); + + if (pe_mpi_rank(pe) > 0) { + /* Send to root: a count, and a data buffer */ + MPI_Request req[2] = {}; + + MPI_Isend(&count, 1, MPI_INT, 0, 211129, comm, req + 0); + MPI_Isend(buf, count*sz, MPI_CHAR, 0, 211130, comm, req + 1); + MPI_Waitall(2, req, MPI_STATUSES_IGNORE); + free(buf); + } + else { + + /* Root: output own, then those for everyone else */ + + char filename[BUFSIZ] = {}; + FILE * fp = NULL; + + sprintf(filename, "colloid-diag-%8.8d.dat", timestep); + fp = fopen(filename, "w"); + if (fp == NULL) { + pe_fatal(pe, "Failed to open diagnostic file %s\n", filename); + } + + stat_diagnostic_write(buf, count, fp); + free(buf); + + for (int nr = 1; nr < pe_mpi_size(pe); nr++) { + int rcount = 0; + + MPI_Recv(&rcount, 1, MPI_INT, nr, 211129, comm, MPI_STATUS_IGNORE); + + buf = (colloid_diagnostic_t *) malloc(rcount*sz); + assert(buf); + if (buf == NULL) pe_fatal(pe, "diagnostic buf malloc fail\n"); + + MPI_Recv(buf, rcount*sz, MPI_CHAR, nr, 211130, comm, MPI_STATUS_IGNORE); + + /* Write out remote buffer */ + stat_diagnostic_write(buf, rcount, fp); + + free(buf); + } + + if (ferror(fp)) perror("perror: "); /* Report but try to keep going. */ + fclose(fp); + } + + return 0; +} + +/***************************************************************************** + * + * stat_diagnostic_write + * + * Write out an array of count diagnostic entries to a file. + * + *****************************************************************************/ + +int stat_diagnostic_write(colloid_diagnostic_t * array, int count, + FILE * fp) { + assert(array); + assert(count >= 0); + assert(fp); + + for (int id = 0; id < count; id++) { + + colloid_diagnostic_t * dp = array + id; + + for (int ia = 0; ia < 3; ia++) { + /* total = hydrodynamic + non-hydrodynamic contributions */ + /* is total force at time of update */ + dp->ftotal[ia] = dp->fhydro[ia] + dp->fnonhy[ia]; + } + fprintf(fp, "Colloid %6d ftotal %14.7e %14.7e %14.7e\n", dp->index, + dp->ftotal[X], dp->ftotal[Y], dp->ftotal[Z]); + fprintf(fp, "Colloid %6d fhydro %14.7e %14.7e %14.7e\n", dp->index, + dp->fhydro[X], dp->fhydro[Y], dp->fhydro[Z]); + fprintf(fp, "Colloid %6d fsbulk %14.7e %14.7e %14.7e\n", dp->index, + dp->fsbulk[X], dp->fsbulk[Y], dp->fsbulk[Z]); + fprintf(fp, "Colloid %6d fsgrad %14.7e %14.7e %14.7e\n", dp->index, + dp->fsgrad[X], dp->fsgrad[Y], dp->fsgrad[Z]); + fprintf(fp, "Colloid %6d fschem %14.7e %14.7e %14.7e\n", dp->index, + dp->fschem[X], dp->fschem[Y], dp->fschem[Z]); + fprintf(fp, "Colloid %6d finter %14.7e %14.7e %14.7e\n", dp->index, + dp->finter[X], dp->finter[Y], dp->finter[Z]); + fprintf(fp, "Colloid %6d fnonhy %14.7e %14.7e %14.7e\n", dp->index, + dp->fnonhy[X], dp->fnonhy[Y], dp->fnonhy[Z]); + } + + return 0; +} + +/***************************************************************************** + * + * colloid_force_from_pth + * + *****************************************************************************/ + +int colloid_force_from_pth(colloid_t * pc, pth_t * pth, double f[3]) { + + assert(pc); + assert(pth); + + f[X] = 0.0; f[Y] = 0.0; f[Z] = 0.0; + + for (colloid_link_t * link = pc->lnk; link; link = link->next) { + + int id = -1; + int p = link->p; + int cmod = cv[p][X]*cv[p][X] + cv[p][Y]*cv[p][Y] + cv[p][Z]*cv[p][Z]; + + if (cmod != 1) continue; + + if (cv[p][X]) id = X; + if (cv[p][Y]) id = Y; + if (cv[p][Z]) id = Z; + + for (int ia = 0; ia < 3; ia++) { + f[ia] += 1.0*cv[p][id] + *pth->str[addr_rank2(pth->nsites, 3, 3, link->i, ia, id)]; + } + } + + return 0; +} + +/***************************************************************************** + * + * stat_colloids_force + * + *****************************************************************************/ + +int stat_colloids_force(colloids_info_t * cinfo, pth_t * pth, int contrib) { + + colloid_t * pc = NULL; + + colloids_info_all_head(cinfo, &pc); + + for (; pc; pc = pc->nextall) { + + switch (contrib) { + case FSCHEM: + colloid_force_from_pth(pc, pth, pc->diagnostic.fschem); + break; + case FSBULK: + colloid_force_from_pth(pc, pth, pc->diagnostic.fsbulk); + break; + case FSGRAD: + colloid_force_from_pth(pc, pth, pc->diagnostic.fsgrad); + break; + default: + /* Should not be here. Internal error. */ + assert(0); + } + } + + return 0; +} + +/***************************************************************************** + * + * stat_stress_compute + * + * Compute the stress everywhere and store using appropriate stress + * function. + * + *****************************************************************************/ + +int stat_stress_compute(pth_t * pth, fe_t * fe, fe_lc_str_ft stress) { + + int nlocal[3] = {}; + int nextra = 2; /* Kludge: Must be liquid crystal */ + + assert(pth); + assert(fe); + + cs_nlocal(pth->cs, nlocal); + + for (int ic = 1 - nextra; ic <= nlocal[X] + nextra; ic++) { + for (int jc = 1 - nextra; jc <= nlocal[Y] + nextra; jc++) { + for (int kc = 1 - nextra; kc <= nlocal[Z] + nextra; kc++) { + + double sth[3][3] = {}; + + int index = cs_index(pth->cs, ic, jc, kc); + stress((fe_lc_t *) fe, index, sth); + pth_stress_set(pth, index, sth); + + } + } + } + + return 0; +} diff --git a/src/stats_colloid_force_split.h b/src/stats_colloid_force_split.h new file mode 100644 index 000000000..906240bcc --- /dev/null +++ b/src/stats_colloid_force_split.h @@ -0,0 +1,23 @@ +/***************************************************************************** + * + * stats_colloid_force_split.h + * + * + *****************************************************************************/ + +#ifndef LUDWIG_STATS_COLLOID_FORCE_SPLIT_H +#define LUDWIG_STATS_COLLOID_FORCE_SPLIT_H + +#include "colloids.h" +#include "field.h" +#include "field_grad.h" +#include "free_energy.h" +#include "map.h" + +__host__ int stats_colloid_force_split_update(colloids_info_t * cinfo, + fe_t * fe, map_t * map, + field_t * q, + field_grad_t * q_grad); +__host__ int stats_colloid_force_split_output(colloids_info_t * cinfo, + int timestep); +#endif From 578f33b18ed7544b7032c9a4150ba7c7889d2512 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Mon, 29 Nov 2021 17:30:06 +0000 Subject: [PATCH 072/117] Remove unsed functions --- src/model.c | 54 ----------------------------------------------------- src/model.h | 3 --- 2 files changed, 57 deletions(-) diff --git a/src/model.c b/src/model.c index 37f257ebb..e5c61cf4a 100644 --- a/src/model.c +++ b/src/model.c @@ -368,60 +368,6 @@ static int lb_model_param_init(lb_t * lb) { return 0; } -/***************************************************************************** - * - * lb_nvel - * - * Return number of velocities at runtime. - * - *****************************************************************************/ - -__host__ __device__ int lb_nvel(lb_t * lb, int * nvel) { - - assert(nvel); - - *nvel = NVEL; - - return 0; -} - -/***************************************************************************** - * - * lb_ndim - * - * Return dimension of model at runtime. - * - *****************************************************************************/ - -__host__ __device__ int lb_ndim(lb_t * lb, int * ndim) { - - assert(ndim); - - *ndim = NDIM; - - return 0; -} - -/***************************************************************************** - * - * lb_nblock - * - * Return cv block size. - * - *****************************************************************************/ - -__host__ int lb_nblock(lb_t * lb, int dim, int * nblock) { - - assert(dim == X || dim == Y || dim == Z); - assert(nblock); - - if (dim == X) *nblock = CVXBLOCK; - if (dim == Y) *nblock = CVYBLOCK; - if (dim == Z) *nblock = CVZBLOCK; - - return 0; -} - /***************************************************************************** * * lb_init_rest_f diff --git a/src/model.h b/src/model.h index 3604be0db..52d2f1de6 100644 --- a/src/model.h +++ b/src/model.h @@ -108,8 +108,6 @@ __host__ int lb_io_rho_set(lb_t *lb, io_info_t * io_rho, int fin, int fout); __host__ int lb_io_info_commit(lb_t * lb, io_info_args_t args); -__host__ __device__ int lb_nvel(lb_t * lb, int * nvel); -__host__ __device__ int lb_ndim(lb_t * lb, int * ndim); __host__ __device__ int lb_ndist(lb_t * lb, int * ndist); __host__ __device__ int lb_f(lb_t * lb, int index, int p, int n, double * f); __host__ __device__ int lb_f_set(lb_t * lb, int index, int p, int n, double f); @@ -118,7 +116,6 @@ __host__ __device__ int lb_0th_moment(lb_t * lb, int index, lb_dist_enum_t nd, /* These could be __host__ __device__ pending removal of * static constants */ -__host__ int lb_nblock(lb_t * lb, int dim, int * nblock); __host__ int lb_init_rest_f(lb_t * lb, double rho0); __host__ int lb_ndist_set(lb_t * lb, int ndist); __host__ int lb_1st_moment(lb_t * lb, int index, lb_dist_enum_t nd, double g[3]); From 180bfe6e2b2b685a1b9dfc7598745c993ddcb84a Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Mon, 29 Nov 2021 17:52:22 +0000 Subject: [PATCH 073/117] Add normaliser test; add hydrodynamic mode test --- tests/unit/test_lb_model.c | 80 +++++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) diff --git a/tests/unit/test_lb_model.c b/tests/unit/test_lb_model.c index fb0c58c85..648a00f09 100644 --- a/tests/unit/test_lb_model.c +++ b/tests/unit/test_lb_model.c @@ -27,7 +27,9 @@ int test_lb_model_nhydro(void); int test_lb_model_create(int nvel); int test_lb_model_cv(const lb_model_t * model); int test_lb_model_wv(const lb_model_t * model); +int test_lb_model_na(const lb_model_t * model); int test_lb_model_ma(const lb_model_t * model); +int test_lb_model_hydrodynamic_modes(const lb_model_t * model); /***************************************************************************** * @@ -82,8 +84,11 @@ int test_lb_model_create(int nvel) { test_lb_model_cv(&model); test_lb_model_wv(&model); + test_lb_model_na(&model); test_lb_model_ma(&model); + test_lb_model_hydrodynamic_modes(&model); + lb_model_free(&model); return 0; @@ -228,6 +233,32 @@ int test_lb_model_wv(const lb_model_t * model) { return ierr; } +/***************************************************************************** + * + * test_lb_model_na + * + *****************************************************************************/ + +int test_lb_model_na(const lb_model_t * model) { + + int ifail = 0; + + assert(model); + + /* The normalisers are related to the weighted inner product of the modes */ + + for (int m = 0; m < model->nvel; m++) { + double wip = 0.0; + for (int p = 0; p < model->nvel; p++) { + wip += model->wv[p]*model->ma[m][p]*model->ma[m][p]; + } + assert(fabs(1.0/wip - model->na[m]) < DBL_EPSILON); + ifail += (fabs(1.0/wip - model->na[m]) > DBL_EPSILON); + } + + return ifail; +} + /***************************************************************************** * * test_lb_model_ma @@ -240,7 +271,7 @@ int test_lb_model_ma(const lb_model_t * model) { assert(model); - /* Check normalisers \sum_p na[i]*wv[p]*ma[i][p]*ma[j][p] = dij. */ + /* Check condition \sum_p na[i]*wv[p]*ma[i][p]*ma[j][p] = dij. */ /* The modes must all be orthonormal wrt one another. */ for (int i = 0; i < model->nvel; i++) { @@ -290,3 +321,50 @@ int test_lb_model_ma(const lb_model_t * model) { return ierr; } + +/***************************************************************************** + * + * test_lb_model_hydrodynamic_modes + * + *****************************************************************************/ + +int test_lb_model_hydrodynamic_modes(const lb_model_t * model) { + + assert(model); + + /* The hydrodynamic modes are always the same independent of model + * and must be in the right order */ + + /* One density */ + + for (int p = 0; p < model->nvel; p++) { + assert(fabs(model->ma[0][p] - 1.0) < DBL_EPSILON); + } + + /* ndim velocities */ + + for (int p = 0; p < model->nvel; p++) { + for (int q = 0; q < model->ndim; q++) { + assert(fabs(model->ma[1+q][p] - model->cv[p][q]) < DBL_EPSILON); + } + } + + /* Upper triangle of stresses */ + { + double cs2 = model->cs2; + + for (int p = 0; p < model->nvel; p++) { + int k = 1 + model->ndim; + for (int i = 0; i < model->ndim; i++) { + for (int j = i; j < model->ndim; j++) { + double dij = (i == j); + double sij = model->cv[p][i]*model->cv[p][j] - cs2*dij; + assert(fabs(model->ma[k][p] - sij) < DBL_EPSILON); + k += 1; + } + } + } + } + + return 0; +} From 1dc36729d779e5f0022b88c6283e44111bfaef50 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Mon, 29 Nov 2021 17:53:02 +0000 Subject: [PATCH 074/117] Remove compile time symbols --- tests/unit/test_model.c | 85 +---------------------------------------- tests/unit/test_prop.c | 24 +++++------- 2 files changed, 11 insertions(+), 98 deletions(-) diff --git a/tests/unit/test_model.c b/tests/unit/test_model.c index ac4f497f1..91b2713b1 100644 --- a/tests/unit/test_model.c +++ b/tests/unit/test_model.c @@ -130,77 +130,18 @@ static void test_model_constants(void) { static void test_model_velocity_set(void) { int i, j, k, p; - double sum, sumx, sumy, sumz; + double sum; LB_CS2_DOUBLE(cs2); LB_RCS2_DOUBLE(rcs2); KRONECKER_DELTA_CHAR(d_); - /* Number of hydrodynamic modes: */ - test_assert(NHYDRO == (1 + NDIM + NDIM*(NDIM+1)/2)); /* Speed of sound */ test_assert(fabs(rcs2 - 3.0) < TEST_DOUBLE_TOLERANCE); - /* Kronecker delta */ - - for (i = 0; i < NDIM; i++) { - for (j = 0; j < NDIM; j++) { - if (i == j) { - test_assert(fabs(d_[i][j] - 1.0) < TEST_DOUBLE_TOLERANCE); - } - else { - test_assert(fabs(d_[i][j] - 0.0) < TEST_DOUBLE_TOLERANCE); - } - } - } - - /* Checking cv[0] */ - - test_assert(cv[0][X] == 0); - test_assert(cv[0][Y] == 0); - test_assert(cv[0][Z] == 0); - - /* Checking cv[p][X] = -cv[NVEL-p][X] (p != 0) */ - - for (p = 1; p < NVEL; p++) { - test_assert(cv[p][X] == -cv[NVEL-p][X]); - test_assert(cv[p][Y] == -cv[NVEL-p][Y]); - test_assert(cv[p][Z] == -cv[NVEL-p][Z]); - } - - /* Sum of quadrature weights, velcoities */ - - sum = 0.0; sumx = 0.0; sumy = 0.0; sumz = 0.0; - - for (p = 0; p < NVEL; p++) { - sum += wv[p]; - sumx += wv[p]*cv[p][X]; - sumy += wv[p]*cv[p][Y]; - sumz += wv[p]*cv[p][Z]; - } - - test_assert(fabs(sum - 1.0) < TEST_DOUBLE_TOLERANCE); - test_assert(fabs(sumx) < TEST_DOUBLE_TOLERANCE); - test_assert(fabs(sumy) < TEST_DOUBLE_TOLERANCE); - test_assert(fabs(sumz) < TEST_DOUBLE_TOLERANCE); - - /* Quadratic terms = cs^2 d_ij */ - - /* Checking wv[p]*cv[p][i]*cv[p][j] */ - - for (i = 0; i < NDIM; i++) { - for (j = 0; j < NDIM; j++) { - sum = 0.0; - for (p = 0; p < NVEL; p++) { - sum += wv[p]*cv[p][i]*cv[p][j]; - } - test_assert(fabs(sum - d_[i][j]/rcs2) < TEST_DOUBLE_TOLERANCE); - } - } - /* Checking wv[p]*q_[p][i][j]... */ for (i = 0; i < NDIM; i++) { @@ -227,30 +168,6 @@ static void test_model_velocity_set(void) { } } -#ifdef NEED_TO_BE_MOVED - /* Check ma_ against rho, cv conserved quantities */ - - for (p = 0; p < NVEL; p++) { - test_assert(fabs(ma_[0][p] - 1.0) < TEST_DOUBLE_TOLERANCE); - for (i = 0; i < NDIM; i++) { - test_assert(fabs(ma_[1+i][p] - cv[p][i]) < TEST_DOUBLE_TOLERANCE); - } - } - - /* Check ma_ against stress modes */ - - for (p = 0; p < NVEL; p++) { - k = 0; - for (i = 0; i < NDIM; i++) { - for (j = i; j < NDIM; j++) { - double q_ij = cv[p][i]*cv[p][j] - cs2*d_[i][j]; - test_assert(fabs(ma_[1 + NDIM + k++][p] - q_ij) - < TEST_DOUBLE_TOLERANCE); - } - } - } -#endif - return; } diff --git a/tests/unit/test_prop.c b/tests/unit/test_prop.c index 822845d23..6322cda56 100644 --- a/tests/unit/test_prop.c +++ b/tests/unit/test_prop.c @@ -80,7 +80,6 @@ int do_test_velocity(pe_t * pe, cs_t * cs, lb_halo_enum_t halo) { int nlocal[3]; int ic, jc, kc, index, p; int nd; - int nvel; int ndist = 2; double f_actual; @@ -94,7 +93,6 @@ int do_test_velocity(pe_t * pe, cs_t * cs, lb_halo_enum_t halo) { lb_ndist_set(lb, ndist); lb_init(lb); - lb_nvel(lb, &nvel); cs_nlocal(cs, nlocal); @@ -107,8 +105,8 @@ int do_test_velocity(pe_t * pe, cs_t * cs, lb_halo_enum_t halo) { index = cs_index(cs, ic, jc, kc); for (nd = 0; nd < ndist; nd++) { - for (p = 0; p < nvel; p++) { - lb_f_set(lb, index, p, nd, 1.0*(p + nd*NVEL)); + for (p = 0; p < lb->model.nvel; p++) { + lb_f_set(lb, index, p, nd, 1.0*(p + nd*lb->model.nvel)); } } @@ -138,9 +136,9 @@ int do_test_velocity(pe_t * pe, cs_t * cs, lb_halo_enum_t halo) { index = cs_index(cs, ic, jc, kc); for (nd = 0; nd < ndist; nd++) { - for (p = 0; p < nvel; p++) { + for (p = 0; p < lb->model.nvel; p++) { lb_f(lb, index, p, nd, &f_actual); - assert(fabs(f_actual - 1.0*(p + nd*NVEL)) < DBL_EPSILON); + assert(fabs(f_actual - 1.0*(p + nd*lb->model.nvel)) < DBL_EPSILON); } } } @@ -171,7 +169,6 @@ int do_test_source_destination(pe_t * pe, cs_t * cs, lb_halo_enum_t halo) { int ic, jc, kc, index, p; int nd; int ndist = 2; - int nvel; int isource, jsource, ksource; double f_actual, f_expect; double ltot[3]; @@ -185,7 +182,6 @@ int do_test_source_destination(pe_t * pe, cs_t * cs, lb_halo_enum_t halo) { assert(lb); lb_ndist_set(lb, ndist); lb_init(lb); - lb_nvel(lb, &nvel); cs_ltot(cs, ltot); cs_ntotal(cs, ntotal); @@ -204,7 +200,7 @@ int do_test_source_destination(pe_t * pe, cs_t * cs, lb_halo_enum_t halo) { ltot[Z]*(offset[Y] + jc) + (offset[Z] + kc); for (nd = 0; nd < ndist; nd++) { - for (p = 0; p < nvel; p++) { + for (p = 0; p < lb->model.nvel; p++) { lb_f_set(lb, index, p, nd, f_actual); } } @@ -234,14 +230,14 @@ int do_test_source_destination(pe_t * pe, cs_t * cs, lb_halo_enum_t halo) { index = cs_index(cs, ic, jc, kc); for (nd = 0; nd < ndist; nd++) { - for (p = 0; p < nvel; p++) { - isource = offset[X] + ic - cv[p][X]; + for (p = 0; p < lb->model.nvel; p++) { + isource = offset[X] + ic - lb->model.cv[p][X]; if (isource == 0) isource += ntotal[X]; if (isource == ntotal[X] + 1) isource = 1; - jsource = offset[Y] + jc - cv[p][Y]; + jsource = offset[Y] + jc - lb->model.cv[p][Y]; if (jsource == 0) jsource += ntotal[Y]; if (jsource == ntotal[Y] + 1) jsource = 1; - ksource = offset[Z] + kc - cv[p][Z]; + ksource = offset[Z] + kc - lb->model.cv[p][Z]; if (ksource == 0) ksource += ntotal[Z]; if (ksource == ntotal[Z] + 1) ksource = 1; @@ -249,7 +245,7 @@ int do_test_source_destination(pe_t * pe, cs_t * cs, lb_halo_enum_t halo) { lb_f(lb, index, p, nd, &f_actual); /* In case of d2q9, propagation is only for kc = 1 */ - if (NDIM == 2 && kc > 1) f_actual = f_expect; + if (lb->model.ndim == 2 && kc > 1) f_actual = f_expect; assert(fabs(f_actual - f_expect) < DBL_EPSILON); } From 43f02c9ec4b6529d733b783fce01abd3392303eb Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Wed, 1 Dec 2021 16:55:15 +0000 Subject: [PATCH 075/117] Bug fix to discount inactive links --- src/stats_colloid_force_split.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/stats_colloid_force_split.c b/src/stats_colloid_force_split.c index d365844a3..df01d25ea 100644 --- a/src/stats_colloid_force_split.c +++ b/src/stats_colloid_force_split.c @@ -208,6 +208,8 @@ int stat_diagnostic_write(colloid_diagnostic_t * array, int count, dp->fschem[X], dp->fschem[Y], dp->fschem[Z]); fprintf(fp, "Colloid %6d finter %14.7e %14.7e %14.7e\n", dp->index, dp->finter[X], dp->finter[Y], dp->finter[Z]); + fprintf(fp, "Colloid %6d fbuild %14.7e %14.7e %14.7e\n", dp->index, + dp->fbuild[X], dp->fbuild[Y], dp->fbuild[Z]); fprintf(fp, "Colloid %6d fnonhy %14.7e %14.7e %14.7e\n", dp->index, dp->fnonhy[X], dp->fnonhy[Y], dp->fnonhy[Z]); } @@ -230,6 +232,8 @@ int colloid_force_from_pth(colloid_t * pc, pth_t * pth, double f[3]) { for (colloid_link_t * link = pc->lnk; link; link = link->next) { + if (link->status != LINK_FLUID) continue; + int id = -1; int p = link->p; int cmod = cv[p][X]*cv[p][X] + cv[p][Y]*cv[p][Y] + cv[p][Z]*cv[p][Z]; From 169dc04d726b4c61a7514493f4df76769454aba7 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Wed, 1 Dec 2021 16:55:52 +0000 Subject: [PATCH 076/117] Add diagnostic for correction force --- src/bbl.c | 7 +++++++ src/colloid_sums.c | 4 +++- src/colloids.h | 1 + 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/bbl.c b/src/bbl.c index b035184d7..68b04607b 100644 --- a/src/bbl.c +++ b/src/bbl.c @@ -404,6 +404,13 @@ static int bbl_pass1(bbl_t * bbl, lb_t * lb, colloids_info_t * cinfo) { if (pc->s.type == COLLOID_TYPE_SUBGRID) continue; + /* Diagnostic record of f0 before additions are made. */ + /* Really, f0 should not be used for dual purposes... */ + + pc->diagnostic.fbuild[X] = pc->f0[X]; + pc->diagnostic.fbuild[Y] = pc->f0[Y]; + pc->diagnostic.fbuild[Z] = pc->f0[Z]; + p_link = pc->lnk; for (i = 0; i < 21; i++) { diff --git a/src/colloid_sums.c b/src/colloid_sums.c index 754f3e3f5..a105bdc20 100644 --- a/src/colloid_sums.c +++ b/src/colloid_sums.c @@ -78,7 +78,7 @@ static int colloid_sums_m7(colloid_sum_t * sum, int, int, int, int); /* Message sizes (doubles) */ /* NULL is a dummy zero size */ -static const int msize_[COLLOID_SUM_MAX] = {0, 10, 35, 7, 4, 6, 7, 10}; +static const int msize_[COLLOID_SUM_MAX] = {0, 10, 35, 7, 4, 6, 7, 13}; /* The following are used for internal communication */ @@ -831,6 +831,7 @@ static int colloid_sums_m7(colloid_sum_t * sum, int ic, int jc, int kc, sum->send[n++] = pc->diagnostic.fsbulk[ia]; sum->send[n++] = pc->diagnostic.fsgrad[ia]; sum->send[n++] = pc->diagnostic.fschem[ia]; + sum->send[n++] = pc->diagnostic.fbuild[ia]; } assert(n == (noff + npart + 1)*sum->msize); } @@ -845,6 +846,7 @@ static int colloid_sums_m7(colloid_sum_t * sum, int ic, int jc, int kc, pc->diagnostic.fsbulk[ia] += sum->recv[n++]; pc->diagnostic.fsgrad[ia] += sum->recv[n++]; pc->diagnostic.fschem[ia] += sum->recv[n++]; + pc->diagnostic.fbuild[ia] += sum->recv[n++]; } assert(n == (noff + npart + 1)*sum->msize); } diff --git a/src/colloids.h b/src/colloids.h index 363e66f56..27285a147 100644 --- a/src/colloids.h +++ b/src/colloids.h @@ -34,6 +34,7 @@ struct colloid_diagnostic_s { double fsgrad[3]; /* Gradient stress (divergence) contribution */ double fschem[3]; /* Total "chemical" stress contribution (is fd2 + fd3) */ double finter[3]; /* External field/interaction contribution */ + double fbuild[3]; /* Force corrections from changes in discrete shape */ double fnonhy[3]; /* Total non-hydrodynamic (interpendent of fd0-fd1) */ /* Might want to split external field / conservative interaction From 1cd385d351b315e92e0347503f281636b17d5b99 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Fri, 3 Dec 2021 17:25:52 +0000 Subject: [PATCH 077/117] Patch to allow GPU tests to pass --- src/subgrid.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/subgrid.c b/src/subgrid.c index 00ad2bfe5..03a1f754f 100644 --- a/src/subgrid.c +++ b/src/subgrid.c @@ -72,6 +72,11 @@ int subgrid_force_from_particles(colloids_info_t * cinfo, hydro_t * hydro, subgrid_wall_lubrication(cinfo, wall); colloid_sums_halo(cinfo, COLLOID_SUM_FORCE_EXT_ONLY); + /* While there is no device implementation, must copy back-and forth + * the force. */ + + hydro_memcpy(hydro, tdpMemcpyDeviceToHost); + /* Loop through all cells (including the halo cells) */ for (ic = 0; ic <= ncell[X] + 1; ic++) { @@ -153,6 +158,8 @@ int subgrid_force_from_particles(colloids_info_t * cinfo, hydro_t * hydro, } } + hydro_memcpy(hydro, tdpMemcpyHostToDevice); + return 0; } @@ -274,6 +281,11 @@ static int subgrid_interpolation(colloids_info_t * cinfo, hydro_t * hydro) { cs_nlocal_offset(cinfo->cs, offset); colloids_info_ncell(cinfo, ncell); + /* While there is no subgrid device implementation, + need to recover the current velocity. */ + + hydro_memcpy(hydro, tdpMemcpyDeviceToHost); + /* Loop through all cells (including the halo cells) and set * the velocity at each particle to zero for this step. */ From 8d11172602078e5cbcee1a9ba6a830fc440ffd25 Mon Sep 17 00:00:00 2001 From: not populated Date: Mon, 6 Dec 2021 10:31:32 +0000 Subject: [PATCH 078/117] Indicate results for single node standard --- tests/performance/cray-archer2-sc16/input | 98 ++ tests/performance/cray-archer2-sc16/qscript | 37 + .../cray-archer2-sc16/slurm-864808.out | 946 ++++++++++++++++++ 3 files changed, 1081 insertions(+) create mode 100644 tests/performance/cray-archer2-sc16/input create mode 100644 tests/performance/cray-archer2-sc16/qscript create mode 100644 tests/performance/cray-archer2-sc16/slurm-864808.out diff --git a/tests/performance/cray-archer2-sc16/input b/tests/performance/cray-archer2-sc16/input new file mode 100644 index 000000000..bf2bcf8e3 --- /dev/null +++ b/tests/performance/cray-archer2-sc16/input @@ -0,0 +1,98 @@ +############################################################################## +# +# Ludwig input file SC16 benchmark +# 1 episode of diagnostic output at 1000 steps is representative. +# +############################################################################## + +N_start 0 +N_cycles 1000 + +############################################################################## +# +# System and MPI +# +############################################################################## + +size 128_128_128 +reduced_halo no + +############################################################################## +# +# Fluid parameters +# +############################################################################## + +viscosity 1.0 + +isothermal_fluctuations off + +############################################################################## +# +# Free energy parameters +# +############################################################################### + +free_energy lc_blue_phase + +fd_advection_scheme_order 3 +fd_gradient_calculation 3d_7pt_fluid + +############################################################################### +# +# Blue Phase free energy +# +############################################################################### + +lc_a0 0.01 +lc_gamma 3.0 +lc_q0 0.19635 +lc_kappa0 0.000648456 +lc_kappa1 0.000648456 +lc_xi 0.7 + +lc_Gamma 0.5 + +lc_q_initialisation twist +lc_q_init_amplitude 0.333333333333333 +lc_init_redshift 1.0 + +lc_anchoring_method two +lc_wall_anchoring normal +lc_coll_anchoring normal +lc_anchoring_strength_colloid 0.002593824 + +############################################################################### +# +# Colloid parameters +# +############################################################################### + +colloid_init no_colloids + +############################################################################### +# +# Periodic conditions / boundaries +# +############################################################################### + +periodicity 1_1_1 + +############################################################################### +# +# Output frequency and type +# +############################################################################### + +freq_statistics 1000 +config_at_end no + +############################################################################### +# +# Miscellaneous +# +# random_seed +ve integer is the random number generator seed +# +############################################################################### + +random_seed 8361235 diff --git a/tests/performance/cray-archer2-sc16/qscript b/tests/performance/cray-archer2-sc16/qscript new file mode 100644 index 000000000..95e69a973 --- /dev/null +++ b/tests/performance/cray-archer2-sc16/qscript @@ -0,0 +1,37 @@ +#!/bin/bash + +#SBATCH --exclusive +#SBATCH --export=none +#SBATCH --partition=standard +#SBATCH --qos=standard + +#SBATCH --nodes=1 +#SBATCH --time=0:20:00 +#SBATCH --ntasks-per-node=8 + +#SBATCH --cpus-per-task=16 +#SBATCH --distribution=block:block +#SBATCH --hint=nomultithread + +module load PrgEnv-gnu +module list + +export OMP_NUM_THREADS=16 +export OMP_PLACES=cores + +module load xthi + +srun -n 1 xthi +srun -n 1 ./Ludwig.exe + +srun -n 2 xthi +srun -n 2 ./Ludwig.exe + +srun -n 4 xthi +srun -n 4 ./Ludwig.exe + +srun -n 8 xthi +srun -n 8 ./Ludwig.exe + + + diff --git a/tests/performance/cray-archer2-sc16/slurm-864808.out b/tests/performance/cray-archer2-sc16/slurm-864808.out new file mode 100644 index 000000000..3aac567d1 --- /dev/null +++ b/tests/performance/cray-archer2-sc16/slurm-864808.out @@ -0,0 +1,946 @@ + +Lmod is automatically replacing "cce/11.0.4" with "gcc/10.2.0". + + +Lmod is automatically replacing "PrgEnv-cray/8.0.0" with "PrgEnv-gnu/8.0.0". + + +Due to MODULEPATH changes, the following have been reloaded: + 1) cray-mpich/8.1.4 + + +Currently Loaded Modules: + 1) gcc/10.2.0 8) cray-mpich/8.1.4 + 2) craype/2.7.6 9) cray-libsci/21.04.1.1 + 3) craype-x86-rome 10) bolt/0.7 + 4) libfabric/1.11.0.4.71 11) epcc-setup-env + 5) craype-network-ofi 12) load-epcc-module + 6) perftools-base/21.02.0 13) PrgEnv-gnu/8.0.0 + 7) xpmem/2.2.40-7.0.1.0_2.7__g1d7a24d.shasta + + + +Node summary for 1 nodes: +Node 0, hostname nid001324, mpi 1, omp 16, executable xthi +MPI summary: 1 ranks +Node 0, rank 0, thread 0, (affinity = 0) +Node 0, rank 0, thread 1, (affinity = 1) +Node 0, rank 0, thread 2, (affinity = 2) +Node 0, rank 0, thread 3, (affinity = 3) +Node 0, rank 0, thread 4, (affinity = 4) +Node 0, rank 0, thread 5, (affinity = 5) +Node 0, rank 0, thread 6, (affinity = 6) +Node 0, rank 0, thread 7, (affinity = 7) +Node 0, rank 0, thread 8, (affinity = 8) +Node 0, rank 0, thread 9, (affinity = 9) +Node 0, rank 0, thread 10, (affinity = 10) +Node 0, rank 0, thread 11, (affinity = 11) +Node 0, rank 0, thread 12, (affinity = 12) +Node 0, rank 0, thread 13, (affinity = 13) +Node 0, rank 0, thread 14, (affinity = 14) +Node 0, rank 0, thread 15, (affinity = 15) +Welcome to Ludwig v0.14.0 (Serial version running on 1 process) +Start time: Mon Dec 6 09:40:29 2021 + +Compiler: + name: Gnu 11.2.0 + version-string: 11.2.0 20210728 (Cray Inc.) + +Target thread model: OpenMP. +OpenMP threads: 16; maximum number of threads: 16. + +Read 28 user parameters from input + +System details +-------------- +System size: 128 128 128 +Decomposition: 1 1 1 +Local domain: 128 128 128 +Periodic: 1 1 1 +Halo nhalo: 2 +Reorder: true +Initialised: 1 + +Free energy details +------------------- + +Blue phase free energy selected. + +Liquid crystal blue phase free energy +Bulk parameter A0: = 1.0000000e-02 +Magnitude of order gamma = 3.0000000e+00 +Pitch wavevector q0 = 1.9635000e-01 +... gives pitch length = 3.1999925e+01 +Elastic constant kappa0 = 6.4845600e-04 +Elastic constant kappa1 = 6.4845600e-04 +Amplitude (uniaxial) order = 3.3333333e-01 +Effective aspect ratio xi = 7.0000000e-01 +Chirality = 3.0000080e-01 +Reduced temperature = 0.0000000e+00 +Initial redshift = 1.0000000e+00 +Dynamic redshift update = no +Liquid crystal activity No + +Liquid crystal anchoring +Anchoring method: = two +Anchoring type (colloids): = normal +Anchoring type (walls): = normal +Surface free energy (colloid)w1: = 2.5938240e-03 +Surface free energy (colloid)w2: = 0.0000000e+00 +Surface free energy (wall) w1: = 0.0000000e+00 +Surface free energy (wall) w2: = 0.0000000e+00 +Ratio (colloid) w1/kappa0: = 4.0000000e+00 +Ratio (wall) w1/kappa0: = 0.0000000e+00 +Computed surface order f(gamma) = 3.3333333e-01 + +Using Beris-Edwards solver: +Rotational diffusion const = 5.0000000e-01 +LC fluctuations: = off + +System properties +---------------- +Mean fluid density: 1.00000e+00 +Shear viscosity 1.00000e+00 +Bulk viscosity 1.00000e+00 +Temperature 0.00000e+00 +External body force density 0.00000e+00 0.00000e+00 0.00000e+00 +External E-field amplitude 0.00000e+00 0.00000e+00 0.00000e+00 +External E-field frequency 0.00000e+00 +External magnetic field 0.00000e+00 0.00000e+00 0.00000e+00 + +Lattice Boltzmann distributions +------------------------------- +Model: d3q19 +SIMD vector len: 2 +Number of sets: 1 +Halo type: full +Input format: binary +Output format: binary +I/O grid: 1 1 1 + +Lattice Boltzmann collision +--------------------------- +Relaxation time scheme: M10 +Hydrodynamic modes: on +Ghost modes: on +Isothermal fluctuations: off +Shear relaxation time: 3.50000e+00 +Bulk relaxation time: 3.50000e+00 +Ghost relaxation time: 1.00000e+00 +[User ] Random number seed: 8361235 + +Hydrodynamics +------------- +Hydrodynamics: on + +Order parameter I/O +------------------- +Order parameter I/O format: +I/O decomposition: 1 1 1 + +Advection scheme order: 3 +Gradient calculation: 3d_7pt_fluid + + +Initialising Q_ab to cholesteric +Helical axis Z +Initial conditions. + +Scalars - total mean variance min max +[rho] 2097152.00 1.00000000000 2.2204460e-16 1.00000000000 1.00000000000 +[phi] 1.7476388e+05 8.3333910e-02 3.1250069e-02 -1.6666667e-01 3.3333333e-01 +[phi] 2.4079829e-01 1.1482157e-07 3.1249931e-02 -2.5000000e-01 2.5000000e-01 +[phi] 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 +[phi] 1.7476146e+05 8.3332756e-02 3.1250069e-02 -1.6666667e-01 3.3333333e-01 +[phi] 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 + +Momentum - x y z +[total ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 +[fluid ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 + +Starting time step loop. + +Scalars - total mean variance min max +[rho] 2097152.00 1.00000000003 8.8264507e-11 0.99999999991 1.00000000302 +[phi] 1.7303123e+05 8.2507719e-02 3.1029972e-02 -1.6661093e-01 3.3162533e-01 +[phi] 2.2790390e-01 1.0867305e-07 3.1029859e-02 -2.4911811e-01 2.4911811e-01 +[phi] -1.9812350e-12 -9.4472649e-19 3.0065582e-33 -1.5099951e-16 1.1650947e-16 +[phi] 1.7302894e+05 8.2506627e-02 3.1029972e-02 -1.6661097e-01 3.3162528e-01 +[phi] -2.7354779e-12 -1.3043775e-18 4.4863135e-33 -1.8828475e-16 2.0412098e-16 + +Free energies - timestep f v f/v f_bulk/v f_grad/v redshift +[fe] 1000 -1.4130150160e+02 2.0971520000e+06 -6.7377806475e-05 -6.9424084750e-05 2.0462782744e-06 1.0000000000e+00 + +Momentum - x y z +[total ] 4.3200998e-11 2.2737423e-11 -4.2518877e-11 +[fluid ] 4.3200998e-11 2.2737423e-11 -4.2518877e-11 + +Velocity - x y z +[minimum ] -3.8161432e-17 -2.0816475e-17 -1.6327987e-12 +[maximum ] 9.7144615e-17 5.2056455e-17 1.6324896e-12 + +Completed cycle 1000 + +Timer resolution: 2e-08 second + +Timer statistics + Section: tmin tmax total + Total: 246.751 246.751 246.751 246.751117 (1 call) + Time step loop: 0.239 0.470 243.768 0.243768 (1000 calls) + Propagation: 0.044 0.047 43.761 0.043761 (1000 calls) + Propagtn (krnl) : 0.044 0.047 43.756 0.043756 (1000 calls) + Collision: 0.024 0.029 24.071 0.024071 (1000 calls) + Collision (krnl) : 0.024 0.029 24.063 0.024063 (1000 calls) + Lattice halos: 0.006 0.011 6.759 0.006759 (1000 calls) + phi gradients: 0.028 0.228 28.781 0.028781 (1000 calls) + phi grad (krnl) : 0.025 0.036 25.072 0.025072 (1000 calls) + phi halos: 0.003 0.150 3.660 0.003660 (1000 calls) + BBL: 0.000 0.000 0.001 0.000001 (1000 calls) + Force calculation: 0.039 0.044 39.437 0.039437 (1000 calls) + Phi force (krnl) : 0.013 0.015 12.983 0.012983 (1000 calls) + phi update: 0.093 0.117 97.805 0.097805 (1000 calls) + Velocity Halo : 0.001 0.001 0.849 0.000849 (1000 calls) +BE mol field (krnl) : 0.019 0.023 18.758 0.018758 (1000 calls) +BP BE update (krnl) : 0.021 0.027 21.079 0.021079 (1000 calls) + Advectn (krnl) : 0.030 0.048 34.537 0.034537 (1000 calls) + Advectn BCS (krnl) : 0.019 0.020 19.143 0.019143 (1000 calls) + Free1: 0.000 1.618 1.620 0.001620 (1000 calls) +End time: Mon Dec 6 09:44:36 2021 +Ludwig finished normally. +Node summary for 1 nodes: +Node 0, hostname nid001324, mpi 2, omp 16, executable xthi +MPI summary: 2 ranks +Node 0, rank 0, thread 0, (affinity = 0) +Node 0, rank 0, thread 1, (affinity = 1) +Node 0, rank 0, thread 2, (affinity = 2) +Node 0, rank 0, thread 3, (affinity = 3) +Node 0, rank 0, thread 4, (affinity = 4) +Node 0, rank 0, thread 5, (affinity = 5) +Node 0, rank 0, thread 6, (affinity = 6) +Node 0, rank 0, thread 7, (affinity = 7) +Node 0, rank 0, thread 8, (affinity = 8) +Node 0, rank 0, thread 9, (affinity = 9) +Node 0, rank 0, thread 10, (affinity = 10) +Node 0, rank 0, thread 11, (affinity = 11) +Node 0, rank 0, thread 12, (affinity = 12) +Node 0, rank 0, thread 13, (affinity = 13) +Node 0, rank 0, thread 14, (affinity = 14) +Node 0, rank 0, thread 15, (affinity = 15) +Node 0, rank 1, thread 0, (affinity = 16) +Node 0, rank 1, thread 1, (affinity = 17) +Node 0, rank 1, thread 2, (affinity = 18) +Node 0, rank 1, thread 3, (affinity = 19) +Node 0, rank 1, thread 4, (affinity = 20) +Node 0, rank 1, thread 5, (affinity = 21) +Node 0, rank 1, thread 6, (affinity = 22) +Node 0, rank 1, thread 7, (affinity = 23) +Node 0, rank 1, thread 8, (affinity = 24) +Node 0, rank 1, thread 9, (affinity = 25) +Node 0, rank 1, thread 10, (affinity = 26) +Node 0, rank 1, thread 11, (affinity = 27) +Node 0, rank 1, thread 12, (affinity = 28) +Node 0, rank 1, thread 13, (affinity = 29) +Node 0, rank 1, thread 14, (affinity = 30) +Node 0, rank 1, thread 15, (affinity = 31) +Welcome to Ludwig v0.14.0 (MPI version running on 2 processes) +Start time: Mon Dec 6 09:44:38 2021 + +Compiler: + name: Gnu 11.2.0 + version-string: 11.2.0 20210728 (Cray Inc.) + +Target thread model: OpenMP. +OpenMP threads: 16; maximum number of threads: 16. + +Read 28 user parameters from input + +System details +-------------- +System size: 128 128 128 +Decomposition: 2 1 1 +Local domain: 64 128 128 +Periodic: 1 1 1 +Halo nhalo: 2 +Reorder: true +Initialised: 1 + +Free energy details +------------------- + +Blue phase free energy selected. + +Liquid crystal blue phase free energy +Bulk parameter A0: = 1.0000000e-02 +Magnitude of order gamma = 3.0000000e+00 +Pitch wavevector q0 = 1.9635000e-01 +... gives pitch length = 3.1999925e+01 +Elastic constant kappa0 = 6.4845600e-04 +Elastic constant kappa1 = 6.4845600e-04 +Amplitude (uniaxial) order = 3.3333333e-01 +Effective aspect ratio xi = 7.0000000e-01 +Chirality = 3.0000080e-01 +Reduced temperature = 0.0000000e+00 +Initial redshift = 1.0000000e+00 +Dynamic redshift update = no +Liquid crystal activity No + +Liquid crystal anchoring +Anchoring method: = two +Anchoring type (colloids): = normal +Anchoring type (walls): = normal +Surface free energy (colloid)w1: = 2.5938240e-03 +Surface free energy (colloid)w2: = 0.0000000e+00 +Surface free energy (wall) w1: = 0.0000000e+00 +Surface free energy (wall) w2: = 0.0000000e+00 +Ratio (colloid) w1/kappa0: = 4.0000000e+00 +Ratio (wall) w1/kappa0: = 0.0000000e+00 +Computed surface order f(gamma) = 3.3333333e-01 + +Using Beris-Edwards solver: +Rotational diffusion const = 5.0000000e-01 +LC fluctuations: = off + +System properties +---------------- +Mean fluid density: 1.00000e+00 +Shear viscosity 1.00000e+00 +Bulk viscosity 1.00000e+00 +Temperature 0.00000e+00 +External body force density 0.00000e+00 0.00000e+00 0.00000e+00 +External E-field amplitude 0.00000e+00 0.00000e+00 0.00000e+00 +External E-field frequency 0.00000e+00 +External magnetic field 0.00000e+00 0.00000e+00 0.00000e+00 + +Lattice Boltzmann distributions +------------------------------- +Model: d3q19 +SIMD vector len: 2 +Number of sets: 1 +Halo type: full +Input format: binary +Output format: binary +I/O grid: 1 1 1 + +Lattice Boltzmann collision +--------------------------- +Relaxation time scheme: M10 +Hydrodynamic modes: on +Ghost modes: on +Isothermal fluctuations: off +Shear relaxation time: 3.50000e+00 +Bulk relaxation time: 3.50000e+00 +Ghost relaxation time: 1.00000e+00 +[User ] Random number seed: 8361235 + +Hydrodynamics +------------- +Hydrodynamics: on + +Order parameter I/O +------------------- +Order parameter I/O format: +I/O decomposition: 1 1 1 + +Advection scheme order: 3 +Gradient calculation: 3d_7pt_fluid + + +Initialising Q_ab to cholesteric +Helical axis Z +Initial conditions. + +Scalars - total mean variance min max +[rho] 2097152.00 1.00000000000 2.2204460e-16 1.00000000000 1.00000000000 +[phi] 1.7476388e+05 8.3333910e-02 3.1250069e-02 -1.6666667e-01 3.3333333e-01 +[phi] 2.4079829e-01 1.1482157e-07 3.1249931e-02 -2.5000000e-01 2.5000000e-01 +[phi] 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 +[phi] 1.7476146e+05 8.3332756e-02 3.1250069e-02 -1.6666667e-01 3.3333333e-01 +[phi] 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 + +Momentum - x y z +[total ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 +[fluid ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 + +Starting time step loop. + +Scalars - total mean variance min max +[rho] 2097152.00 0.99999999998 3.4473313e-11 0.99999999991 1.00000000302 +[phi] 1.7303123e+05 8.2507719e-02 3.1029972e-02 -1.6661093e-01 3.3162533e-01 +[phi] 2.2790390e-01 1.0867305e-07 3.1029859e-02 -2.4911811e-01 2.4911811e-01 +[phi] -1.9812350e-12 -9.4472649e-19 3.0065582e-33 -1.5099951e-16 1.1650947e-16 +[phi] 1.7302894e+05 8.2506627e-02 3.1029972e-02 -1.6661097e-01 3.3162528e-01 +[phi] -2.7354779e-12 -1.3043775e-18 4.4863135e-33 -1.8828475e-16 2.0412098e-16 + +Free energies - timestep f v f/v f_bulk/v f_grad/v redshift +[fe] 1000 -1.4130150161e+02 2.0971520000e+06 -6.7377806476e-05 -6.9424084751e-05 2.0462782744e-06 1.0000000000e+00 + +Momentum - x y z +[total ] 4.3200998e-11 2.2737479e-11 -4.2518877e-11 +[fluid ] 4.3200998e-11 2.2737479e-11 -4.2518877e-11 + +Velocity - x y z +[minimum ] -3.8161432e-17 -2.0816475e-17 -1.6327987e-12 +[maximum ] 9.7144615e-17 5.2056455e-17 1.6324896e-12 + +Completed cycle 1000 + +Timer resolution: 2e-08 second + +Timer statistics + Section: tmin tmax total + Total: 124.773 124.774 124.774 124.773611 (1 call) + Time step loop: 0.122 0.173 123.311 0.123311 (1000 calls) + Propagation: 0.022 0.024 22.599 0.022599 (1000 calls) + Propagtn (krnl) : 0.022 0.024 22.593 0.022593 (1000 calls) + Collision: 0.011 0.014 11.581 0.011581 (1000 calls) + Collision (krnl) : 0.011 0.014 11.573 0.011573 (1000 calls) + Lattice halos: 0.004 0.009 4.112 0.004112 (1000 calls) + phi gradients: 0.015 0.045 15.028 0.015028 (1000 calls) + phi grad (krnl) : 0.013 0.019 13.032 0.013032 (1000 calls) + phi halos: 0.002 0.026 1.990 0.001990 (1000 calls) + BBL: 0.000 0.000 0.001 0.000001 (1000 calls) + Force calculation: 0.020 0.023 20.207 0.020207 (1000 calls) + Phi force (krnl) : 0.007 0.008 6.744 0.006744 (1000 calls) + phi update: 0.047 0.061 48.383 0.048383 (1000 calls) + Velocity Halo : 0.001 0.004 0.630 0.000630 (1000 calls) +BE mol field (krnl) : 0.010 0.013 10.375 0.010375 (1000 calls) +BP BE update (krnl) : 0.011 0.013 10.666 0.010666 (1000 calls) + Advectn (krnl) : 0.015 0.025 16.024 0.016024 (1000 calls) + Advectn BCS (krnl) : 0.009 0.009 8.937 0.008937 (1000 calls) + Free1: 0.000 0.812 0.813 0.000813 (1000 calls) +End time: Mon Dec 6 09:46:43 2021 +Ludwig finished normally. +Node summary for 1 nodes: +Node 0, hostname nid001324, mpi 4, omp 16, executable xthi +MPI summary: 4 ranks +Node 0, rank 0, thread 0, (affinity = 0) +Node 0, rank 0, thread 1, (affinity = 1) +Node 0, rank 0, thread 2, (affinity = 2) +Node 0, rank 0, thread 3, (affinity = 3) +Node 0, rank 0, thread 4, (affinity = 4) +Node 0, rank 0, thread 5, (affinity = 5) +Node 0, rank 0, thread 6, (affinity = 6) +Node 0, rank 0, thread 7, (affinity = 7) +Node 0, rank 0, thread 8, (affinity = 8) +Node 0, rank 0, thread 9, (affinity = 9) +Node 0, rank 0, thread 10, (affinity = 10) +Node 0, rank 0, thread 11, (affinity = 11) +Node 0, rank 0, thread 12, (affinity = 12) +Node 0, rank 0, thread 13, (affinity = 13) +Node 0, rank 0, thread 14, (affinity = 14) +Node 0, rank 0, thread 15, (affinity = 15) +Node 0, rank 1, thread 0, (affinity = 16) +Node 0, rank 1, thread 1, (affinity = 17) +Node 0, rank 1, thread 2, (affinity = 18) +Node 0, rank 1, thread 3, (affinity = 19) +Node 0, rank 1, thread 4, (affinity = 20) +Node 0, rank 1, thread 5, (affinity = 21) +Node 0, rank 1, thread 6, (affinity = 22) +Node 0, rank 1, thread 7, (affinity = 23) +Node 0, rank 1, thread 8, (affinity = 24) +Node 0, rank 1, thread 9, (affinity = 25) +Node 0, rank 1, thread 10, (affinity = 26) +Node 0, rank 1, thread 11, (affinity = 27) +Node 0, rank 1, thread 12, (affinity = 28) +Node 0, rank 1, thread 13, (affinity = 29) +Node 0, rank 1, thread 14, (affinity = 30) +Node 0, rank 1, thread 15, (affinity = 31) +Node 0, rank 2, thread 0, (affinity = 32) +Node 0, rank 2, thread 1, (affinity = 33) +Node 0, rank 2, thread 2, (affinity = 34) +Node 0, rank 2, thread 3, (affinity = 35) +Node 0, rank 2, thread 4, (affinity = 36) +Node 0, rank 2, thread 5, (affinity = 37) +Node 0, rank 2, thread 6, (affinity = 38) +Node 0, rank 2, thread 7, (affinity = 39) +Node 0, rank 2, thread 8, (affinity = 40) +Node 0, rank 2, thread 9, (affinity = 41) +Node 0, rank 2, thread 10, (affinity = 42) +Node 0, rank 2, thread 11, (affinity = 43) +Node 0, rank 2, thread 12, (affinity = 44) +Node 0, rank 2, thread 13, (affinity = 45) +Node 0, rank 2, thread 14, (affinity = 46) +Node 0, rank 2, thread 15, (affinity = 47) +Node 0, rank 3, thread 0, (affinity = 48) +Node 0, rank 3, thread 1, (affinity = 49) +Node 0, rank 3, thread 2, (affinity = 50) +Node 0, rank 3, thread 3, (affinity = 51) +Node 0, rank 3, thread 4, (affinity = 52) +Node 0, rank 3, thread 5, (affinity = 53) +Node 0, rank 3, thread 6, (affinity = 54) +Node 0, rank 3, thread 7, (affinity = 55) +Node 0, rank 3, thread 8, (affinity = 56) +Node 0, rank 3, thread 9, (affinity = 57) +Node 0, rank 3, thread 10, (affinity = 58) +Node 0, rank 3, thread 11, (affinity = 59) +Node 0, rank 3, thread 12, (affinity = 60) +Node 0, rank 3, thread 13, (affinity = 61) +Node 0, rank 3, thread 14, (affinity = 62) +Node 0, rank 3, thread 15, (affinity = 63) +Welcome to Ludwig v0.14.0 (MPI version running on 4 processes) +Start time: Mon Dec 6 09:46:45 2021 + +Compiler: + name: Gnu 11.2.0 + version-string: 11.2.0 20210728 (Cray Inc.) + +Target thread model: OpenMP. +OpenMP threads: 16; maximum number of threads: 16. + +Read 28 user parameters from input + +System details +-------------- +System size: 128 128 128 +Decomposition: 2 2 1 +Local domain: 64 64 128 +Periodic: 1 1 1 +Halo nhalo: 2 +Reorder: true +Initialised: 1 + +Free energy details +------------------- + +Blue phase free energy selected. + +Liquid crystal blue phase free energy +Bulk parameter A0: = 1.0000000e-02 +Magnitude of order gamma = 3.0000000e+00 +Pitch wavevector q0 = 1.9635000e-01 +... gives pitch length = 3.1999925e+01 +Elastic constant kappa0 = 6.4845600e-04 +Elastic constant kappa1 = 6.4845600e-04 +Amplitude (uniaxial) order = 3.3333333e-01 +Effective aspect ratio xi = 7.0000000e-01 +Chirality = 3.0000080e-01 +Reduced temperature = 0.0000000e+00 +Initial redshift = 1.0000000e+00 +Dynamic redshift update = no +Liquid crystal activity No + +Liquid crystal anchoring +Anchoring method: = two +Anchoring type (colloids): = normal +Anchoring type (walls): = normal +Surface free energy (colloid)w1: = 2.5938240e-03 +Surface free energy (colloid)w2: = 0.0000000e+00 +Surface free energy (wall) w1: = 0.0000000e+00 +Surface free energy (wall) w2: = 0.0000000e+00 +Ratio (colloid) w1/kappa0: = 4.0000000e+00 +Ratio (wall) w1/kappa0: = 0.0000000e+00 +Computed surface order f(gamma) = 3.3333333e-01 + +Using Beris-Edwards solver: +Rotational diffusion const = 5.0000000e-01 +LC fluctuations: = off + +System properties +---------------- +Mean fluid density: 1.00000e+00 +Shear viscosity 1.00000e+00 +Bulk viscosity 1.00000e+00 +Temperature 0.00000e+00 +External body force density 0.00000e+00 0.00000e+00 0.00000e+00 +External E-field amplitude 0.00000e+00 0.00000e+00 0.00000e+00 +External E-field frequency 0.00000e+00 +External magnetic field 0.00000e+00 0.00000e+00 0.00000e+00 + +Lattice Boltzmann distributions +------------------------------- +Model: d3q19 +SIMD vector len: 2 +Number of sets: 1 +Halo type: full +Input format: binary +Output format: binary +I/O grid: 1 1 1 + +Lattice Boltzmann collision +--------------------------- +Relaxation time scheme: M10 +Hydrodynamic modes: on +Ghost modes: on +Isothermal fluctuations: off +Shear relaxation time: 3.50000e+00 +Bulk relaxation time: 3.50000e+00 +Ghost relaxation time: 1.00000e+00 +[User ] Random number seed: 8361235 + +Hydrodynamics +------------- +Hydrodynamics: on + +Order parameter I/O +------------------- +Order parameter I/O format: +I/O decomposition: 1 1 1 + +Advection scheme order: 3 +Gradient calculation: 3d_7pt_fluid + + +Initialising Q_ab to cholesteric +Helical axis Z +Initial conditions. + +Scalars - total mean variance min max +[rho] 2097152.00 1.00000000000 2.2204460e-16 1.00000000000 1.00000000000 +[phi] 1.7476388e+05 8.3333910e-02 3.1250069e-02 -1.6666667e-01 3.3333333e-01 +[phi] 2.4079829e-01 1.1482157e-07 3.1249931e-02 -2.5000000e-01 2.5000000e-01 +[phi] 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 +[phi] 1.7476146e+05 8.3332756e-02 3.1250069e-02 -1.6666667e-01 3.3333333e-01 +[phi] 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 + +Momentum - x y z +[total ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 +[fluid ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 + +Starting time step loop. + +Scalars - total mean variance min max +[rho] 2097152.00 1.00000000000 1.9937385e-12 0.99999999991 1.00000000302 +[phi] 1.7303123e+05 8.2507719e-02 3.1029972e-02 -1.6661093e-01 3.3162533e-01 +[phi] 2.2790390e-01 1.0867305e-07 3.1029859e-02 -2.4911811e-01 2.4911811e-01 +[phi] -1.9812350e-12 -9.4472649e-19 3.0065582e-33 -1.5099951e-16 1.1650947e-16 +[phi] 1.7302894e+05 8.2506627e-02 3.1029972e-02 -1.6661097e-01 3.3162528e-01 +[phi] -2.7354779e-12 -1.3043775e-18 4.4863135e-33 -1.8828475e-16 2.0412098e-16 + +Free energies - timestep f v f/v f_bulk/v f_grad/v redshift +[fe] 1000 -1.4130150161e+02 2.0971520000e+06 -6.7377806475e-05 -6.9424084751e-05 2.0462782744e-06 1.0000000000e+00 + +Momentum - x y z +[total ] 4.3200998e-11 2.2737590e-11 -4.2518877e-11 +[fluid ] 4.3200998e-11 2.2737590e-11 -4.2518877e-11 + +Velocity - x y z +[minimum ] -3.8161432e-17 -2.0816475e-17 -1.6327987e-12 +[maximum ] 9.7144615e-17 5.2056455e-17 1.6324896e-12 + +Completed cycle 1000 + +Timer resolution: 2e-08 second + +Timer statistics + Section: tmin tmax total + Total: 66.705 66.705 66.705 66.704946 (1 call) + Time step loop: 0.065 0.088 65.962 0.065962 (1000 calls) + Propagation: 0.011 0.012 11.471 0.011471 (1000 calls) + Propagtn (krnl) : 0.011 0.012 11.467 0.011467 (1000 calls) + Collision: 0.007 0.007 6.826 0.006826 (1000 calls) + Collision (krnl) : 0.007 0.007 6.819 0.006819 (1000 calls) + Lattice halos: 0.003 0.009 3.194 0.003194 (1000 calls) + phi gradients: 0.006 0.013 6.802 0.006802 (1000 calls) + phi grad (krnl) : 0.005 0.010 5.414 0.005414 (1000 calls) + phi halos: 0.001 0.004 1.380 0.001380 (1000 calls) + BBL: 0.000 0.000 0.001 0.000001 (1000 calls) + Force calculation: 0.012 0.015 12.341 0.012341 (1000 calls) + Phi force (krnl) : 0.004 0.004 4.001 0.004001 (1000 calls) + phi update: 0.024 0.035 24.686 0.024686 (1000 calls) + Velocity Halo : 0.000 0.002 0.549 0.000549 (1000 calls) +BE mol field (krnl) : 0.006 0.008 6.229 0.006229 (1000 calls) +BP BE update (krnl) : 0.006 0.007 5.880 0.005880 (1000 calls) + Advectn (krnl) : 0.006 0.013 6.762 0.006762 (1000 calls) + Advectn BCS (krnl) : 0.004 0.005 4.145 0.004145 (1000 calls) + Free1: 0.000 0.405 0.407 0.000407 (1000 calls) +End time: Mon Dec 6 09:47:51 2021 +Ludwig finished normally. +Node summary for 1 nodes: +Node 0, hostname nid001324, mpi 8, omp 16, executable xthi +MPI summary: 8 ranks +Node 0, rank 0, thread 0, (affinity = 0) +Node 0, rank 0, thread 1, (affinity = 1) +Node 0, rank 0, thread 2, (affinity = 2) +Node 0, rank 0, thread 3, (affinity = 3) +Node 0, rank 0, thread 4, (affinity = 4) +Node 0, rank 0, thread 5, (affinity = 5) +Node 0, rank 0, thread 6, (affinity = 6) +Node 0, rank 0, thread 7, (affinity = 7) +Node 0, rank 0, thread 8, (affinity = 8) +Node 0, rank 0, thread 9, (affinity = 9) +Node 0, rank 0, thread 10, (affinity = 10) +Node 0, rank 0, thread 11, (affinity = 11) +Node 0, rank 0, thread 12, (affinity = 12) +Node 0, rank 0, thread 13, (affinity = 13) +Node 0, rank 0, thread 14, (affinity = 14) +Node 0, rank 0, thread 15, (affinity = 15) +Node 0, rank 1, thread 0, (affinity = 16) +Node 0, rank 1, thread 1, (affinity = 17) +Node 0, rank 1, thread 2, (affinity = 18) +Node 0, rank 1, thread 3, (affinity = 19) +Node 0, rank 1, thread 4, (affinity = 20) +Node 0, rank 1, thread 5, (affinity = 21) +Node 0, rank 1, thread 6, (affinity = 22) +Node 0, rank 1, thread 7, (affinity = 23) +Node 0, rank 1, thread 8, (affinity = 24) +Node 0, rank 1, thread 9, (affinity = 25) +Node 0, rank 1, thread 10, (affinity = 26) +Node 0, rank 1, thread 11, (affinity = 27) +Node 0, rank 1, thread 12, (affinity = 28) +Node 0, rank 1, thread 13, (affinity = 29) +Node 0, rank 1, thread 14, (affinity = 30) +Node 0, rank 1, thread 15, (affinity = 31) +Node 0, rank 2, thread 0, (affinity = 32) +Node 0, rank 2, thread 1, (affinity = 33) +Node 0, rank 2, thread 2, (affinity = 34) +Node 0, rank 2, thread 3, (affinity = 35) +Node 0, rank 2, thread 4, (affinity = 36) +Node 0, rank 2, thread 5, (affinity = 37) +Node 0, rank 2, thread 6, (affinity = 38) +Node 0, rank 2, thread 7, (affinity = 39) +Node 0, rank 2, thread 8, (affinity = 40) +Node 0, rank 2, thread 9, (affinity = 41) +Node 0, rank 2, thread 10, (affinity = 42) +Node 0, rank 2, thread 11, (affinity = 43) +Node 0, rank 2, thread 12, (affinity = 44) +Node 0, rank 2, thread 13, (affinity = 45) +Node 0, rank 2, thread 14, (affinity = 46) +Node 0, rank 2, thread 15, (affinity = 47) +Node 0, rank 3, thread 0, (affinity = 48) +Node 0, rank 3, thread 1, (affinity = 49) +Node 0, rank 3, thread 2, (affinity = 50) +Node 0, rank 3, thread 3, (affinity = 51) +Node 0, rank 3, thread 4, (affinity = 52) +Node 0, rank 3, thread 5, (affinity = 53) +Node 0, rank 3, thread 6, (affinity = 54) +Node 0, rank 3, thread 7, (affinity = 55) +Node 0, rank 3, thread 8, (affinity = 56) +Node 0, rank 3, thread 9, (affinity = 57) +Node 0, rank 3, thread 10, (affinity = 58) +Node 0, rank 3, thread 11, (affinity = 59) +Node 0, rank 3, thread 12, (affinity = 60) +Node 0, rank 3, thread 13, (affinity = 61) +Node 0, rank 3, thread 14, (affinity = 62) +Node 0, rank 3, thread 15, (affinity = 63) +Node 0, rank 4, thread 0, (affinity = 64) +Node 0, rank 4, thread 1, (affinity = 65) +Node 0, rank 4, thread 2, (affinity = 66) +Node 0, rank 4, thread 3, (affinity = 67) +Node 0, rank 4, thread 4, (affinity = 68) +Node 0, rank 4, thread 5, (affinity = 69) +Node 0, rank 4, thread 6, (affinity = 70) +Node 0, rank 4, thread 7, (affinity = 71) +Node 0, rank 4, thread 8, (affinity = 72) +Node 0, rank 4, thread 9, (affinity = 73) +Node 0, rank 4, thread 10, (affinity = 74) +Node 0, rank 4, thread 11, (affinity = 75) +Node 0, rank 4, thread 12, (affinity = 76) +Node 0, rank 4, thread 13, (affinity = 77) +Node 0, rank 4, thread 14, (affinity = 78) +Node 0, rank 4, thread 15, (affinity = 79) +Node 0, rank 5, thread 0, (affinity = 80) +Node 0, rank 5, thread 1, (affinity = 81) +Node 0, rank 5, thread 2, (affinity = 82) +Node 0, rank 5, thread 3, (affinity = 83) +Node 0, rank 5, thread 4, (affinity = 84) +Node 0, rank 5, thread 5, (affinity = 85) +Node 0, rank 5, thread 6, (affinity = 86) +Node 0, rank 5, thread 7, (affinity = 87) +Node 0, rank 5, thread 8, (affinity = 88) +Node 0, rank 5, thread 9, (affinity = 89) +Node 0, rank 5, thread 10, (affinity = 90) +Node 0, rank 5, thread 11, (affinity = 91) +Node 0, rank 5, thread 12, (affinity = 92) +Node 0, rank 5, thread 13, (affinity = 93) +Node 0, rank 5, thread 14, (affinity = 94) +Node 0, rank 5, thread 15, (affinity = 95) +Node 0, rank 6, thread 0, (affinity = 96) +Node 0, rank 6, thread 1, (affinity = 97) +Node 0, rank 6, thread 2, (affinity = 98) +Node 0, rank 6, thread 3, (affinity = 99) +Node 0, rank 6, thread 4, (affinity = 100) +Node 0, rank 6, thread 5, (affinity = 101) +Node 0, rank 6, thread 6, (affinity = 102) +Node 0, rank 6, thread 7, (affinity = 103) +Node 0, rank 6, thread 8, (affinity = 104) +Node 0, rank 6, thread 9, (affinity = 105) +Node 0, rank 6, thread 10, (affinity = 106) +Node 0, rank 6, thread 11, (affinity = 107) +Node 0, rank 6, thread 12, (affinity = 108) +Node 0, rank 6, thread 13, (affinity = 109) +Node 0, rank 6, thread 14, (affinity = 110) +Node 0, rank 6, thread 15, (affinity = 111) +Node 0, rank 7, thread 0, (affinity = 112) +Node 0, rank 7, thread 1, (affinity = 113) +Node 0, rank 7, thread 2, (affinity = 114) +Node 0, rank 7, thread 3, (affinity = 115) +Node 0, rank 7, thread 4, (affinity = 116) +Node 0, rank 7, thread 5, (affinity = 117) +Node 0, rank 7, thread 6, (affinity = 118) +Node 0, rank 7, thread 7, (affinity = 119) +Node 0, rank 7, thread 8, (affinity = 120) +Node 0, rank 7, thread 9, (affinity = 121) +Node 0, rank 7, thread 10, (affinity = 122) +Node 0, rank 7, thread 11, (affinity = 123) +Node 0, rank 7, thread 12, (affinity = 124) +Node 0, rank 7, thread 13, (affinity = 125) +Node 0, rank 7, thread 14, (affinity = 126) +Node 0, rank 7, thread 15, (affinity = 127) +Welcome to Ludwig v0.14.0 (MPI version running on 8 processes) +Start time: Mon Dec 6 09:47:54 2021 + +Compiler: + name: Gnu 11.2.0 + version-string: 11.2.0 20210728 (Cray Inc.) + +Target thread model: OpenMP. +OpenMP threads: 16; maximum number of threads: 16. + +Read 28 user parameters from input + +System details +-------------- +System size: 128 128 128 +Decomposition: 2 2 2 +Local domain: 64 64 64 +Periodic: 1 1 1 +Halo nhalo: 2 +Reorder: true +Initialised: 1 + +Free energy details +------------------- + +Blue phase free energy selected. + +Liquid crystal blue phase free energy +Bulk parameter A0: = 1.0000000e-02 +Magnitude of order gamma = 3.0000000e+00 +Pitch wavevector q0 = 1.9635000e-01 +... gives pitch length = 3.1999925e+01 +Elastic constant kappa0 = 6.4845600e-04 +Elastic constant kappa1 = 6.4845600e-04 +Amplitude (uniaxial) order = 3.3333333e-01 +Effective aspect ratio xi = 7.0000000e-01 +Chirality = 3.0000080e-01 +Reduced temperature = 0.0000000e+00 +Initial redshift = 1.0000000e+00 +Dynamic redshift update = no +Liquid crystal activity No + +Liquid crystal anchoring +Anchoring method: = two +Anchoring type (colloids): = normal +Anchoring type (walls): = normal +Surface free energy (colloid)w1: = 2.5938240e-03 +Surface free energy (colloid)w2: = 0.0000000e+00 +Surface free energy (wall) w1: = 0.0000000e+00 +Surface free energy (wall) w2: = 0.0000000e+00 +Ratio (colloid) w1/kappa0: = 4.0000000e+00 +Ratio (wall) w1/kappa0: = 0.0000000e+00 +Computed surface order f(gamma) = 3.3333333e-01 + +Using Beris-Edwards solver: +Rotational diffusion const = 5.0000000e-01 +LC fluctuations: = off + +System properties +---------------- +Mean fluid density: 1.00000e+00 +Shear viscosity 1.00000e+00 +Bulk viscosity 1.00000e+00 +Temperature 0.00000e+00 +External body force density 0.00000e+00 0.00000e+00 0.00000e+00 +External E-field amplitude 0.00000e+00 0.00000e+00 0.00000e+00 +External E-field frequency 0.00000e+00 +External magnetic field 0.00000e+00 0.00000e+00 0.00000e+00 + +Lattice Boltzmann distributions +------------------------------- +Model: d3q19 +SIMD vector len: 2 +Number of sets: 1 +Halo type: full +Input format: binary +Output format: binary +I/O grid: 1 1 1 + +Lattice Boltzmann collision +--------------------------- +Relaxation time scheme: M10 +Hydrodynamic modes: on +Ghost modes: on +Isothermal fluctuations: off +Shear relaxation time: 3.50000e+00 +Bulk relaxation time: 3.50000e+00 +Ghost relaxation time: 1.00000e+00 +[User ] Random number seed: 8361235 + +Hydrodynamics +------------- +Hydrodynamics: on + +Order parameter I/O +------------------- +Order parameter I/O format: +I/O decomposition: 1 1 1 + +Advection scheme order: 3 +Gradient calculation: 3d_7pt_fluid + + +Initialising Q_ab to cholesteric +Helical axis Z +Initial conditions. + +Scalars - total mean variance min max +[rho] 2097152.00 1.00000000000 2.2204460e-16 1.00000000000 1.00000000000 +[phi] 1.7476388e+05 8.3333910e-02 3.1250069e-02 -1.6666667e-01 3.3333333e-01 +[phi] 2.4079829e-01 1.1482157e-07 3.1249931e-02 -2.5000000e-01 2.5000000e-01 +[phi] 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 +[phi] 1.7476146e+05 8.3332756e-02 3.1250069e-02 -1.6666667e-01 3.3333333e-01 +[phi] 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 + +Momentum - x y z +[total ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 +[fluid ] 0.0000000e+00 0.0000000e+00 0.0000000e+00 + +Starting time step loop. + +Scalars - total mean variance min max +[rho] 2097152.00 1.00000000000 1.2587709e-12 0.99999999991 1.00000000302 +[phi] 1.7303123e+05 8.2507719e-02 3.1029972e-02 -1.6661093e-01 3.3162533e-01 +[phi] 2.2790390e-01 1.0867305e-07 3.1029859e-02 -2.4911811e-01 2.4911811e-01 +[phi] -1.9812350e-12 -9.4472649e-19 3.0065582e-33 -1.5099951e-16 1.1650947e-16 +[phi] 1.7302894e+05 8.2506627e-02 3.1029972e-02 -1.6661097e-01 3.3162528e-01 +[phi] -2.7354779e-12 -1.3043775e-18 4.4863135e-33 -1.8828475e-16 2.0412098e-16 + +Free energies - timestep f v f/v f_bulk/v f_grad/v redshift +[fe] 1000 -1.4130150161e+02 2.0971520000e+06 -6.7377806475e-05 -6.9424084750e-05 2.0462782744e-06 1.0000000000e+00 + +Momentum - x y z +[total ] 4.3427928e-11 2.2738034e-11 -4.2518877e-11 +[fluid ] 4.3427928e-11 2.2738034e-11 -4.2518877e-11 + +Velocity - x y z +[minimum ] -3.8161432e-17 -2.0816475e-17 -1.6327987e-12 +[maximum ] 9.7144615e-17 5.2056455e-17 1.6324896e-12 + +Completed cycle 1000 + +Timer resolution: 2e-08 second + +Timer statistics + Section: tmin tmax total + Total: 33.068 33.068 33.068 33.068290 (1 call) + Time step loop: 0.032 0.054 32.682 0.032682 (1000 calls) + Propagation: 0.003 0.005 3.677 0.003677 (1000 calls) + Propagtn (krnl) : 0.003 0.005 3.670 0.003670 (1000 calls) + Collision: 0.003 0.004 3.396 0.003396 (1000 calls) + Collision (krnl) : 0.003 0.004 3.389 0.003389 (1000 calls) + Lattice halos: 0.002 0.012 2.220 0.002220 (1000 calls) + phi gradients: 0.004 0.009 4.621 0.004621 (1000 calls) + phi grad (krnl) : 0.003 0.005 2.752 0.002752 (1000 calls) + phi halos: 0.001 0.004 1.859 0.001859 (1000 calls) + BBL: 0.000 0.000 0.001 0.000001 (1000 calls) + Force calculation: 0.006 0.009 6.222 0.006222 (1000 calls) + Phi force (krnl) : 0.002 0.003 1.893 0.001893 (1000 calls) + phi update: 0.011 0.022 12.126 0.012126 (1000 calls) + Velocity Halo : 0.000 0.004 0.732 0.000732 (1000 calls) +BE mol field (krnl) : 0.003 0.005 3.010 0.003010 (1000 calls) +BP BE update (krnl) : 0.003 0.005 3.322 0.003322 (1000 calls) + Advectn (krnl) : 0.003 0.010 3.370 0.003370 (1000 calls) + Advectn BCS (krnl) : 0.001 0.002 1.160 0.001160 (1000 calls) + Free1: 0.000 0.207 0.207 0.000207 (1000 calls) +End time: Mon Dec 6 09:48:27 2021 +Ludwig finished normally. From e149db3aa2081b6bacdaa9ea8ff375ffb5ef18ed Mon Sep 17 00:00:00 2001 From: not populated Date: Mon, 6 Dec 2021 10:40:13 +0000 Subject: [PATCH 079/117] Example for ARCHER2 --- config/epcc-archer2.mk | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 config/epcc-archer2.mk diff --git a/config/epcc-archer2.mk b/config/epcc-archer2.mk new file mode 100644 index 000000000..76066a6d6 --- /dev/null +++ b/config/epcc-archer2.mk @@ -0,0 +1,26 @@ +############################################################################## +# +# archer2 +# https://www.archer2.ac.uk +# +# PrgEnv-cray +# - Use cce >= 12 to avoid problem in openmp +# - "module load cce/12.0.3" +# +# Same compiler options for all PrgEnv are available. +# +############################################################################## + +BUILD = parallel +MODEL = -D_D3Q19_ + +CC = cc -fopenmp +CFLAGS = -g -O3 -Wall -DNSIMDVL=2 -DNDEBUG + +MPI_INC_PATH = +MPI_LIB_PATH = +MPI_LIB = + +LAUNCH_SERIAL_CMD = +LAUNCH_MPIRUN_CMD = srun +MPIRUN_NTASK_FLAG = -n From 63c0a639c11847323497cb755cbb43c8ac2ab241 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Wed, 8 Dec 2021 14:24:44 +0000 Subject: [PATCH 080/117] Add information to stdout --- .../d3q19-short/serial-open-ru1.log | 43 ++++++++++++------- .../d3q19-short/serial-open-ru2.log | 39 +++++++++++------ 2 files changed, 52 insertions(+), 30 deletions(-) diff --git a/tests/regression/d3q19-short/serial-open-ru1.log b/tests/regression/d3q19-short/serial-open-ru1.log index 6108b7739..d5f69266e 100644 --- a/tests/regression/d3q19-short/serial-open-ru1.log +++ b/tests/regression/d3q19-short/serial-open-ru1.log @@ -1,9 +1,9 @@ Welcome to Ludwig v0.14.0 (Serial version running on 1 process) -Start time: Tue Nov 16 17:02:01 2021 +Start time: Wed Dec 8 14:16:26 2021 Compiler: - name: Gnu 11.2.0 - version-string: 11.2.0 + name: Clang 13.0.0 + version-string: 13.0.0 (clang-1300.0.29.3) Note assertions via standard C assert() are on. @@ -59,6 +59,17 @@ Hydrodynamics ------------- Hydrodynamics: on +Hydrodynamic open boundary condition for inflow +Inflow type: rhou +Inflow flow profile: uniform +Inflow flow direction: 1 0 0 +Inflow flow value u0: 0.0000000e+00 0.0000000e+00 0.0000000e+00 + +Hydrodynamic open boundary condition at outflow +Outflow type: rhou +Outflow flow direction: 1 0 0 +Outflow flow rho0: 1.0000000e+00 + Boundary walls -------------- Boundary walls: - Y Z @@ -98,17 +109,17 @@ Timer resolution: 1e-06 second Timer statistics Section: tmin tmax total - Total: 0.014 0.014 0.014 0.013520 (1 call) - Time step loop: 0.006 0.006 0.006 0.006045 (1 call) - Propagation: 0.001 0.001 0.001 0.001431 (1 call) - Propagtn (krnl) : 0.001 0.001 0.001 0.001422 (1 call) - Collision: 0.003 0.003 0.003 0.002758 (1 call) - Collision (krnl) : 0.003 0.003 0.003 0.002740 (1 call) - Lattice halos: 0.001 0.001 0.001 0.000799 (1 call) - phi gradients: 0.000 0.000 0.000 0.000001 (1 call) - BBL: 0.001 0.001 0.001 0.000846 (1 call) - Force calculation: 0.000 0.000 0.000 0.000003 (1 call) - phi update: 0.000 0.000 0.000 0.000001 (1 call) - Free1: 0.002 0.002 0.002 0.002090 (1 call) -End time: Tue Nov 16 17:02:01 2021 + Total: 0.012 0.012 0.012 0.012291 (1 call) + Time step loop: 0.005 0.005 0.005 0.005252 (1 call) + Propagation: 0.001 0.001 0.001 0.001092 (1 call) + Propagtn (krnl) : 0.001 0.001 0.001 0.001086 (1 call) + Collision: 0.002 0.002 0.002 0.002334 (1 call) + Collision (krnl) : 0.002 0.002 0.002 0.002320 (1 call) + Lattice halos: 0.001 0.001 0.001 0.000764 (1 call) + phi gradients: 0.000 0.000 0.000 0.000002 (1 call) + BBL: 0.001 0.001 0.001 0.000851 (1 call) + Force calculation: 0.000 0.000 0.000 0.000004 (1 call) + phi update: 0.000 0.000 0.000 0.000000 (1 call) + Free1: 0.002 0.002 0.002 0.001855 (1 call) +End time: Wed Dec 8 14:16:26 2021 Ludwig finished normally. diff --git a/tests/regression/d3q19-short/serial-open-ru2.log b/tests/regression/d3q19-short/serial-open-ru2.log index d2f5969fa..ac243a575 100644 --- a/tests/regression/d3q19-short/serial-open-ru2.log +++ b/tests/regression/d3q19-short/serial-open-ru2.log @@ -1,9 +1,9 @@ Welcome to Ludwig v0.14.0 (Serial version running on 1 process) -Start time: Tue Nov 16 17:03:12 2021 +Start time: Wed Dec 8 14:16:27 2021 Compiler: - name: Gnu 11.2.0 - version-string: 11.2.0 + name: Clang 13.0.0 + version-string: 13.0.0 (clang-1300.0.29.3) Note assertions via standard C assert() are on. @@ -59,6 +59,17 @@ Hydrodynamics ------------- Hydrodynamics: on +Hydrodynamic open boundary condition for inflow +Inflow type: rhou +Inflow flow profile: uniform +Inflow flow direction: 0 0 1 +Inflow flow value u0: 0.0000000e+00 0.0000000e+00 3.0000000e-03 + +Hydrodynamic open boundary condition at outflow +Outflow type: rhou +Outflow flow direction: 0 0 1 +Outflow flow rho0: 1.0000000e+00 + Boundary walls -------------- Boundary walls: X Y - @@ -98,17 +109,17 @@ Timer resolution: 1e-06 second Timer statistics Section: tmin tmax total - Total: 0.058 0.058 0.058 0.058257 (1 call) - Time step loop: 0.005 0.005 0.051 0.005108 (10 calls) - Propagation: 0.001 0.001 0.011 0.001057 (10 calls) - Propagtn (krnl) : 0.001 0.001 0.011 0.001051 (10 calls) - Collision: 0.002 0.003 0.025 0.002493 (10 calls) - Collision (krnl) : 0.002 0.003 0.025 0.002485 (10 calls) - Lattice halos: 0.000 0.001 0.005 0.000537 (10 calls) + Total: 0.055 0.055 0.055 0.054889 (1 call) + Time step loop: 0.005 0.005 0.048 0.004768 (10 calls) + Propagation: 0.001 0.001 0.010 0.000981 (10 calls) + Propagtn (krnl) : 0.001 0.001 0.010 0.000977 (10 calls) + Collision: 0.002 0.003 0.022 0.002248 (10 calls) + Collision (krnl) : 0.002 0.003 0.022 0.002242 (10 calls) + Lattice halos: 0.000 0.001 0.005 0.000510 (10 calls) phi gradients: 0.000 0.000 0.000 0.000001 (10 calls) - BBL: 0.001 0.001 0.008 0.000816 (10 calls) + BBL: 0.001 0.001 0.008 0.000824 (10 calls) Force calculation: 0.000 0.000 0.000 0.000001 (10 calls) - phi update: 0.000 0.000 0.000 0.000000 (10 calls) - Free1: 0.000 0.002 0.002 0.000197 (10 calls) -End time: Tue Nov 16 17:03:12 2021 + phi update: 0.000 0.000 0.000 0.000001 (10 calls) + Free1: 0.000 0.002 0.002 0.000194 (10 calls) +End time: Wed Dec 8 14:16:27 2021 Ludwig finished normally. From 9c78830b29e4076da50b0f1a526cfeaaa3ddf4e5 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Wed, 8 Dec 2021 14:25:46 +0000 Subject: [PATCH 081/117] Extend update to halo regions to cover parallel case --- src/phi_bc_inflow_fixed.c | 6 ++++-- src/phi_bc_outflow_free.c | 13 ++++++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/phi_bc_inflow_fixed.c b/src/phi_bc_inflow_fixed.c index f939ec648..42202694c 100644 --- a/src/phi_bc_inflow_fixed.c +++ b/src/phi_bc_inflow_fixed.c @@ -110,9 +110,11 @@ __host__ int phi_bc_inflow_fixed_update(phi_bc_inflow_fixed_t * inflow, if (noffset[id] == 0) { /* The inflow region covers the halo only in the flow direction. */ + /* As we are just imposing a prescribed phi0, we can extend into + * the halo region in the other directions. */ - int imin[3] = {1, 1, 1}; - int imax[3] = {nlocal[X], nlocal[Y], nlocal[Z]}; + int imin[3] = {1- nhalo, 1-nhalo, 1-nhalo}; + int imax[3] = {nlocal[X]+nhalo, nlocal[Y]+nhalo, nlocal[Z]+nhalo}; imin[id] = 1 - nhalo; imax[id] = 0; diff --git a/src/phi_bc_outflow_free.c b/src/phi_bc_outflow_free.c index d10912e35..bfebd50de 100644 --- a/src/phi_bc_outflow_free.c +++ b/src/phi_bc_outflow_free.c @@ -79,6 +79,13 @@ __host__ int phi_bc_outflow_free_free(phi_bc_outflow_free_t * outflow) { * * phi_bc_outflow_free_update * + * Important assumption here. We should have up-to-date halo information + * in the non-flow direction, so that we can push the update into the + * non-flow halo directions locally. + * + * For complete safety, there should probably be an in-built halo + * exchange to ensure the relevant information is up-to-date. + * *****************************************************************************/ __host__ int phi_bc_outflow_free_update(phi_bc_outflow_free_t * outflow, @@ -107,8 +114,8 @@ __host__ int phi_bc_outflow_free_update(phi_bc_outflow_free_t * outflow, /* Set halo region e.g., phi(x > L_x, y, z) = phi(x = L_x, y, z) */ /* Slightly convoluted to allow x, y, or z direction. */ - int imin[3] = {1, 1, 1}; - int imax[3] = {nlocal[X], nlocal[Y], nlocal[Z]}; + int imin[3] = {1-nhalo, 1-nhalo, 1-nhalo}; + int imax[3] = {nlocal[X]+nhalo, nlocal[Y]+nhalo, nlocal[Z]+nhalo}; imin[id] = nlocal[id]; imax[id] = nlocal[id]; @@ -128,7 +135,7 @@ __host__ int phi_bc_outflow_free_update(phi_bc_outflow_free_t * outflow, } } } - } + } } return 0; From 7657bc395e71e11efb2e73f9c96e57bfda0e511e Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Wed, 8 Dec 2021 14:26:37 +0000 Subject: [PATCH 082/117] Correct outflow position in parallel --- src/lb_bc_outflow_rhou.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/lb_bc_outflow_rhou.c b/src/lb_bc_outflow_rhou.c index 0fe8640d8..38dde7a31 100644 --- a/src/lb_bc_outflow_rhou.c +++ b/src/lb_bc_outflow_rhou.c @@ -138,25 +138,25 @@ __host__ int lb_bc_outflow_init_link(lb_bc_outflow_rhou_t * outflow, cs_t * cs = NULL; int noffset[3] = {}; + int ntotal[3] = {}; + int nlocal[3] = {}; int nlink = 0; assert(outflow); assert(id == X || id == Y || id == Z); cs = outflow->cs; + + cs_ntotal(cs, ntotal); + cs_nlocal(cs, nlocal); cs_nlocal_offset(cs, noffset); - if (noffset[id] == 0) { + if (noffset[id] + nlocal[id] == ntotal[id]) { int nmin[3] = {1, 1, 1}; - int ntotal[3] = {}; - int nlocal[3] = {}; lb_model_t model = {}; lb_model_create(outflow->options.nvel, &model); - cs_ntotal(cs, ntotal); - cs_nlocal(cs, nlocal); - nmin[id] = nlocal[id]; /* Only rightmost edge in the relevant direction */ for (int ic = nmin[X]; ic <= nlocal[X]; ic++) { @@ -234,12 +234,17 @@ __host__ int lb_bc_outflow_rhou_update(lb_bc_outflow_rhou_t * outflow, cs_t * cs = NULL; int id = -1; + int nlocal[3] = {}; + int ntotal[3] = {}; int noffset[3] = {}; assert(outflow); assert(hydro); cs = outflow->cs; + + cs_ntotal(cs, ntotal); + cs_nlocal(cs, nlocal); cs_nlocal_offset(cs, noffset); if (outflow->options.flow[X]) id = X; @@ -247,15 +252,12 @@ __host__ int lb_bc_outflow_rhou_update(lb_bc_outflow_rhou_t * outflow, if (outflow->options.flow[Z]) id = Z; - if (noffset[id] == 0) { + if (noffset[id] + nlocal[id] == ntotal[id]) { int nmin[3] = {1,1,1}; - int nlocal[3] = {}; int idx = outflow->options.flow[X]; int jdy = outflow->options.flow[Y]; int kdz = outflow->options.flow[Z]; - cs_nlocal(cs, nlocal); - nmin[id] = nlocal[id]; /* Only rightmost edge in the relevant direction */ for (int ic = nmin[X]; ic <= nlocal[X]; ic++) { @@ -281,7 +283,8 @@ __host__ int lb_bc_outflow_rhou_update(lb_bc_outflow_rhou_t * outflow, * * lb_bc_outflow_rhou_impose * - * ABSOLUTELY THE SAME + * Very largely the same as the inflow routine; there could be + * some consolidation. * Intent: After lattice halo swap; before propagation. * *****************************************************************************/ From 09bfa0d621fa4e932e069429874f77fd13b52749 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Wed, 8 Dec 2021 14:27:03 +0000 Subject: [PATCH 083/117] Add halo swap for input boundary --- src/lb_bc_inflow_rhou.c | 199 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) diff --git a/src/lb_bc_inflow_rhou.c b/src/lb_bc_inflow_rhou.c index 53c97adcc..69b82069e 100644 --- a/src/lb_bc_inflow_rhou.c +++ b/src/lb_bc_inflow_rhou.c @@ -27,6 +27,7 @@ #include "lb_model.h" #include "lb_bc_inflow_rhou.h" +#include "cs_limits.h" typedef enum {LINK_COUNT, LINK_ASSIGN} link_init_enum_t; @@ -43,6 +44,9 @@ static const lb_bc_open_vtable_t vt_ = { (lb_bc_open_stats_ft) lb_bc_inflow_rhou_stats }; +__host__ int lb_bc_inflow_rhou_halo_update(lb_bc_inflow_rhou_t * inflow, + hydro_t * hydro); + /***************************************************************************** * * lb_bc_inflow_rhou_create @@ -275,6 +279,194 @@ __host__ int lb_bc_inflow_rhou_update(lb_bc_inflow_rhou_t * inflow, return 0; } +/***************************************************************************** + * + * lb_bc_inflow_rhou_halo_update + * + * In the two-dimensional picture at the inflow, normal to the flow, + * there are two corner blocks that must be moved (0, +/-1, 0) and + * two blocks in (0, 0, +/-1). The same four corner blocks should + * also be moved diagonally. + * + *****************************************************************************/ + +__host__ int lb_bc_inflow_rhou_halo_update(lb_bc_inflow_rhou_t * inflow, + hydro_t * hydro) { + cs_t * cs = NULL; + int noffset[3] = {}; + int nlocal[3] = {}; + + const int tag = 12347; + + assert(inflow); + assert(hydro); + + cs = inflow->cs; + cs_nlocal(cs, nlocal); + cs_nlocal_offset(cs, noffset); + + /* Must have flow in x-direction at the moment! */ + assert(inflow->options.flow[X]); + + if (noffset[X] == 0) { + + MPI_Comm comm = MPI_COMM_NULL; + MPI_Request req[8] = {}; + double *buf[8] = {}; + int ngbr[8] = {}; + int count[8] = {}; /* Data items */ + int nhalo = 1; /* Only ever one if distributions are involved. */ + + /* Recv from ... */ + cs_cart_comm(cs, &comm); + ngbr[0] = cs_cart_neighb(cs, FORWARD, Y); + ngbr[1] = cs_cart_neighb(cs, BACKWARD, Y); + ngbr[2] = cs_cart_neighb(cs, FORWARD, Z); + ngbr[3] = cs_cart_neighb(cs, BACKWARD, Z); + + /* Send to ... */ + ngbr[4] = cs_cart_neighb(cs, BACKWARD, Y); + ngbr[5] = cs_cart_neighb(cs, FORWARD, Y); + ngbr[6] = cs_cart_neighb(cs, BACKWARD, Z); + ngbr[7] = cs_cart_neighb(cs, FORWARD, Z); + + { + int countY = 4*nlocal[Z]*nhalo*nhalo; /* 4 (rho, u_x, u_y, u_z) */ + int countZ = 4*nlocal[Y]*nhalo*nhalo; + count[0] = countY; + count[1] = countY; + count[2] = countZ; + count[3] = countZ; + count[4] = countY; + count[5] = countY; + count[6] = countZ; + count[7] = countZ; + } + + for (int m = 0; m < 8; m++) { + pe_t * pe = inflow->pe; + req[m] = MPI_REQUEST_NULL; + buf[m] = (double *) malloc(sizeof(double)*count[m]); + assert(buf[m]); + if (buf[m] == NULL) pe_fatal(pe, "malloc() failed\n"); + } + + /* Post receives */ + for (int m = 0; m < 4; m++) { + MPI_Irecv(buf[m], count[m], MPI_DOUBLE, ngbr[m], tag, comm, req + m); + } + + /* Pack buffers and post sends */ + for (int ms = 0; ms < 4; ms++) { + int m = 4 + ms; + int ib = 0; + int nhm1 = nhalo-1; + cs_limits_t lim = {}; + + if (m == 4) { /* send to Y-1,Z */ + lim.jmin = 1; lim.jmax = nhalo; + lim.kmin = 1; lim.kmax = nlocal[Z]; + } + if (m == 5) { /* send to Y+1,Z */ + lim.jmin = nlocal[Y] - nhm1; lim.jmax = nlocal[Y]; + lim.kmin = 1; lim.kmax = nlocal[Z]; + } + if (m == 6) { /* send to Y,Z-1 */ + lim.jmin = 1; lim.jmax = nlocal[Y]; + lim.kmin = 1; lim.kmax = nhalo; + } + if (m == 7) { /* send to Y,Z+1 */ + lim.jmin = 1; lim.jmax = nlocal[Y]; + lim.kmin = nlocal[Z] - nhm1; lim.kmax = nlocal[Z]; + } + + int ic = 0; + for (int jc = lim.jmin; jc <= lim.jmax; jc++) { + for (int kc = lim.kmin; kc <= lim.kmax; kc++) { + int index = cs_index(cs, ic, jc, kc); + double rho = 0.0; + double u[3] = {}; + hydro_rho(hydro, index, &rho); + hydro_u(hydro, index, u); + buf[m][ib++] = rho; + buf[m][ib++] = u[X]; + buf[m][ib++] = u[Y]; + buf[m][ib++] = u[Z]; + } + } + assert(ib == count[m]); + + MPI_Isend(buf[m], count[m], MPI_DOUBLE, ngbr[m], tag, comm, req + m); + } + + /* Process */ + for (int ms = 0; ms < 8; ms++) { + int m = -1; + MPI_Status status = {}; + + MPI_Waitany(8, req, &m, &status); + if (m == MPI_UNDEFINED) continue; + if (status.MPI_SOURCE == MPI_PROC_NULL) continue; + + if (m >= 4) { + /* Send has completed */ + free(buf[m]); + buf[m] = NULL; + } + else { + /* Recv has arrived: unpack to correct destination */ + int ib = 0; + cs_limits_t lim = {}; + + if (m == 0) { /* recv from Y+1,Z */ + lim.jmin = nlocal[Y] + 1; lim.jmax = nlocal[Y] + nhalo; + lim.kmin = 1; lim.kmax = nlocal[Z]; + } + if (m == 1) { /* recv from Y-1,Z */ + lim.jmin = 1 - nhalo; lim.jmin = 0; + lim.kmin = 1; lim.kmax = nlocal[Z]; + } + if (m == 2) { /* recv from Y, Z+1 */ + lim.jmin = 1; lim.jmax = nlocal[Y]; + lim.kmin = nlocal[Z] + 1; lim.kmax = nlocal[Z] + nhalo; + } + if (m == 3) { /* recv from Y, Z-1 */ + lim.jmin = 1; lim.jmax = nlocal[Y]; + lim.kmin = 1 - nhalo; lim.kmax = 0; + } + + int ic = 0; + for (int jc = lim.jmin; jc <= lim.jmax; jc++) { + for (int kc = lim.kmin; kc <= lim.kmax; kc++) { + int index = cs_index(cs, ic, jc, kc); + double rho = 0.0; + double u[3] = {}; + rho = buf[m][ib++]; + u[X] = buf[m][ib++]; + u[Y] = buf[m][ib++]; + u[Z] = buf[m][ib++]; + hydro_rho_set(hydro, index, rho); + hydro_u_set(hydro, index, u); + } + } + assert(ib == count[m]); + + /* Done with this message */ + free(buf[m]); + buf[m] = NULL; + } + } + + /* Ensure we have released all the buffers */ + for (int m = 0; m < 8; m++) { + free(buf[m]); + } + /* Finish */ + } + + return 0; +} + /***************************************************************************** * * lb_bc_inflow_rhou_impose @@ -290,6 +482,13 @@ __host__ int lb_bc_inflow_rhou_impose(lb_bc_inflow_rhou_t * inflow, assert(hydro); assert(lb); + /* Ensure we have appropriate halo values (rho, u) at inflow */ + /* We can skip in serial, as we must have a completely non-periodic system */ + + if (pe_mpi_size(inflow->pe) > 1) { + lb_bc_inflow_rhou_halo_update(inflow, hydro); + } + /* For each incoming link set f_p = f^eq_p (rho, u) */ for (int n = 0; n < inflow->nlink; n++) { From 15bf39c1d31a5de64059c84d27edce6df5ed959b Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Wed, 8 Dec 2021 14:27:43 +0000 Subject: [PATCH 084/117] Add some information to run time stdout --- src/lb_bc_open_rt.c | 21 ++++++++++++++++++++- src/phi_bc_open_rt.c | 15 +++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/lb_bc_open_rt.c b/src/lb_bc_open_rt.c index 4d217ed07..c11a5ded3 100644 --- a/src/lb_bc_open_rt.c +++ b/src/lb_bc_open_rt.c @@ -92,7 +92,10 @@ __host__ int lb_bc_open_rt(pe_t * pe, rt_t * rt, cs_t * cs, lb_t * lb, rt_string_parameter(rt, "lb_bc_inflow_type", intype, BUFSIZ/2); rt_double_parameter_vector(rt, "lb_bc_inflow_rhou_u0", u0); - + + pe_info(pe, "\n"); + pe_info(pe, "Hydrodynamic open boundary condition for inflow\n"); + if (strncmp(intype, "rhou", BUFSIZ) == 0) { /* Give me a rhou inflow */ lb_bc_inflow_rhou_t * rhou = NULL; @@ -108,6 +111,14 @@ __host__ int lb_bc_open_rt(pe_t * pe, rt_t * rt, cs_t * cs, lb_t * lb, lb_bc_inflow_rhou_create(pe, cs, &options, &rhou); *inflow = (lb_bc_open_t *) rhou; + + /* Might be nice to delegate this elsewhere ... */ + pe_info(pe, "Inflow type: %s\n", "rhou"); + pe_info(pe, "Inflow flow profile: %s\n", "uniform"); + pe_info(pe, "Inflow flow direction: %d %d %d\n", + flow[X], flow[Y], flow[Z]); + pe_info(pe, "Inflow flow value u0: %14.7e %14.7e %14.7e\n", + u0[X], u0[Y], u0[Z]); } else { /* Not recognised */ @@ -124,6 +135,9 @@ __host__ int lb_bc_open_rt(pe_t * pe, rt_t * rt, cs_t * cs, lb_t * lb, rt_string_parameter(rt, "lb_bc_outflow_type", outtype, BUFSIZ/2); rt_double_parameter(rt, "rho0", &rho0); rt_double_parameter(rt, "lb_bc_outflow_rhou_rho0", &rho0); + + pe_info(pe, "\n"); + pe_info(pe, "Hydrodynamic open boundary condition at outflow\n"); if (strncmp(outtype, "rhou", BUFSIZ) == 0) { lb_bc_outflow_rhou_t * rhou = NULL; @@ -138,6 +152,11 @@ __host__ int lb_bc_open_rt(pe_t * pe, rt_t * rt, cs_t * cs, lb_t * lb, lb_bc_outflow_rhou_create(pe, cs, &options, &rhou); *outflow = (lb_bc_open_t *) rhou; + + pe_info(pe, "Outflow type: %s\n", "rhou"); + pe_info(pe, "Outflow flow direction: %d %d %d\n", + flow[X], flow[Y], flow[Z]); + pe_info(pe, "Outflow flow rho0: %14.7e\n", rho0); } else { pe_fatal(pe, "lb_bc_outflow_type not recognised\n"); diff --git a/src/phi_bc_open_rt.c b/src/phi_bc_open_rt.c index 7f2bf034a..e2392e001 100644 --- a/src/phi_bc_open_rt.c +++ b/src/phi_bc_open_rt.c @@ -83,6 +83,11 @@ __host__ int phi_bc_open_rt(pe_t * pe, rt_t * rt, cs_t * cs, rt_string_parameter(rt, "phi_bc_inflow_type", intype, BUFSIZ); rt_double_parameter(rt, "phi_bc_inflow_fixed_phib", &phib); + pe_info(pe, "\n"); + pe_info(pe, "Order parameter\n"); + pe_info(pe, "---------------\n\n"); + pe_info(pe, "Inflow open boundary for composition (phi)\n"); + if (strncmp(intype, "fixed", BUFSIZ) == 0) { /* A fixed-type inflow */ phi_bc_inflow_fixed_t * bc = NULL; @@ -96,6 +101,11 @@ __host__ int phi_bc_open_rt(pe_t * pe, rt_t * rt, cs_t * cs, phi_bc_inflow_fixed_create(pe, cs, &options, &bc); *inflow = (phi_bc_open_t *) bc; + + pe_info(pe, "Composition inflow condition: %s\n", "fixed"); + pe_info(pe, "Composition inflow direction: %d %d %d\n", + flow[X], flow[Y], flow[Z]); + pe_info(pe, "Composition inflow phi_b: %14.7e\n", phib); } else { pe_info(pe, "phi_bc_inflow_type not recognised: %s\n", intype); @@ -111,6 +121,9 @@ __host__ int phi_bc_open_rt(pe_t * pe, rt_t * rt, cs_t * cs, rt_string_parameter(rt, "phi_bc_outflow_type", outtype, BUFSIZ); + pe_info(pe, "\n"); + pe_info(pe, "Outflow open boundary for composition (phi)\n"); + if (strncmp(outtype, "free", BUFSIZ) == 0) { phi_bc_outflow_free_t * bc = NULL; phi_bc_outflow_opts_t options = {.flow = {flow[X], flow[Y], flow[Z]}}; @@ -122,6 +135,8 @@ __host__ int phi_bc_open_rt(pe_t * pe, rt_t * rt, cs_t * cs, phi_bc_outflow_free_create(pe, cs, &options, &bc); *outflow = (phi_bc_open_t *) bc; + + pe_info(pe, "Composition outflow condition: %s\n", "free"); } else { pe_fatal(pe, "phi_bc_outflow_type not recognised: %s\n", outtype); From f47beeefbee02ca3d7501317d29886ece0491c58 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Wed, 8 Dec 2021 16:07:12 +0000 Subject: [PATCH 085/117] Fix inconsisitent prototypes --- src/ewald.c | 2 +- src/leesedwards.h | 4 ++-- src/psi_gradients.h | 5 +++-- src/wall.c | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/ewald.c b/src/ewald.c index 6d5a93c8f..567959b1f 100644 --- a/src/ewald.c +++ b/src/ewald.c @@ -55,7 +55,7 @@ struct ewald_s { static int ewald_sum_sin_cos_terms(ewald_t * ewald); static int ewald_get_number_fourier_terms(ewald_t * ewald); -static int ewald_set_kr_table(ewald_t * ewlad, double []); +static int ewald_set_kr_table(ewald_t * ewlad, double r[3]); /***************************************************************************** * diff --git a/src/leesedwards.h b/src/leesedwards.h index 2fb2341c4..2a800a8cd 100644 --- a/src/leesedwards.h +++ b/src/leesedwards.h @@ -6,7 +6,7 @@ * Edinburgh Parallel Computing Centre * * Kevin Stratford (kevin@epcc.ed.ac.uk) - * (c) 2010-2016 The University of Edinburgh + * (c) 2010-2021 The University of Edinburgh * *****************************************************************************/ @@ -44,7 +44,7 @@ __host__ int lees_edw_target(lees_edw_t * le, lees_edw_t ** target); __host__ int lees_edw_info(lees_edw_t * le); __host__ int lees_edw_comm(lees_edw_t * le, MPI_Comm * comm); __host__ int lees_edw_plane_comm(lees_edw_t * le, MPI_Comm * comm); -__host__ int lees_edw_jstart_to_mpi_ranks(lees_edw_t * le, int, int send[2], int recv[2]); +__host__ int lees_edw_jstart_to_mpi_ranks(lees_edw_t * le, int, int send[3], int recv[3]); __host__ int lees_edw_buffer_dy(lees_edw_t * le, int ib, double t0, double * dy); __host__ int lees_edw_buffer_du(lees_edw_t * le, int ib, double ule[3]); diff --git a/src/psi_gradients.h b/src/psi_gradients.h index 90f9be49f..297da5537 100644 --- a/src/psi_gradients.h +++ b/src/psi_gradients.h @@ -42,8 +42,9 @@ extern const double psi_gr_rcs2; int psi_electric_field(psi_t * psi, int index, double e[3]); int psi_electric_field_d3qx(psi_t * psi, int index, double e[3]); -int psi_grad_rho_d3qx(psi_t * obj, map_t * map, int index, int n, double * grad_rho); +int psi_grad_rho_d3qx(psi_t * obj, map_t * map, int index, int n, + double grad_rho[3]); int psi_grad_eps_d3qx(psi_t * psi, fe_t * fe, f_vare_t fepsilon, int index, - double * grad_eps); + double grad_eps[3]); #endif diff --git a/src/wall.c b/src/wall.c index f6ef559dc..e364d3a8b 100644 --- a/src/wall.c +++ b/src/wall.c @@ -1488,7 +1488,7 @@ __host__ int wall_shear_init(wall_t * wall) { *****************************************************************************/ __host__ int wall_lubr_sphere(wall_t * wall, double ah, const double r[3], - double * drag) { + double drag[3]) { double hlub; double h; From 1b78387cb0b276c35045d826c0b6e4f5da4567a9 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Wed, 8 Dec 2021 16:09:10 +0000 Subject: [PATCH 086/117] Fix inconsisitent prototypes --- src/fe_ternary_stats.c | 2 +- tests/unit/test_colloids_halo.c | 2 +- tests/unit/test_phi_ch.c | 2 +- util/extract.c | 5 +++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/fe_ternary_stats.c b/src/fe_ternary_stats.c index 288b25550..01877ffd0 100644 --- a/src/fe_ternary_stats.c +++ b/src/fe_ternary_stats.c @@ -214,7 +214,7 @@ __host__ int fe_ternary_surf(fe_ternary_t * fe, map_t * map, double * fes) { *****************************************************************************/ __global__ void fe_ternary_bulk_kernel(kernel_ctxt_t * ktx, fe_ternary_t * fe, - map_t * map, double * febulk) { + map_t * map, double febulk[1]) { int kindex; int kiterations; int tid; diff --git a/tests/unit/test_colloids_halo.c b/tests/unit/test_colloids_halo.c index da9f5d837..3b5e32a17 100644 --- a/tests/unit/test_colloids_halo.c +++ b/tests/unit/test_colloids_halo.c @@ -27,7 +27,7 @@ int test_colloids_halo111(pe_t * pe, cs_t * cs); int test_colloids_halo211(pe_t * pe, cs_t * cs); int test_colloids_halo_repeat(pe_t * pe, cs_t * cs); -static void test_position(cs_t * cs, const double * r1, const double * r2); +static void test_position(cs_t * cs, const double r1[3], const double r2[3]); /***************************************************************************** * diff --git a/tests/unit/test_phi_ch.c b/tests/unit/test_phi_ch.c index 2beeeff32..5c46ab1f5 100644 --- a/tests/unit/test_phi_ch.c +++ b/tests/unit/test_phi_ch.c @@ -35,7 +35,7 @@ #include "util.h" #include "tests.h" -static int test_u_zero(cs_t * cs, hydro_t * hydro, const double *); +static int test_u_zero(cs_t * cs, hydro_t * hydro, const double u[3]); static int test_advection(cs_t * cs, phi_ch_t * pch, field_t * phi, hydro_t * hydro); static int test_set_drop(cs_t * cs, field_t * phi, const double rc[3], diff --git a/util/extract.c b/util/extract.c index 1103c9805..8b956cfa9 100644 --- a/util/extract.c +++ b/util/extract.c @@ -121,7 +121,7 @@ int write_data_ascii_cmf(FILE * fp, int n[3], int nrec0, int nrec, double *); int write_data_binary(FILE * fp, int n[3], int nrec0, int nrec, double * data); int write_data_binary_cmf(FILE * fp, int n[3], int nrec0, int nrec, double *); -int site_index(int, int, int, const int *); +int site_index(int, int, int, const int nlocal[3]); void read_data(FILE *, metadata_v1_t * meta, double *); int write_vtk_header(FILE * fp, int nrec, int ndim[3], const char * descript, vtk_enum_t vtk); @@ -311,7 +311,8 @@ int extract_driver(const char * filename, metadata_v1_t * meta, int version) { { char tmp[FILENAME_MAX/2] = {}; /* Avoid potential buffer overflow */ - strncpy(tmp, meta->stub, strnlen(meta->stub, FILENAME_MAX/2-1)); + strncpy(tmp, meta->stub, + FILENAME_MAX/2 - strnlen(meta->stub, FILENAME_MAX/2-1) - 1); snprintf(io_data, sizeof(io_data), "%s-%8.8d", tmp, ntime); } From e46930f0e24a8faf7c3b03231dd185ef0532055c Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Wed, 8 Dec 2021 16:25:08 +0000 Subject: [PATCH 087/117] Fix various warnings/alerts --- src/blue_phase_rt.c | 2 +- src/colloid_io.c | 9 ++++--- src/colloids_halo.c | 2 +- src/colloids_rt.c | 60 ++++++++++++++++++++++----------------------- src/compiler.c | 3 ++- src/coords.c | 3 +++ src/io_harness.c | 12 ++++----- src/runtime.c | 10 ++++---- 8 files changed, 53 insertions(+), 48 deletions(-) diff --git a/src/blue_phase_rt.c b/src/blue_phase_rt.c index 9c91ebde1..f6fe239e5 100644 --- a/src/blue_phase_rt.c +++ b/src/blue_phase_rt.c @@ -222,7 +222,7 @@ __host__ int blue_phase_init_rt(pe_t * pe, rt_t *rt, w1_wall = 0.0; w2_wall = 0.0; - strcpy(type_wall, type); + strncpy(type_wall, type, BUFSIZ - strnlen(type, BUFSIZ) - 1); rt_string_parameter(rt, "lc_wall_anchoring", type_wall, FILENAME_MAX); diff --git a/src/colloid_io.c b/src/colloid_io.c index 33b9aeeed..3c2344fa4 100644 --- a/src/colloid_io.c +++ b/src/colloid_io.c @@ -7,7 +7,7 @@ * Edinburgh Soft Matter and Statistical Physics Group and * Edinburgh Parallel Computing Centre * - * (c) 2010-2020 The University of Edinburgh + * (c) 2010-2021 The University of Edinburgh * * Contributing authors: * Kevin Stratford (kevin@epcc.ed.ac.uk) @@ -429,7 +429,7 @@ int colloid_io_write_buffer_binary(FILE * fp, int nc, colloid_state_t * buf) { int colloid_io_read(colloid_io_t * cio, const char * filename) { int ngroup; - char filename_io[FILENAME_MAX]; + char filename_io[FILENAME_MAX] = {}; FILE * fp_state; assert(cio->f_header_read); @@ -441,7 +441,7 @@ int colloid_io_read(colloid_io_t * cio, const char * filename) { if (cio->single_file_read) { /* All groups read for single 'serial' file */ - sprintf(filename_io, "%s.%3.3d-%3.3d", filename, 1, 1); + snprintf(filename_io, FILENAME_MAX-1, "%s.%3.3d-%3.3d", filename, 1, 1); pe_info(cio->pe, "colloid_io_read: reading from single file %s\n", filename_io); } else { @@ -743,7 +743,8 @@ static int colloid_io_filename(colloid_io_t * cio, char * filename, pe_fatal(cio->pe, "Format botch for cio stub %s\n", stub); } - sprintf(filename, "%s.%3.3d-%3.3d", stub, cio->n_io, cio->index + 1); + snprintf(filename, FILENAME_MAX/2-1, "%s.%3.3d-%3.3d", stub, cio->n_io, + cio->index + 1); return 0; } diff --git a/src/colloids_halo.c b/src/colloids_halo.c index f4dbcab87..230d44623 100644 --- a/src/colloids_halo.c +++ b/src/colloids_halo.c @@ -341,7 +341,7 @@ static int colloids_halo_load(colloid_halo_t * halo, int dim) { static int colloids_halo_load_list(colloid_halo_t * halo, int ic, int jc, int kc, - const double * rperiod, int noff) { + const double rperiod[3], int noff) { int n; colloid_t * pc = NULL; diff --git a/src/colloids_rt.c b/src/colloids_rt.c index 537b8a908..10705b731 100644 --- a/src/colloids_rt.c +++ b/src/colloids_rt.c @@ -306,12 +306,12 @@ int colloids_rt_init_from_file(pe_t * pe, rt_t * rt, colloids_info_t * cinfo, ntstep = physics_control_timestep(phys); if (ntstep == 0) { - sprintf(filename, "%s%s", subdirectory, stub); + snprintf(filename, FILENAME_MAX, "%s%s", subdirectory, stub); } else { strcpy(stub, "config.cds"); rt_string_parameter(rt, "colloid_file_stub", stub, BUFSIZ); - sprintf(filename, "%s%s%8.8d", subdirectory, stub, ntstep); + snprintf(filename, 3*FILENAME_MAX, "%s%s%8.8d", subdirectory, stub, ntstep); } colloid_io_read(cio, filename); @@ -389,31 +389,31 @@ int colloids_rt_state_stub(pe_t * pe, rt_t * rt, colloids_info_t * cinfo, state->rebuild = 1; - sprintf(key, "%s_%s", stub, "nbonds"); + snprintf(key, BUFSIZ-1, "%s_%s", stub, "nbonds"); nrt = rt_int_parameter(rt, key, &state->nbonds); if (nrt) pe_info(pe, format_i1, key, state->nbonds); if (state->nbonds > 0) { - sprintf(key, "%s_%s", stub, "bond1"); + snprintf(key, BUFSIZ-1, "%s_%s", stub, "bond1"); nrt = rt_int_parameter(rt, key, &state->bond[0]); if (nrt) pe_info(pe, format_i1, key, state->bond[0]); } if (state->nbonds > 1) { - sprintf(key, "%s_%s", stub, "bond2"); + snprintf(key, BUFSIZ-1, "%s_%s", stub, "bond2"); nrt = rt_int_parameter(rt, key, &state->bond[1]); if (nrt) pe_info(pe, format_i1, key, state->bond[1]); } - sprintf(key, "%s_%s", stub, "nangles"); + snprintf(key, BUFSIZ-1, "%s_%s", stub, "nangles"); nrt = rt_int_parameter(rt, key, &state->nangles); if (nrt) pe_info(pe, format_i1, key, state->nangles); - sprintf(key1, "%s_%s", stub, "isfixedrxyz"); + snprintf(key1, BUFSIZ-1, "%s_%s", stub, "isfixedrxyz"); nrt1 = rt_int_parameter_vector(rt, key1, state->isfixedrxyz); /* Defer output until isfxiedr is known */ - sprintf(key, "%s_%s", stub, "isfixedr"); + snprintf(key, BUFSIZ-1, "%s_%s", stub, "isfixedr"); nrt = rt_int_parameter(rt, key, &state->isfixedr); if (nrt) { pe_info(pe, format_i1, key, state->isfixedr); @@ -425,11 +425,11 @@ int colloids_rt_state_stub(pe_t * pe, rt_t * rt, colloids_info_t * cinfo, if (nrt1) pe_info(pe, format_i3, key1, state->isfixedrxyz[X], state->isfixedrxyz[Y], state->isfixedrxyz[Z]); - sprintf(key1, "%s_%s", stub, "isfixedvxyz"); + snprintf(key1, BUFSIZ-1, "%s_%s", stub, "isfixedvxyz"); nrt1 = rt_int_parameter_vector(rt, key1, state->isfixedvxyz); /* Defer output until isfixedv is known */ - sprintf(key, "%s_%s", stub, "isfixedv"); + snprintf(key, BUFSIZ-1, "%s_%s", stub, "isfixedv"); nrt = rt_int_parameter(rt, key, &state->isfixedv); if (nrt) { pe_info(pe, format_i1, key, state->isfixedv); @@ -441,15 +441,15 @@ int colloids_rt_state_stub(pe_t * pe, rt_t * rt, colloids_info_t * cinfo, if (nrt1) pe_info(pe, format_i3, key1, state->isfixedvxyz[X], state->isfixedvxyz[Y], state->isfixedvxyz[Z]); - sprintf(key, "%s_%s", stub, "isfixedw"); + snprintf(key, BUFSIZ-1, "%s_%s", stub, "isfixedw"); nrt = rt_int_parameter(rt, key, &state->isfixedw); if (nrt) pe_info(pe, format_i1, key, state->isfixedw); - sprintf(key, "%s_%s", stub, "isfixeds"); + snprintf(key, BUFSIZ-1, "%s_%s", stub, "isfixeds"); nrt = rt_int_parameter(rt, key, &state->isfixeds); if (nrt) pe_info(pe, format_i1, key, state->isfixeds); - sprintf(key, "%s_%s", stub, "type"); + snprintf(key, BUFSIZ-1, "%s_%s", stub, "type"); nrt = rt_string_parameter(rt, key, value, BUFSIZ); state->type = COLLOID_TYPE_DEFAULT; @@ -457,71 +457,71 @@ int colloids_rt_state_stub(pe_t * pe, rt_t * rt, colloids_info_t * cinfo, if (strcmp(value, "subgrid") == 0) state->type = COLLOID_TYPE_SUBGRID; if (nrt) pe_info(pe, format_s1, stub, value); - sprintf(key, "%s_%s", stub, "rng"); + snprintf(key, BUFSIZ-1, "%s_%s", stub, "rng"); nrt = rt_int_parameter(rt, key, &state->rng); if (nrt) pe_info(pe, format_i1, key, state->rng); - sprintf(key, "%s_%s", stub, "interact_type"); + snprintf(key, BUFSIZ-1, "%s_%s", stub, "interact_type"); nrt = rt_int_parameter(rt, key, &state->inter_type); if (nrt) pe_info(pe, format_i1, key, state->inter_type); - sprintf(key, "%s_%s", stub, "a0"); + snprintf(key, BUFSIZ-1, "%s_%s", stub, "a0"); nrt = rt_double_parameter(rt, key, &state->a0); if (nrt) pe_info(pe, format_e1, key, state->a0); - sprintf(key, "%s_%s", stub, "ah"); + snprintf(key, BUFSIZ-1, "%s_%s", stub, "ah"); nrt = rt_double_parameter(rt, key, &state->ah); if (nrt) pe_info(pe, format_e1, key, state->ah); - sprintf(key, "%s_%s", stub, "al"); + snprintf(key, BUFSIZ-1, "%s_%s", stub, "al"); nrt = rt_double_parameter(rt, key, &state->al); if (nrt) pe_info(pe, format_e1, key, state->al); - sprintf(key, "%s_%s", stub, "r"); + snprintf(key, BUFSIZ-1, "%s_%s", stub, "r"); nrt = rt_double_parameter_vector(rt, key, state->r); if (nrt) pe_info(pe, format_e3, key, state->r[X], state->r[Y], state->r[Z]); - sprintf(key, "%s_%s", stub, "v"); + snprintf(key, BUFSIZ-1, "%s_%s", stub, "v"); nrt = rt_double_parameter_vector(rt, key, state->v); if (nrt) pe_info(pe, format_e3, key, state->v[X], state->v[Y], state->v[Z]); - sprintf(key, "%s_%s", stub, "w"); + snprintf(key, BUFSIZ-1, "%s_%s", stub, "w"); nrt = rt_double_parameter_vector(rt, key, state->w); if (nrt) pe_info(pe, format_e3, key, state->w[X], state->w[Y], state->w[Z]); - sprintf(key, "%s_%s", stub, "s"); + snprintf(key, BUFSIZ-1, "%s_%s", stub, "s"); nrt = rt_double_parameter_vector(rt, key, state->s); if (nrt) pe_info(pe, format_e3, key, state->s[X], state->s[Y], state->s[Z]); - sprintf(key, "%s_%s", stub, "m"); + snprintf(key, BUFSIZ-1, "%s_%s", stub, "m"); nrt = rt_double_parameter_vector(rt, key, state->m); if (nrt) pe_info(pe, format_e3, key, state->m[X], state->m[Y], state->m[Z]); - sprintf(key, "%s_%s", stub, "b1"); + snprintf(key, BUFSIZ-1, "%s_%s", stub, "b1"); nrt = rt_double_parameter(rt, key, &state->b1); if (nrt) pe_info(pe, format_e1, key, state->b1); - sprintf(key, "%s_%s", stub, "b2"); + snprintf(key, BUFSIZ-1, "%s_%s", stub, "b2"); nrt = rt_double_parameter(rt, key, &state->b2); if (nrt) pe_info(pe, format_e1, key, state->b2); - sprintf(key, "%s_%s", stub, "c"); + snprintf(key, BUFSIZ-1, "%s_%s", stub, "c"); nrt = rt_double_parameter(rt, key, &state->c); if (nrt) pe_info(pe, format_e1, key, state->c); - sprintf(key, "%s_%s", stub, "h"); + snprintf(key, BUFSIZ-1, "%s_%s", stub, "h"); nrt = rt_double_parameter(rt, key, &state->h); if (nrt) pe_info(pe, format_e1, key, state->h); - sprintf(key, "%s_%s", stub, "q0"); + snprintf(key, BUFSIZ-1, "%s_%s", stub, "q0"); nrt = rt_double_parameter(rt, key, &state->q0); if (nrt) pe_info(pe, format_e1, key, state->q0); - sprintf(key, "%s_%s", stub, "q1"); + snprintf(key, BUFSIZ-1, "%s_%s", stub, "q1"); nrt = rt_double_parameter(rt, key, &state->q1); if (nrt) pe_info(pe, format_e1, key, state->q1); - sprintf(key, "%s_%s", stub, "epsilon"); + snprintf(key, BUFSIZ-1, "%s_%s", stub, "epsilon"); nrt = rt_double_parameter(rt, key, &state->epsilon); if (nrt) pe_info(pe, format_e1, key, state->epsilon); diff --git a/src/compiler.c b/src/compiler.c index a6527778e..82e7111fa 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -109,7 +109,8 @@ int compiler_id(compiler_info_t * compiler) { compiler->major = __GNUC__; compiler->minor = __GNUC_MINOR__; compiler->patchlevel = __GNUC_PATCHLEVEL__; - strncpy(compiler->version, __VERSION__, strnlen(__VERSION__, BUFSIZ-1)); + strncpy(compiler->version, __VERSION__, + BUFSIZ - strnlen(__VERSION__, BUFSIZ-1) - 1); sprintf(compiler->name, "%s", "Gnu"); ierr = 0; diff --git a/src/coords.c b/src/coords.c index 67e3b6e87..52aa62a11 100644 --- a/src/coords.c +++ b/src/coords.c @@ -560,6 +560,9 @@ static __host__ int cs_rectilinear_decomposition(cs_t * cs) { for (idim = 0; idim < 3; idim++) { + /* Guard for zealous code scanning */ + assert(0 < mpisz[idim] && mpisz[idim] < 8192); + cs->listnlocal[idim] = (int *) calloc(mpisz[idim], sizeof(int)); cs->listnoffset[idim] = (int *) calloc(mpisz[idim], sizeof(int)); assert(cs->listnlocal[idim]); diff --git a/src/io_harness.c b/src/io_harness.c index cbbb93ba9..aaf38bd44 100644 --- a/src/io_harness.c +++ b/src/io_harness.c @@ -232,8 +232,8 @@ static void io_set_group_filename(char * filename_io, const char * stub, assert(info->io_comm->n_io < 1000); /* format restriction ... */ - sprintf(filename_io, "%s.%3.3d-%3.3d", stub, info->io_comm->n_io, - info->io_comm->index + 1); + sprintf(filename_io, "%s.%3.3d-%3.3d", stub, + info->io_comm->n_io, info->io_comm->index + 1); return; } @@ -443,7 +443,7 @@ int io_write_metadata_file(io_info_t * info, char * filename_stub) { le_uy = 0.0; io_set_group_filename(filename, filename_stub, info); - sprintf(filename_io, "%s.meta", filename); + snprintf(filename_io, 2*FILENAME_MAX, "%s.meta", filename); /* Write local decomposition information to the buffer */ @@ -526,7 +526,7 @@ int io_remove_metadata(io_info_t * obj, const char * file_stub) { if (obj->io_comm->rank == 0) { pe_subdirectory(obj->pe, subdirectory); io_set_group_filename(filename, file_stub, obj); - sprintf(filename_io, "%s%s.meta", subdirectory, filename); + snprintf(filename_io, 2*FILENAME_MAX, "%s%s.meta", subdirectory, filename); remove(filename_io); } @@ -924,7 +924,7 @@ int io_write_data_s(io_info_t * obj, const char * filename_stub, void * data) { if (obj->metadata_written == 0) io_write_metadata(obj); cs_nlocal(obj->cs, nlocal); - sprintf(filename_io, "%s.%3.3d-%3.3d", filename_stub, 1, 1); + snprintf(filename_io, FILENAME_MAX, "%s.%3.3d-%3.3d", filename_stub, 1, 1); itemsz = obj->bytesize; @@ -1113,7 +1113,7 @@ int io_read_data(io_info_t * obj, const char * filename_stub, void * data) { io_set_group_filename(filename_io, filename_stub, obj); if (obj->single_file_read) { - sprintf(filename_io, "%s.%3.3d-%3.3d", filename_stub, 1, 1); + snprintf(filename_io, FILENAME_MAX, "%s.%3.3d-%3.3d", filename_stub, 1, 1); } if (obj->io_comm->rank == 0) { diff --git a/src/runtime.c b/src/runtime.c index dee6b0ad5..7a3a04761 100644 --- a/src/runtime.c +++ b/src/runtime.c @@ -341,7 +341,7 @@ int rt_int_parameter(rt_t * rt, const char * key, int * value) { * *****************************************************************************/ -int rt_double_parameter_vector(rt_t * rt, const char * key, double v[]) { +int rt_double_parameter_vector(rt_t * rt, const char * key, double v[3]) { int key_present = 0; char str_value[NKEY_LENGTH]; @@ -368,7 +368,7 @@ int rt_double_parameter_vector(rt_t * rt, const char * key, double v[]) { * *****************************************************************************/ -int rt_int_parameter_vector(rt_t * rt, const char * key, int v[]) { +int rt_int_parameter_vector(rt_t * rt, const char * key, int v[3]) { int key_present = 0; char str_value[NKEY_LENGTH]; @@ -583,8 +583,8 @@ int rt_active_keys(rt_t * rt, int * nactive) { static int rt_is_valid_key_pair(rt_t * rt, const char * line, int lineno) { - char a[NKEY_LENGTH] = {}; - char b[NKEY_LENGTH] = {}; + char a[NKEY_LENGTH+1] = {}; + char b[NKEY_LENGTH+1] = {}; char fmt[32] = {}; if (strncmp("#", line, 1) == 0) return 0; @@ -684,7 +684,7 @@ static int rt_look_up_key(rt_t * rt, const char * key, char * value) { if (strcmp(a, key) == 0) { pkey->is_active = 0; key_present = 1; - strncpy(value, b, NKEY_LENGTH); + strncpy(value, b, NKEY_LENGTH - strnlen(b, NKEY_LENGTH) - 1); break; } } From e78d007f85fd4a8e026869cd4ab6b4245eba74f1 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Wed, 8 Dec 2021 16:45:28 +0000 Subject: [PATCH 088/117] Fix string truncation warnings --- src/colloids_rt.c | 4 ++-- src/runtime.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/colloids_rt.c b/src/colloids_rt.c index 10705b731..290bf095f 100644 --- a/src/colloids_rt.c +++ b/src/colloids_rt.c @@ -306,12 +306,12 @@ int colloids_rt_init_from_file(pe_t * pe, rt_t * rt, colloids_info_t * cinfo, ntstep = physics_control_timestep(phys); if (ntstep == 0) { - snprintf(filename, FILENAME_MAX, "%s%s", subdirectory, stub); + snprintf(filename, 3*BUFSIZ, "%s%s", subdirectory, stub); } else { strcpy(stub, "config.cds"); rt_string_parameter(rt, "colloid_file_stub", stub, BUFSIZ); - snprintf(filename, 3*FILENAME_MAX, "%s%s%8.8d", subdirectory, stub, ntstep); + snprintf(filename, 3*BUFSIZ, "%s%s%8.8d", subdirectory, stub, ntstep); } colloid_io_read(cio, filename); diff --git a/src/runtime.c b/src/runtime.c index 7a3a04761..e488d1da7 100644 --- a/src/runtime.c +++ b/src/runtime.c @@ -646,7 +646,7 @@ static int rt_add_key_pair(rt_t * rt, const char * key, int lineno) { else { /* Put the new key at the head of the list. */ - strncpy(pnew->key, key, strnlen(key, NKEY_LENGTH-1)); + strncpy(pnew->key, key, NKEY_LENGTH - strnlen(key, NKEY_LENGTH-1) - 1); pnew->is_active = 1; pnew->input_line_no = lineno; From 98e24de60781bc1a0ed7aa6d084b581fa7beb190 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Wed, 8 Dec 2021 16:59:15 +0000 Subject: [PATCH 089/117] Replace sprintf --- src/io_harness.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/io_harness.c b/src/io_harness.c index aaf38bd44..b44fca41c 100644 --- a/src/io_harness.c +++ b/src/io_harness.c @@ -232,7 +232,7 @@ static void io_set_group_filename(char * filename_io, const char * stub, assert(info->io_comm->n_io < 1000); /* format restriction ... */ - sprintf(filename_io, "%s.%3.3d-%3.3d", stub, + snprintf(filename_io, FILENAME_MAX, "%s.%3.3d-%3.3d", stub, info->io_comm->n_io, info->io_comm->index + 1); return; From ad2b02dcd405799a701df0112f4c0071150bd7b3 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Fri, 10 Dec 2021 12:38:27 +0000 Subject: [PATCH 090/117] Some refactoring to remove problematic scanf etc --- src/runtime.c | 170 ++++++++++++++++++++++++++++++++++++++++---------- src/runtime.h | 1 + 2 files changed, 138 insertions(+), 33 deletions(-) diff --git a/src/runtime.c b/src/runtime.c index e488d1da7..419a83bca 100644 --- a/src/runtime.c +++ b/src/runtime.c @@ -47,10 +47,14 @@ #define NKEY_LENGTH 128 /* Maximum key / value string length */ #define NKEY_MAX 1024 /* Prevent buffer overflow in keys */ +/* Relevant key/value separators (include \n to strip them out) */ +static const char * sep_ = " \t\n"; + typedef struct key_pair_s key_pair_t; struct key_pair_s { char key[NKEY_LENGTH]; + char val[NKEY_LENGTH]; int is_active; int input_line_no; key_pair_t * next; @@ -70,6 +74,9 @@ static int rt_look_up_key(rt_t * rt, const char * key, char * value); static int rt_free_keylist(key_pair_t * key); static int rt_vinfo(rt_t * rt, rt_enum_t lv, const char * fmt, ...); +static int rt_line_count_tokens(const char * line); +static int rt_key_value(const char * line, char ** key, char ** val); + /***************************************************************************** * * rt_create @@ -247,8 +254,8 @@ int rt_info(rt_t * rt) { static int rt_key_broadcast(rt_t * rt) { + int nkeys_at_root = 0; char * packed_keys = NULL; - int nk = 0; MPI_Comm comm; assert(rt); @@ -256,10 +263,11 @@ static int rt_key_broadcast(rt_t * rt) { /* Broacdcast the number of keys and set up the message. */ - MPI_Bcast(&rt->nkeys, 1, MPI_INT, 0, comm); + nkeys_at_root = rt->nkeys; + MPI_Bcast(&nkeys_at_root, 1, MPI_INT, 0, comm); - if (rt->nkeys <= NKEY_MAX) { - packed_keys = (char *) calloc(rt->nkeys*NKEY_LENGTH, sizeof(char)); + if (nkeys_at_root <= NKEY_MAX) { + packed_keys = (char *) calloc(2*nkeys_at_root*NKEY_LENGTH, sizeof(char)); assert(packed_keys); } @@ -269,21 +277,28 @@ static int rt_key_broadcast(rt_t * rt) { if (pe_mpi_rank(rt->pe) == 0) { key_pair_t * key = rt->keylist; + int nk = 0; for ( ; key; key = key->next) { strncpy(packed_keys + nk*NKEY_LENGTH, key->key, NKEY_LENGTH); nk += 1; + strncpy(packed_keys + nk*NKEY_LENGTH, key->val, NKEY_LENGTH); + nk += 1; } + assert(nk == 2*rt->nkeys); } - MPI_Bcast(packed_keys, rt->nkeys*NKEY_LENGTH, MPI_CHAR, 0, comm); + MPI_Bcast(packed_keys, 2*nkeys_at_root*NKEY_LENGTH, MPI_CHAR, 0, comm); /* Unpack message and set up the list */ if (pe_mpi_rank(rt->pe) != 0) { - for (nk = 0; nk < rt->nkeys; nk++) { - rt_add_key_pair(rt, packed_keys + nk*NKEY_LENGTH, 0); + for (int nk = 0; nk < nkeys_at_root; nk++) { + char * key = packed_keys + (2*nk )*NKEY_LENGTH; + char * val = packed_keys + (2*nk+1)*NKEY_LENGTH; + rt_add_key_value(rt, key, val); } + assert(rt->nkeys == nkeys_at_root); } free(packed_keys); @@ -583,9 +598,10 @@ int rt_active_keys(rt_t * rt, int * nactive) { static int rt_is_valid_key_pair(rt_t * rt, const char * line, int lineno) { - char a[NKEY_LENGTH+1] = {}; - char b[NKEY_LENGTH+1] = {}; - char fmt[32] = {}; + assert(rt); + assert(line); + + /* Ignore comments and blank lines */ if (strncmp("#", line, 1) == 0) return 0; if (strncmp("\n", line, 1) == 0) return 0; @@ -593,34 +609,90 @@ static int rt_is_valid_key_pair(rt_t * rt, const char * line, int lineno) { /* Minimal syntax checks. The user will need to sort these * out. */ - snprintf(fmt, sizeof(fmt), "%%%ds %%%ds", NKEY_LENGTH-1, NKEY_LENGTH-1); - - if (sscanf(line, fmt, a, b) != 2) { + if (rt_line_count_tokens(line) < 2) { /* This does not look like a key value pair... */ - pe_fatal(rt->pe, "Please check input file syntax at line %d:\n %s\n", - lineno, line); + pe_fatal(rt->pe, "Input file at line %d has %d token:\n %s\n", + lineno, rt_line_count_tokens(line), line); } else { /* Check against existing keys for duplicate definitions. */ + char * newkey = NULL; + char * newval = NULL; - key_pair_t * key = rt->keylist; + rt_key_value(line, &newkey, &newval); + + if (strncmp(newval, "#", 1) == 0) { + pe_info(rt->pe, "Second token in line must not be a comment\n"); + pe_fatal(rt->pe, "Please check input line at line %d\n", lineno); + } - while (key) { + if (rt_key_present(rt, newkey)) { + /* Duplicate */ + } - /* We must compare for exact equality against existing key. */ - sscanf(key->key, "%s ", b); + free(newkey); + free(newval); + } - if (strcmp(b, a) == 0) { - pe_info(rt->pe, "At line %d: %s\n", lineno, line); - pe_fatal(rt->pe, "Duplication of parameters in input file: %s %s\n", - a, b); - } + return 1; +} + +/***************************************************************************** + * + * rt_line_count_tokens + * + * Count " " separated tokens in line. + * + *****************************************************************************/ + +static int rt_line_count_tokens(const char * line) { + + int ntok = 0; + + assert(line); + + { + char * copy = strndup(line, BUFSIZ); + char * token = strtok(copy, sep_); - key = key->next; + while (token) { + ntok += 1; + token = strtok(NULL, sep_); } + + free(copy); } - return 1; + return ntok; +} + +/***************************************************************************** + * + * rt_key_value + * + * Parse a single string as space-separated key value. + * A new copy of the key and value are returned. + * + * Returns 0 on sucess. + * + *****************************************************************************/ + +static int rt_key_value(const char * line, char ** key, char ** val) { + + int ifail = 0; + int ntok = rt_line_count_tokens(line); + + if (ntok < 2) { + ifail = -1; + } + else { + char * copy = strndup(line, BUFSIZ); + *key = strdup(strtok(copy, sep_)); + *val = strdup(strtok(NULL, sep_)); + free(copy); + } + + return ifail; } /***************************************************************************** @@ -646,17 +718,51 @@ static int rt_add_key_pair(rt_t * rt, const char * key, int lineno) { else { /* Put the new key at the head of the list. */ - strncpy(pnew->key, key, NKEY_LENGTH - strnlen(key, NKEY_LENGTH-1) - 1); + char * newkey = NULL; + char * newval = NULL; + + rt_key_value(key, &newkey, &newval); + strncpy(pnew->key, newkey, NKEY_LENGTH - strnlen(newkey, NKEY_LENGTH) - 1); + strncpy(pnew->val, newval, NKEY_LENGTH - strnlen(newval, NKEY_LENGTH) - 1); + pnew->is_active = 1; pnew->input_line_no = lineno; pnew->next = rt->keylist; rt->keylist = pnew; + + free(newkey); + free(newval); } return 0; } +/***************************************************************************** + * + * rt_key_present + * + * Is the key present in the list at all? + * + *****************************************************************************/ + +int rt_key_present(rt_t * rt, const char * key) { + + int present = 0; + key_pair_t * pair = NULL; + + assert(rt); + + for ( ; pair; pair = pair->next) { + if (strncmp(key, pair->key, NKEY_LENGTH) == 0) { + present = 1; + break; + } + } + + return present; +} + /***************************************************************************** * * rt_look_up_key @@ -669,8 +775,6 @@ static int rt_add_key_pair(rt_t * rt, const char * key, int lineno) { static int rt_look_up_key(rt_t * rt, const char * key, char * value) { int key_present = 0; - char a[NKEY_LENGTH]; - char b[NKEY_LENGTH]; key_pair_t * pkey; assert(rt); @@ -679,12 +783,12 @@ static int rt_look_up_key(rt_t * rt, const char * key, char * value) { for ( ; pkey; pkey = pkey->next) { - sscanf(pkey->key, "%s %s", a, b); - - if (strcmp(a, key) == 0) { + if (strcmp(pkey->key, key) == 0) { + int len = strnlen(pkey->val, NKEY_LENGTH); pkey->is_active = 0; key_present = 1; - strncpy(value, b, NKEY_LENGTH - strnlen(b, NKEY_LENGTH) - 1); + strncpy(value, pkey->val, NKEY_LENGTH - len - 1); + break; } } diff --git a/src/runtime.h b/src/runtime.h index 8d1f9aa37..4b79cb82f 100644 --- a/src/runtime.h +++ b/src/runtime.h @@ -39,6 +39,7 @@ int rt_add_key_value(rt_t * rt, const char * key, const char * value); int rt_int_nvector(rt_t * rt, const char * key, int nv, int * v, rt_enum_t lv); int rt_double_nvector(rt_t * rt, const char * key, int nv, double * v, rt_enum_t level); +int rt_key_present(rt_t * rt, const char * key); int rt_key_required(rt_t * rt, const char * key, rt_enum_t level); int rt_report_unused_keys(rt_t * rt, rt_enum_t level); From bab0ed8bce83802e693d8b78f5979f58a0e48908 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Fri, 10 Dec 2021 14:00:14 +0000 Subject: [PATCH 091/117] Further replace sprintf --- src/runtime.c | 78 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 26 deletions(-) diff --git a/src/runtime.c b/src/runtime.c index 419a83bca..502c56e1f 100644 --- a/src/runtime.c +++ b/src/runtime.c @@ -74,8 +74,11 @@ static int rt_look_up_key(rt_t * rt, const char * key, char * value); static int rt_free_keylist(key_pair_t * key); static int rt_vinfo(rt_t * rt, rt_enum_t lv, const char * fmt, ...); +static int rt_is_valid_token(const char * token); static int rt_line_count_tokens(const char * line); static int rt_key_value(const char * line, char ** key, char ** val); +static int rt_add_key_value_pair(rt_t * rt, const char * key, + const char * val, int lineno); /***************************************************************************** * @@ -169,7 +172,6 @@ int rt_read_input_file(rt_t * rt, const char * input_file_name) { /* Look at the line and add it if it's a key. */ if (rt_is_valid_key_pair(rt, line, nline)) { rt_add_key_pair(rt, line, nline); - rt->nkeys += 1; } if (rt->nkeys > NKEY_MAX) { pe_fatal(rt->pe, "Too many keys! Increase NKEY_MAX %d\n", NKEY_MAX); @@ -205,22 +207,12 @@ int rt_add_key_value(rt_t * rt, const char * key, const char * value) { assert(key); assert(value); - /* Form a new line with a space between key and value */ - + /* Say the line is just the number of keys */ nline = rt->nkeys + 1; - if (strlen(key) + strlen(value) >= NKEY_LENGTH - 2) { - /* avoid buffer overflow */ - } - else { - char line[NKEY_LENGTH]; - sprintf(line, "%s %s", key, value); - - if (rt_is_valid_key_pair(rt, line, nline)) { - rt_add_key_pair(rt, line, nline); - rt->nkeys += 1; - added = 1; - } + if (rt_is_valid_token(key) && rt_is_valid_token(value)) { + rt_add_key_value_pair(rt, key, value, nline); + added = 1; } return added; @@ -585,6 +577,26 @@ int rt_active_keys(rt_t * rt, int * nactive) { return 0; } +/***************************************************************************** + * + * rt_is_valid_token + * + * Some checks on allowable tokens for either keys or values. + * + *****************************************************************************/ + +static int rt_is_valid_token(const char * token) { + + int isvalid = 1; + + assert(token); + + if (rt_line_count_tokens(token) != 1) isvalid = 0; + if (strncmp(token, "#", 1) == 0) isvalid = 0; + + return isvalid; +} + /***************************************************************************** * * rt_is_valid_key @@ -627,7 +639,8 @@ static int rt_is_valid_key_pair(rt_t * rt, const char * line, int lineno) { } if (rt_key_present(rt, newkey)) { - /* Duplicate */ + pe_info(rt->pe, "Key %s (line %d) is already present\n", newkey, lineno); + pe_fatal(rt->pe, "Please check the input and remove one or other\n"); } free(newkey); @@ -703,8 +716,27 @@ static int rt_key_value(const char * line, char ** key, char ** val) { * *****************************************************************************/ -static int rt_add_key_pair(rt_t * rt, const char * key, int lineno) { +static int rt_add_key_pair(rt_t * rt, const char * line, int lineno) { + int ifail = 0; + char * newkey = NULL; + char * newval = NULL; + + assert(rt); + assert(line); + + rt_key_value(line, &newkey, &newval); + + ifail = rt_add_key_value_pair(rt, newkey, newval, lineno); + + free(newkey); + free(newval); + + return ifail; +} + +static int rt_add_key_value_pair(rt_t * rt, const char * key, + const char * val, int lineno) { key_pair_t * pnew = NULL; assert(rt); @@ -717,22 +749,16 @@ static int rt_add_key_pair(rt_t * rt, const char * key, int lineno) { } else { /* Put the new key at the head of the list. */ + rt->nkeys += 1; - char * newkey = NULL; - char * newval = NULL; - - rt_key_value(key, &newkey, &newval); - strncpy(pnew->key, newkey, NKEY_LENGTH - strnlen(newkey, NKEY_LENGTH) - 1); - strncpy(pnew->val, newval, NKEY_LENGTH - strnlen(newval, NKEY_LENGTH) - 1); + strncpy(pnew->key, key, NKEY_LENGTH - strnlen(key, NKEY_LENGTH) - 1); + strncpy(pnew->val, val, NKEY_LENGTH - strnlen(val, NKEY_LENGTH) - 1); pnew->is_active = 1; pnew->input_line_no = lineno; pnew->next = rt->keylist; rt->keylist = pnew; - - free(newkey); - free(newval); } return 0; From 688df98073a9f82435b10c5e5ff9bce98eadbea8 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Fri, 10 Dec 2021 14:52:53 +0000 Subject: [PATCH 092/117] Use official cart dims in allocation --- src/coords.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/coords.c b/src/coords.c index 52aa62a11..2d5e29962 100644 --- a/src/coords.c +++ b/src/coords.c @@ -173,8 +173,6 @@ __host__ int cs_init(cs_t * cs) { MPI_Dims_create(pe_mpi_size(cs->pe), 3, cs->param->mpi_cartsz); } - cs_rectilinear_decomposition(cs); - /* A communicator which is always periodic: */ MPI_Cart_create(comm, 3, cs->param->mpi_cartsz, iperiodic, cs->reorder, @@ -200,6 +198,8 @@ __host__ int cs_init(cs_t * cs) { /* Set local number of lattice sites and offsets. */ + cs_rectilinear_decomposition(cs); + cs->param->nlocal[X] = cs->listnlocal[X][cs->param->mpi_cartcoords[X]]; cs->param->nlocal[Y] = cs->listnlocal[Y][cs->param->mpi_cartcoords[Y]]; cs->param->nlocal[Z] = cs->listnlocal[Z][cs->param->mpi_cartcoords[Z]]; @@ -545,12 +545,19 @@ static __host__ int cs_rectilinear_decomposition(cs_t * cs) { int idim; int n, ntot, nremainder; - int mpisz[3]; int ntotal[3]; + int mpisz[3] = {}; assert(cs); - cs_cartsz(cs, mpisz); + { + int dims[3] = {}; + int coords[3] = {}; + int periods[3] = {}; + MPI_Cart_get(cs->commcart, 3, dims, coords, periods); + mpisz[X] = dims[X]; mpisz[Y] = dims[Y]; mpisz[Z] = dims[Z]; + } + cs_ntotal(cs, ntotal); /* For each direction in turn: @@ -560,9 +567,6 @@ static __host__ int cs_rectilinear_decomposition(cs_t * cs) { for (idim = 0; idim < 3; idim++) { - /* Guard for zealous code scanning */ - assert(0 < mpisz[idim] && mpisz[idim] < 8192); - cs->listnlocal[idim] = (int *) calloc(mpisz[idim], sizeof(int)); cs->listnoffset[idim] = (int *) calloc(mpisz[idim], sizeof(int)); assert(cs->listnlocal[idim]); From 9f577916fbc130e18fb633987e6dc95dcd106118 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Fri, 10 Dec 2021 15:23:33 +0000 Subject: [PATCH 093/117] Remove useless assertions --- src/util_sum.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/util_sum.c b/src/util_sum.c index 175591124..73bb4172d 100644 --- a/src/util_sum.c +++ b/src/util_sum.c @@ -233,7 +233,6 @@ __host__ void kahan_mpi_op_sum_function(kahan_t * invec, kahan_t * inoutvec, __host__ int kahan_mpi_op_sum(MPI_Op * op) { - assert(kahan_mpi_op_sum_function); assert(op); MPI_Op_create((MPI_User_function *) kahan_mpi_op_sum_function, 0, op); @@ -310,7 +309,6 @@ __host__ void klein_mpi_op_sum_function(klein_t * invec, klein_t * inoutvec, __host__ int klein_mpi_op_sum(MPI_Op * op) { - assert(klein_mpi_op_sum_function); assert(op); MPI_Op_create((MPI_User_function *) klein_mpi_op_sum_function, 0, op); From 5df42e2aa2d2aa4d76d86e295949b3e6869f0549 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Fri, 10 Dec 2021 16:52:01 +0000 Subject: [PATCH 094/117] Fix to allow general model --- tests/unit/test_lb_bc_inflow_rhou.c | 17 +++++++++-------- tests/unit/test_lb_bc_outflow_rhou.c | 16 ++++++++-------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/tests/unit/test_lb_bc_inflow_rhou.c b/tests/unit/test_lb_bc_inflow_rhou.c index b5feb29ec..bf72220f7 100644 --- a/tests/unit/test_lb_bc_inflow_rhou.c +++ b/tests/unit/test_lb_bc_inflow_rhou.c @@ -22,8 +22,8 @@ /* Tests */ __host__ int test_lb_bc_inflow_rhou_create(pe_t * pe, cs_t * cs); -__host__ int test_lb_bc_inflow_rhou_update(pe_t * pe, cs_t * cs); -__host__ int test_lb_bc_inflow_rhou_impose(pe_t * pe, cs_t * cs); +__host__ int test_lb_bc_inflow_rhou_update(pe_t * pe, cs_t * cs, int nvel); +__host__ int test_lb_bc_inflow_rhou_impose(pe_t * pe, cs_t * cs, int nvel); /***************************************************************************** * @@ -41,8 +41,8 @@ __host__ int test_lb_bc_inflow_rhou_suite(void) { cs_init(cs); test_lb_bc_inflow_rhou_create(pe, cs); - test_lb_bc_inflow_rhou_update(pe, cs); - test_lb_bc_inflow_rhou_impose(pe, cs); + test_lb_bc_inflow_rhou_update(pe, cs, NVEL); + test_lb_bc_inflow_rhou_impose(pe, cs, NVEL); pe_info(pe, "PASS ./unit/test_lb_bc_inflow_rhou\n"); @@ -97,13 +97,13 @@ __host__ int test_lb_bc_inflow_rhou_create(pe_t * pe, cs_t * cs) { * *****************************************************************************/ -__host__ int test_lb_bc_inflow_rhou_update(pe_t * pe, cs_t * cs) { +__host__ int test_lb_bc_inflow_rhou_update(pe_t * pe, cs_t * cs, int nvel) { int nlocal[3] = {}; int noffset[3] = {}; double rho0 = 2.0; - lb_bc_inflow_opts_t options = {.nvel = 15, + lb_bc_inflow_opts_t options = {.nvel = nvel, .flow = {1, 0, 0}, .u0 = {-1.0,-2.0,-3.0}}; lb_bc_inflow_rhou_t * inflow = NULL; @@ -172,9 +172,10 @@ __host__ int test_lb_bc_inflow_rhou_update(pe_t * pe, cs_t * cs) { * * test_lb_bc_inflow_rhou_impose * + * *****************************************************************************/ -__host__ int test_lb_bc_inflow_rhou_impose(pe_t * pe, cs_t * cs) { +__host__ int test_lb_bc_inflow_rhou_impose(pe_t * pe, cs_t * cs, int nvel) { int ierr = 0; @@ -184,7 +185,7 @@ __host__ int test_lb_bc_inflow_rhou_impose(pe_t * pe, cs_t * cs) { double rho0 = 1.0; - lb_bc_inflow_opts_t options = {.nvel = 19, + lb_bc_inflow_opts_t options = {.nvel = nvel, .flow = {1, 0, 0}, .u0 = {0.01, 0.0, 0.0}}; lb_bc_inflow_rhou_t * inflow = NULL; diff --git a/tests/unit/test_lb_bc_outflow_rhou.c b/tests/unit/test_lb_bc_outflow_rhou.c index 71228fa3a..4c05d716c 100644 --- a/tests/unit/test_lb_bc_outflow_rhou.c +++ b/tests/unit/test_lb_bc_outflow_rhou.c @@ -20,8 +20,8 @@ #include "lb_bc_outflow_rhou.h" __host__ int test_lb_bc_outflow_rhou_create(pe_t * pe, cs_t * cs); -__host__ int test_lb_bc_outflow_rhou_update(pe_t * pe, cs_t * cs); -__host__ int test_lb_bc_outflow_rhou_impose(pe_t * pe, cs_t * cs); +__host__ int test_lb_bc_outflow_rhou_update(pe_t * pe, cs_t * cs, int nvel); +__host__ int test_lb_bc_outflow_rhou_impose(pe_t * pe, cs_t * cs, int nvel); /***************************************************************************** * @@ -39,8 +39,8 @@ __host__ int test_lb_bc_outflow_rhou_suite(void) { cs_init(cs); test_lb_bc_outflow_rhou_create(pe, cs); - test_lb_bc_outflow_rhou_update(pe, cs); - test_lb_bc_outflow_rhou_impose(pe, cs); + test_lb_bc_outflow_rhou_update(pe, cs, NVEL); + test_lb_bc_outflow_rhou_impose(pe, cs, NVEL); pe_info(pe, "PASS ./unit/test_lb_bc_outflow_rhou\n"); @@ -89,13 +89,13 @@ __host__ int test_lb_bc_outflow_rhou_create(pe_t * pe, cs_t * cs) { * *****************************************************************************/ -__host__ int test_lb_bc_outflow_rhou_update(pe_t * pe, cs_t * cs) { +__host__ int test_lb_bc_outflow_rhou_update(pe_t * pe, cs_t * cs, int nvel) { int nlocal[3] = {}; int ntotal[3] = {}; int noffset[3] = {}; - lb_bc_outflow_opts_t options = {.nvel = 9, + lb_bc_outflow_opts_t options = {.nvel = nvel, .flow = {0, 1, 0}, .rho0 = 2.0}; lb_bc_outflow_rhou_t * outflow = NULL; @@ -145,7 +145,7 @@ __host__ int test_lb_bc_outflow_rhou_update(pe_t * pe, cs_t * cs) { * *****************************************************************************/ -__host__ int test_lb_bc_outflow_rhou_impose(pe_t * pe, cs_t * cs) { +__host__ int test_lb_bc_outflow_rhou_impose(pe_t * pe, cs_t * cs, int nvel) { int ierr = 0; @@ -153,7 +153,7 @@ __host__ int test_lb_bc_outflow_rhou_impose(pe_t * pe, cs_t * cs) { int ntotal[3] = {}; int noffset[3] = {}; - lb_bc_outflow_opts_t options = {.nvel = 19, + lb_bc_outflow_opts_t options = {.nvel = nvel, .flow = {0, 0, 1}, .rho0 = 3.0}; lb_bc_outflow_rhou_t * outflow = NULL; From 4ebf29254c41021b573ebeb2551a9e2187f6f44a Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Sat, 11 Dec 2021 15:22:45 +0000 Subject: [PATCH 095/117] Improve 4th order sescription --- src/lb_d3q27.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/lb_d3q27.c b/src/lb_d3q27.c index 6c98c6587..cdd8bd775 100644 --- a/src/lb_d3q27.c +++ b/src/lb_d3q27.c @@ -126,8 +126,8 @@ int lb_d3q27_create(lb_model_t * model) { * [18] H_iyyzz (c_iy c_iy - cs2)*(c_iz c_iz - cs2) * [19] H_izzxx ... * - * Four 4th order polynomials H_ixxyz, etc (ORTHOGONALISED against H_i) - * [20] H_ixxyz c_ix c_ix c_iy c_iz - cs2 c_iy c_iz - cs4 + * Four 4th order polynomials H_ixxyz, etc + * [20] H_ixxyz (c_ix c_ix - cs2) c_iy c_iz * [21] H_iyyzx ... * [22] H_izzxy ... * @@ -140,6 +140,7 @@ int lb_d3q27_create(lb_model_t * model) { * [26] H_ixxyyzz H_ixxyy (c_iz c_iz - cs2) * * + * A case of a complete basis with all Hermite polynomials. * See, e.g., Coreixas et al. PRE 96 033306 (2017) for a broad * description of construction of models from Hermite tensors. * @@ -180,9 +181,9 @@ static int lb_d3q27_matrix_ma(lb_model_t * model) { model->ma[17][p] = 9.0*(cx*cx - cs2)*(cy*cy - cs2); model->ma[18][p] = 9.0*(cy*cy - cs2)*(cz*cz - cs2); model->ma[19][p] = 9.0*(cz*cz - cs2)*(cx*cx - cs2); - model->ma[20][p] = 9.0*(cx*cx*cy*cz - cs2*cy*cz + cs2*cs2) - 1.0; - model->ma[21][p] = 9.0*(cy*cy*cz*cx - cs2*cz*cx + cs2*cs2) - 1.0; - model->ma[22][p] = 9.0*(cz*cz*cx*cy - cs2*cx*cy + cs2*cs2) - 1.0; + model->ma[20][p] = 9.0*(cx*cx - cs2)*cy*cz; + model->ma[21][p] = 9.0*(cy*cy - cs2)*cz*cx; + model->ma[22][p] = 9.0*(cz*cz - cs2)*cx*cy; model->ma[23][p] = 9.0*(cx*cx - cs2)*(cy*cy - cs2)*cz; model->ma[24][p] = 9.0*(cy*cy - cs2)*(cz*cz - cs2)*cx; model->ma[25][p] = 9.0*(cz*cz - cs2)*(cx*cx - cs2)*cy; From 6abbba294e3ea299600971cd9a6ca8d5ce73c18b Mon Sep 17 00:00:00 2001 From: not populated Date: Mon, 13 Dec 2021 10:54:09 +0000 Subject: [PATCH 096/117] Minor fix --- src/lc_droplet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lc_droplet.c b/src/lc_droplet.c index 5ba722310..a33a909f5 100644 --- a/src/lc_droplet.c +++ b/src/lc_droplet.c @@ -598,7 +598,7 @@ int fe_lc_droplet_str_symm(fe_lc_droplet_t * fe, int index, double sth[3][3]){ /* Put active stress here (even if zero) */ { - double phi = 0; + double phi = 0.0; double sa[3][3] = {}; field_scalar(fe->symm->phi, index, &phi); From 5de8f50a45319a72297c9e9f215250855de00402 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Mon, 13 Dec 2021 14:30:44 +0000 Subject: [PATCH 097/117] Update for tested open condition --- tests/regression/d2q9/serial-open-phi.log | 70 +++++++++++++++-------- 1 file changed, 46 insertions(+), 24 deletions(-) diff --git a/tests/regression/d2q9/serial-open-phi.log b/tests/regression/d2q9/serial-open-phi.log index ee535d89d..414ea8ade 100644 --- a/tests/regression/d2q9/serial-open-phi.log +++ b/tests/regression/d2q9/serial-open-phi.log @@ -1,5 +1,5 @@ Welcome to Ludwig v0.14.0 (Serial version running on 1 process) -Start time: Thu Nov 18 11:47:58 2021 +Start time: Mon Dec 13 14:29:42 2021 Compiler: name: Gnu 11.2.0 @@ -74,6 +74,28 @@ Hydrodynamics ------------- Hydrodynamics: on +Hydrodynamic open boundary condition for inflow +Inflow type: rhou +Inflow flow profile: uniform +Inflow flow direction: 1 0 0 +Inflow flow value u0: 1.0000000e-02 0.0000000e+00 0.0000000e+00 + +Hydrodynamic open boundary condition at outflow +Outflow type: rhou +Outflow flow direction: 1 0 0 +Outflow flow rho0: 1.0000000e+00 + +Order parameter +--------------- + +Inflow open boundary for composition (phi) +Composition inflow condition: fixed +Composition inflow direction: 1 0 0 +Composition inflow phi_b: 1.0000000e+00 + +Outflow open boundary for composition (phi) +Composition outflow condition: free + Order parameter I/O ------------------- Order parameter I/O format: @@ -112,19 +134,19 @@ Momentum - x y z Starting time step loop. Scalars - total mean variance min max -[rho] 3200.09 1.00002739061 9.3509479e-06 0.99481135726 1.01392358365 -[phi] 2.7928350e+03 8.7276095e-01 2.0154281e-01 -1.0030607e+00 1.0027681e+00 +[rho] 3200.09 1.00002744913 9.3513571e-06 0.99481135726 1.01392358365 +[phi] 2.7928351e+03 8.7276096e-01 2.0154282e-01 -1.0030607e+00 1.0027424e+00 Free energies - timestep f v f/v f_s1 fs_s2 -[fe] 10 -4.7838937700e+01 3.2000000000e+03 -1.4949668031e-02 0.0000000000e+00 0.0000000000e+00 +[fe] 10 -4.7838937863e+01 3.2000000000e+03 -1.4949668082e-02 0.0000000000e+00 0.0000000000e+00 Momentum - x y z -[total ] 3.2068535e+01 1.9290125e-15 0.0000000e+00 -[fluid ] 3.0263827e+01 5.0067189e-04 0.0000000e+00 -[walls ] 1.8047079e+00 -5.0067189e-04 0.0000000e+00 +[total ] 3.2067742e+01 -1.4727802e-15 0.0000000e+00 +[fluid ] 3.0263450e+01 5.0067189e-04 0.0000000e+00 +[walls ] 1.8042912e+00 -5.0067189e-04 0.0000000e+00 Velocity - x y z -[minimum ] 2.8443251e-03 -6.4426101e-03 0.0000000e+00 +[minimum ] 2.8439734e-03 -6.4426101e-03 0.0000000e+00 [maximum ] 1.6515746e-02 6.4426101e-03 1.1754944e-38 Completed cycle 10 @@ -133,20 +155,20 @@ Timer resolution: 1e-06 second Timer statistics Section: tmin tmax total - Total: 0.166 0.166 0.166 0.165952 (1 call) - Time step loop: 0.015 0.018 0.157 0.015683 (10 calls) - Propagation: 0.002 0.003 0.023 0.002265 (10 calls) - Propagtn (krnl) : 0.002 0.003 0.023 0.002259 (10 calls) - Collision: 0.005 0.006 0.050 0.004985 (10 calls) - Collision (krnl) : 0.005 0.006 0.050 0.004979 (10 calls) - Lattice halos: 0.001 0.002 0.013 0.001320 (10 calls) - phi gradients: 0.000 0.001 0.005 0.000459 (10 calls) - phi halos: 0.000 0.000 0.003 0.000343 (10 calls) - BBL: 0.000 0.000 0.001 0.000050 (10 calls) - Force calculation: 0.003 0.004 0.031 0.003059 (10 calls) - phi update: 0.003 0.004 0.031 0.003135 (10 calls) - Advectn (krnl) : 0.001 0.001 0.008 0.000781 (10 calls) - Advectn BCS (krnl) : 0.001 0.001 0.008 0.000831 (10 calls) - Free1: 0.000 0.001 0.001 0.000150 (10 calls) -End time: Thu Nov 18 11:47:58 2021 + Total: 0.163 0.163 0.163 0.162859 (1 call) + Time step loop: 0.015 0.018 0.154 0.015379 (10 calls) + Propagation: 0.002 0.002 0.021 0.002136 (10 calls) + Propagtn (krnl) : 0.002 0.002 0.021 0.002131 (10 calls) + Collision: 0.005 0.005 0.050 0.005040 (10 calls) + Collision (krnl) : 0.005 0.005 0.050 0.005035 (10 calls) + Lattice halos: 0.001 0.002 0.012 0.001241 (10 calls) + phi gradients: 0.000 0.001 0.005 0.000476 (10 calls) + phi halos: 0.000 0.000 0.004 0.000353 (10 calls) + BBL: 0.000 0.000 0.000 0.000049 (10 calls) + Force calculation: 0.003 0.004 0.030 0.003014 (10 calls) + phi update: 0.003 0.003 0.030 0.003008 (10 calls) + Advectn (krnl) : 0.001 0.001 0.007 0.000740 (10 calls) + Advectn BCS (krnl) : 0.001 0.001 0.008 0.000825 (10 calls) + Free1: 0.000 0.001 0.001 0.000143 (10 calls) +End time: Mon Dec 13 14:29:42 2021 Ludwig finished normally. From 3873d97f13f09dbb9d1fa1fb83e19480500211ab Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Mon, 13 Dec 2021 14:52:02 +0000 Subject: [PATCH 098/117] Add halo swap in rho u --- src/lb_bc_outflow_rhou.c | 195 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 195 insertions(+) diff --git a/src/lb_bc_outflow_rhou.c b/src/lb_bc_outflow_rhou.c index 38dde7a31..122258534 100644 --- a/src/lb_bc_outflow_rhou.c +++ b/src/lb_bc_outflow_rhou.c @@ -27,6 +27,7 @@ #include "lb_model.h" #include "lb_bc_outflow_rhou.h" +#include "cs_limits.h" typedef enum {LINK_COUNT, LINK_ASSIGN} link_init_enum_t; @@ -279,6 +280,196 @@ __host__ int lb_bc_outflow_rhou_update(lb_bc_outflow_rhou_t * outflow, return 0; } +/***************************************************************************** + * + * lb_bc_outflow_rhou_halo + * + * There is a lot in common with the inflow hlow which should be + * abstracted away as only dependent on hydro_t. + * + * Apart from being at the other end of the system. + * + *****************************************************************************/ + +__host__ int lb_bc_outflow_rhou_halo_update(lb_bc_outflow_rhou_t * outflow, + hydro_t * hydro) { + cs_t * cs = NULL; + int noffset[3] = {}; + int ntotal[3] = {}; + int nlocal[3] = {}; + + const int tag = 12348; + + assert(outflow); + assert(hydro); + + cs = outflow->cs; + cs_ntotal(cs, ntotal); + cs_nlocal(cs, nlocal); + cs_nlocal_offset(cs, noffset); + + /* Must have flow in x-direction at the moment! */ + assert(outflow->options.flow[X]); + + if (noffset[X] + nlocal[X] == ntotal[X]) { + + MPI_Comm comm = MPI_COMM_NULL; + MPI_Request req[8] = {}; + double *buf[8] = {}; + int ngbr[8] = {}; + int count[8] = {}; /* Data items */ + int nhalo = 1; /* Only ever one if distributions are involved. */ + + /* Recv from ... */ + cs_cart_comm(cs, &comm); + ngbr[0] = cs_cart_neighb(cs, FORWARD, Y); + ngbr[1] = cs_cart_neighb(cs, BACKWARD, Y); + ngbr[2] = cs_cart_neighb(cs, FORWARD, Z); + ngbr[3] = cs_cart_neighb(cs, BACKWARD, Z); + + /* Send to ... */ + ngbr[4] = cs_cart_neighb(cs, BACKWARD, Y); + ngbr[5] = cs_cart_neighb(cs, FORWARD, Y); + ngbr[6] = cs_cart_neighb(cs, BACKWARD, Z); + ngbr[7] = cs_cart_neighb(cs, FORWARD, Z); + + { + int countY = 4*nlocal[Z]*nhalo*nhalo; /* 4 (rho, u_x, u_y, u_z) */ + int countZ = 4*nlocal[Y]*nhalo*nhalo; + count[0] = countY; + count[1] = countY; + count[2] = countZ; + count[3] = countZ; + count[4] = countY; + count[5] = countY; + count[6] = countZ; + count[7] = countZ; + } + + for (int m = 0; m < 8; m++) { + pe_t * pe = hydro->pe; + req[m] = MPI_REQUEST_NULL; + buf[m] = (double *) malloc(sizeof(double)*count[m]); + assert(buf[m]); + if (buf[m] == NULL) pe_fatal(pe, "malloc() failed\n"); + } + + /* Post receives */ + for (int m = 0; m < 4; m++) { + MPI_Irecv(buf[m], count[m], MPI_DOUBLE, ngbr[m], tag, comm, req + m); + } + + /* Pack buffers and post sends */ + for (int ms = 0; ms < 4; ms++) { + int m = 4 + ms; + int ib = 0; + int nhm1 = nhalo-1; + cs_limits_t lim = {}; + + if (m == 4) { /* send to Y-1,Z */ + lim.jmin = 1; lim.jmax = nhalo; + lim.kmin = 1; lim.kmax = nlocal[Z]; + } + if (m == 5) { /* send to Y+1,Z */ + lim.jmin = nlocal[Y] - nhm1; lim.jmax = nlocal[Y]; + lim.kmin = 1; lim.kmax = nlocal[Z]; + } + if (m == 6) { /* send to Y,Z-1 */ + lim.jmin = 1; lim.jmax = nlocal[Y]; + lim.kmin = 1; lim.kmax = nhalo; + } + if (m == 7) { /* send to Y,Z+1 */ + lim.jmin = 1; lim.jmax = nlocal[Y]; + lim.kmin = nlocal[Z] - nhm1; lim.kmax = nlocal[Z]; + } + + int ic = nlocal[X] + 1; /* halo region */ + for (int jc = lim.jmin; jc <= lim.jmax; jc++) { + for (int kc = lim.kmin; kc <= lim.kmax; kc++) { + int index = cs_index(cs, ic, jc, kc); + double rho = 0.0; + double u[3] = {}; + hydro_rho(hydro, index, &rho); + hydro_u(hydro, index, u); + buf[m][ib++] = rho; + buf[m][ib++] = u[X]; + buf[m][ib++] = u[Y]; + buf[m][ib++] = u[Z]; + } + } + assert(ib == count[m]); + + MPI_Isend(buf[m], count[m], MPI_DOUBLE, ngbr[m], tag, comm, req + m); + } + + /* Process */ + for (int ms = 0; ms < 8; ms++) { + int m = -1; + MPI_Status status = {}; + + MPI_Waitany(8, req, &m, &status); + if (m == MPI_UNDEFINED) continue; + if (status.MPI_SOURCE == MPI_PROC_NULL) continue; + + if (m >= 4) { + /* Send has completed */ + free(buf[m]); + buf[m] = NULL; + } + else { + /* Recv has arrived: unpack to correct destination */ + int ib = 0; + cs_limits_t lim = {}; + + if (m == 0) { /* recv from Y+1,Z */ + lim.jmin = nlocal[Y] + 1; lim.jmax = nlocal[Y] + nhalo; + lim.kmin = 1; lim.kmax = nlocal[Z]; + } + if (m == 1) { /* recv from Y-1,Z */ + lim.jmin = 1 - nhalo; lim.jmin = 0; + lim.kmin = 1; lim.kmax = nlocal[Z]; + } + if (m == 2) { /* recv from Y, Z+1 */ + lim.jmin = 1; lim.jmax = nlocal[Y]; + lim.kmin = nlocal[Z] + 1; lim.kmax = nlocal[Z] + nhalo; + } + if (m == 3) { /* recv from Y, Z-1 */ + lim.jmin = 1; lim.jmax = nlocal[Y]; + lim.kmin = 1 - nhalo; lim.kmax = 0; + } + + int ic = nlocal[X] + 1; /* halo region */ + for (int jc = lim.jmin; jc <= lim.jmax; jc++) { + for (int kc = lim.kmin; kc <= lim.kmax; kc++) { + int index = cs_index(cs, ic, jc, kc); + double rho = 0.0; + double u[3] = {}; + rho = buf[m][ib++]; + u[X] = buf[m][ib++]; + u[Y] = buf[m][ib++]; + u[Z] = buf[m][ib++]; + hydro_rho_set(hydro, index, rho); + hydro_u_set(hydro, index, u); + } + } + assert(ib == count[m]); + + /* Done with this message */ + free(buf[m]); + buf[m] = NULL; + } + } + + /* Ensure we have released all the buffers */ + for (int m = 0; m < 8; m++) { + free(buf[m]); + } + /* Finish */ + } + + return 0; +} + /***************************************************************************** * * lb_bc_outflow_rhou_impose @@ -296,6 +487,10 @@ __host__ int lb_bc_outflow_rhou_impose(lb_bc_outflow_rhou_t * outflow, assert(hydro); assert(lb); + if (pe_mpi_size(outflow->pe) > 1) { + lb_bc_outflow_rhou_halo_update(outflow, hydro); + } + /* For each incoming link (at outflow) set f_p = f^eq_p (rho, u) */ for (int n = 0; n < outflow->nlink; n++) { From 0ede192c8c3a9237ffc7bc0ffb4ad091ed4276a0 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Mon, 13 Dec 2021 14:52:33 +0000 Subject: [PATCH 099/117] Disallow directions other then x in parallel --- src/lb_bc_open_rt.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/lb_bc_open_rt.c b/src/lb_bc_open_rt.c index c11a5ded3..154bc4a3f 100644 --- a/src/lb_bc_open_rt.c +++ b/src/lb_bc_open_rt.c @@ -69,6 +69,13 @@ __host__ int lb_bc_open_rt(pe_t * pe, rt_t * rt, cs_t * cs, lb_t * lb, if (lb_bc_inflow_opts_flow_valid(flow) == 0) { pe_fatal(pe, "Inflow/outflow requires exactly one-non wall direction\n"); } + + /* Temporarily override this while only x-direction halo swap + * implementation in available. */ + + if (pe_mpi_size(pe) > 1 && (flow[Y] != 0 || flow[Z] != 0)) { + pe_fatal(pe, "Open boundary condition direction must be X\n"); + } /* Test periodicity. Must be (0,0,0). */ From 33b22316a303f2cfbb518ff215bf223a07798f5c Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Mon, 13 Dec 2021 15:44:11 +0000 Subject: [PATCH 100/117] Add switch for force diagnostic --- src/ludwig.c | 13 ++++--------- src/stats_colloid_force_split.c | 20 +++++++++++++++----- src/stats_colloid_force_split.h | 14 ++++++++------ 3 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/ludwig.c b/src/ludwig.c index 619c3f046..345303b05 100644 --- a/src/ludwig.c +++ b/src/ludwig.c @@ -715,15 +715,13 @@ void ludwig_run(const char * inputfile) { ludwig->hydro, ludwig->map, ludwig->wall); } } - /* OLIVER: - You need this, only at statistics steps... - stats_colloid_force_split_update(ludwig->collinfo, - ludwig->fe, ludwig->map, - ludwig->q, ludwig->q_grad); - */ TIMER_stop(TIMER_FORCE_CALCULATION); + if (ludwig->q && is_statistics_step()) { + stats_colloid_force_split_update(ludwig->collinfo, ludwig->fe); + } + TIMER_start(TIMER_ORDER_PARAMETER_UPDATE); if (ludwig->ch) { @@ -946,10 +944,7 @@ void ludwig_run(const char * inputfile) { field_memcpy(ludwig->q, tdpMemcpyDeviceToHost); field_grad_memcpy(ludwig->q_grad, tdpMemcpyDeviceToHost); stats_field_info(ludwig->q, ludwig->map); - /* OLIVER: - You need this for diagnostic output stats_colloid_force_split_output(ludwig->collinfo, step); - */ } if (ludwig->psi) { diff --git a/src/stats_colloid_force_split.c b/src/stats_colloid_force_split.c index df01d25ea..45a234f66 100644 --- a/src/stats_colloid_force_split.c +++ b/src/stats_colloid_force_split.c @@ -6,6 +6,11 @@ * a colloid. In the context of liquid crystal free energy. * * + * Edinburgh Soft Matter and Staticial Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * * Contributing authors: * Oliver Henrich (o.henrich@strath.ac.uk) * Kevin Stratford (kevin@epcc.ed.ac.uk) @@ -23,6 +28,8 @@ #include "phi_force_stress.h" #include "stats_colloid_force_split.h" +static int switch_me_on_ = 0; + enum {FSBULK, FSGRAD, FSCHEM}; /* Identify different components */ typedef int (*fe_lc_str_ft)(fe_lc_t * fe, int inde, double s[3][3]); @@ -46,15 +53,16 @@ int stat_diagnostic_write(colloid_diagnostic_t * array, int count, FILE * fp); * *****************************************************************************/ -int stats_colloid_force_split_update(colloids_info_t * cinfo, fe_t * fe, - map_t * map, - field_t * q, field_grad_t * q_grad) { +int stats_colloid_force_split_update(colloids_info_t * cinfo, fe_t * fe) { + pth_t * pth = NULL; pe_t * pe = NULL; cs_t * cs = NULL; - pe = q->pe; - cs = q->cs; + if (switch_me_on_ == 0) return 0; + + pe = cinfo->pe; + cs = cinfo->cs; pth_create(pe, cs, PTH_METHOD_DIVERGENCE, &pth); @@ -96,6 +104,8 @@ int stats_colloid_force_split_output(colloids_info_t * cinfo, int timestep) { assert(cinfo); assert(timestep >= 0); + if (switch_me_on_ == 0) return 0; + pe = cinfo->pe; /* Run halo_sum on diagnostic quantities */ diff --git a/src/stats_colloid_force_split.h b/src/stats_colloid_force_split.h index 906240bcc..17b39677f 100644 --- a/src/stats_colloid_force_split.h +++ b/src/stats_colloid_force_split.h @@ -2,6 +2,13 @@ * * stats_colloid_force_split.h * + * Edinburgh Soft Matter and Statistical Physics Group and + * Edinburgh Parallel Computing Centre + * + * (c) 2021 The University of Edinburgh + * + * Contributing authors: + * Kevin Stratford (kevin@epcc.ed.ac.uk) * *****************************************************************************/ @@ -9,15 +16,10 @@ #define LUDWIG_STATS_COLLOID_FORCE_SPLIT_H #include "colloids.h" -#include "field.h" -#include "field_grad.h" #include "free_energy.h" -#include "map.h" __host__ int stats_colloid_force_split_update(colloids_info_t * cinfo, - fe_t * fe, map_t * map, - field_t * q, - field_grad_t * q_grad); + fe_t * fe); __host__ int stats_colloid_force_split_output(colloids_info_t * cinfo, int timestep); #endif From a95baffa725f42896281290c1cc0d720db8f7d8a Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Mon, 13 Dec 2021 15:44:36 +0000 Subject: [PATCH 101/117] Add note on force split --- CHANGES.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 04b787224..95e20e54a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,6 +4,9 @@ version 0.15.0 - Add ability to rotate BPI and BPII liquid crystal initial conditions Thanks to Oliver H. for this. See Section 3 of web documentation. +- A diagnostic computation and output of the force breakdown on each + colloid has been added. This is currently via a static switch in + stats_colloid_force_split.c version 0.14.0 From 29ff3285532d84b35489b7bbe558d88a472afee0 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Mon, 13 Dec 2021 19:45:18 +0000 Subject: [PATCH 102/117] Remove global cv wv --- src/bbl.c | 75 +++++++------- src/build.c | 215 +++++++++++++++++++++++----------------- src/build.h | 10 +- src/collision.c | 5 +- src/colloids_rt.c | 11 +- src/colloids_rt.h | 3 +- src/lb_model_s.h | 2 +- src/ludwig.c | 12 ++- src/model.c | 140 ++++++++++++++------------ src/model_le.c | 90 ++++++++++------- src/phi_force_colloid.c | 23 +++-- src/phi_force_colloid.h | 3 +- src/wall.c | 84 +++++++++------- tests/unit/test_build.c | 54 ++++++---- tests/unit/test_halo.c | 17 ++-- tests/unit/test_model.c | 70 ++++--------- tests/unit/test_wall.c | 87 ++++++++++------ 17 files changed, 499 insertions(+), 402 deletions(-) diff --git a/src/bbl.c b/src/bbl.c index 44dab3c0d..916be4a69 100644 --- a/src/bbl.c +++ b/src/bbl.c @@ -7,7 +7,7 @@ * Edinburgh Soft Matter and Statistical Physics Group and * Edinburgh Parallel Computing Centre * - * (c) 2010-2020 The University of Edinburgh + * (c) 2010-2021 The University of Edinburgh * * Contributing Authors: * Kevin Stratford (kevin@epcc.ed.ac.uk) @@ -43,7 +43,8 @@ struct bbl_s { static int bbl_pass1(bbl_t * bbl, lb_t * lb, colloids_info_t * cinfo); static int bbl_pass2(bbl_t * bbl, lb_t * lb, colloids_info_t * cinfo); -static int bbl_active_conservation(bbl_t * bbl, colloids_info_t * cinfo); +static int bbl_active_conservation(bbl_t * bbl, lb_t * lb, + colloids_info_t * cinfo); static int bbl_wall_lubrication_account(bbl_t * bbl, wall_t * wall, colloids_info_t * cinfo); @@ -172,7 +173,7 @@ int bounce_back_on_links(bbl_t * bbl, lb_t * lb, wall_t * wall, colloid_sums_halo(cinfo, COLLOID_SUM_DYNAMICS); if (bbl->active) { - bbl_active_conservation(bbl, cinfo); + bbl_active_conservation(bbl, lb, cinfo); colloid_sums_halo(cinfo, COLLOID_SUM_ACTIVE); } @@ -192,8 +193,8 @@ int bounce_back_on_links(bbl_t * bbl, lb_t * lb, wall_t * wall, * *****************************************************************************/ -static int bbl_active_conservation(bbl_t * bbl, colloids_info_t * cinfo) { - +static int bbl_active_conservation(bbl_t * bbl, lb_t * lb, + colloids_info_t * cinfo) { int ia; double dm; double c[3]; @@ -220,10 +221,10 @@ static int bbl_active_conservation(bbl_t * bbl, colloids_info_t * cinfo) { if (p_link->status != LINK_FLUID) continue; - dm = -wv[p_link->p]*pc->sump; + dm = -lb->model.wv[p_link->p]*pc->sump; for (ia = 0; ia < 3; ia++) { - c[ia] = 1.0*cv[p_link->p][ia]; + c[ia] = 1.0*lb->model.cv[p_link->p][ia]; } cross_product(p_link->rb, c, rbxc); @@ -297,6 +298,7 @@ __global__ void bbl_pass0_kernel(kernel_ctxt_t * ktxt, cs_t * cs, lb_t * lb, int kindex; int kiter; + LB_CS2_DOUBLE(cs2); LB_RCS2_DOUBLE(rcs2); assert(ktxt); @@ -343,16 +345,17 @@ __global__ void bbl_pass0_kernel(kernel_ctxt_t * ktxt, cs_t * cs, lb_t * lb, ub[Y] = pc->s.v[Y] + pc->s.w[Z]*rb[X] - pc->s.w[X]*rb[Z]; ub[Z] = pc->s.v[Z] + pc->s.w[X]*rb[Y] - pc->s.w[Y]*rb[X]; - for (p = 1; p < NVEL; p++) { + for (p = 1; p < lbp.nvel; p++) { udotc = lbp.cv[p][X]*ub[X] + lbp.cv[p][Y]*ub[Y] + lbp.cv[p][Z]*ub[Z]; sdotq = 0.0; for (ia = 0; ia < 3; ia++) { for (ib = 0; ib < 3; ib++) { - sdotq += lbp.q[p][ia][ib]*ub[ia]*ub[ib]; + double dab = (ia == ib); + sdotq += (lbp.cv[p][ia]*lbp.cv[p][ib] - cs2*dab)*ub[ia]*ub[ib]; } } - lb->f[ LB_ADDR(lb->nsite, lb->ndist, NVEL, index, LB_RHO, p) ] + lb->f[ LB_ADDR(lb->nsite, lb->ndist, lbp.nvel, index, LB_RHO, p) ] = lbp.wv[p]*(1.0 + rcs2*udotc + 0.5*rcs2*rcs2*sdotq); } } @@ -428,12 +431,12 @@ static int bbl_pass1(bbl_t * bbl, lb_t * lb, colloids_info_t * cinfo) { if (p_link->status == LINK_UNUSED) continue; - i = p_link->i; /* index site i (outside) */ - j = p_link->j; /* index site j (inside) */ - ij = p_link->p; /* link velocity index i->j */ - ji = NVEL - ij; /* link velocity index j->i */ + i = p_link->i; /* index site i (outside) */ + j = p_link->j; /* index site j (inside) */ + ij = p_link->p; /* link velocity index i->j */ + ji = lb->model.nvel - ij; /* link velocity index j->i */ - assert(ij > 0 && ij < NVEL); + assert(ij > 0 && ij < lb->model.nvel); /* For stationary link, the momentum transfer from the * fluid to the colloid is "dm" */ @@ -444,8 +447,8 @@ static int bbl_pass1(bbl_t * bbl, lb_t * lb, colloids_info_t * cinfo) { * Note minus sign. */ lb_f(lb, i, ij, 0, &fdist); - dm = 2.0*fdist - wv[ij]*pc->deltam; - delta = 2.0*rcs2*wv[ij]*rho0; + dm = 2.0*fdist - lb->model.wv[ij]*pc->deltam; + delta = 2.0*rcs2*lb->model.wv[ij]*rho0; /* Squirmer section */ if (pc->s.type == COLLOID_TYPE_ACTIVE) { @@ -471,7 +474,7 @@ static int bbl_pass1(bbl_t * bbl, lb_t * lb, colloids_info_t * cinfo) { dm_a = 0.0; for (ia = 0; ia < 3; ia++) { - dm_a += -delta*plegendre*rmod*tans[ia]*cv[ij][ia]; + dm_a += -delta*plegendre*rmod*tans[ia]*lb->model.cv[ij][ia]; } lb_f(lb, i, ij, 0, &fdist); @@ -496,7 +499,7 @@ static int bbl_pass1(bbl_t * bbl, lb_t * lb, colloids_info_t * cinfo) { } for (ia = 0; ia < 3; ia++) { - c[ia] = 1.0*cv[ij][ia]; + c[ia] = 1.0*lb->model.cv[ij][ia]; } cross_product(p_link->rb, c, rbxc); @@ -633,15 +636,15 @@ static int bbl_pass2(bbl_t * bbl, lb_t * lb, colloids_info_t * cinfo) { for ( ; p_link; p_link = p_link->next) { - i = p_link->i; /* index site i (outside) */ - j = p_link->j; /* index site j (inside) */ - ij = p_link->p; /* link velocity index i->j */ - ji = NVEL - ij; /* link velocity index j->i */ + i = p_link->i; /* index site i (outside) */ + j = p_link->j; /* index site j (inside) */ + ij = p_link->p; /* link velocity index i->j */ + ji = lb->model.nvel - ij; /* link velocity index j->i */ if (p_link->status == LINK_FLUID) { lb_f(lb, i, ij, 0, &fdist); - dm = 2.0*fdist - wv[ij]*pc->deltam; + dm = 2.0*fdist - lb->model.wv[ij]*pc->deltam; /* Compute the self-consistent boundary velocity, * and add the correction term for changes in shape. */ @@ -650,18 +653,18 @@ static int bbl_pass2(bbl_t * bbl, lb_t * lb, colloids_info_t * cinfo) { vdotc = 0.0; for (ia = 0; ia < 3; ia++) { - vdotc += (pc->s.v[ia] + wxrb[ia])*cv[ij][ia]; + vdotc += (pc->s.v[ia] + wxrb[ia])*lb->model.cv[ij][ia]; } - vdotc = 2.0*rcs2*wv[ij]*vdotc; - df = rho0*vdotc + wv[ij]*pc->deltam; + vdotc = 2.0*rcs2*lb->model.wv[ij]*vdotc; + df = rho0*vdotc + lb->model.wv[ij]*pc->deltam; /* Contribution to mass conservation from squirmer */ - df += wv[ij]*pc->sump; + df += lb->model.wv[ij]*pc->sump; /* Correction owing to missing links "squeeze term" */ - df -= wv[ij]*dms; + df -= lb->model.wv[ij]*dms; /* The outside site actually undergoes BBL. */ @@ -676,7 +679,7 @@ static int bbl_pass2(bbl_t * bbl, lb_t * lb, colloids_info_t * cinfo) { lb_0th_moment(lb, i, LB_PHI, &dg); dg *= vdotc; pc->s.deltaphi += dg; - dg -= wv[ij]*dgtm1; + dg -= lb->model.wv[ij]*dgtm1; lb_f(lb, i, ij, LB_PHI, &fdist); fdist = fdist - dg; @@ -685,9 +688,9 @@ static int bbl_pass2(bbl_t * bbl, lb_t * lb, colloids_info_t * cinfo) { /* The stress is r_b f_b */ for (ia = 0; ia < 3; ia++) { - bbl->stress[ia][X] += p_link->rb[X]*(dm - df)*cv[ij][ia]; - bbl->stress[ia][Y] += p_link->rb[Y]*(dm - df)*cv[ij][ia]; - bbl->stress[ia][Z] += p_link->rb[Z]*(dm - df)*cv[ij][ia]; + bbl->stress[ia][X] += p_link->rb[X]*(dm - df)*lb->model.cv[ij][ia]; + bbl->stress[ia][Y] += p_link->rb[Y]*(dm - df)*lb->model.cv[ij][ia]; + bbl->stress[ia][Z] += p_link->rb[Z]*(dm - df)*lb->model.cv[ij][ia]; } } else if (p_link->status == LINK_COLLOID) { @@ -700,9 +703,9 @@ static int bbl_pass2(bbl_t * bbl, lb_t * lb, colloids_info_t * cinfo) { dm += fdist; for (ia = 0; ia < 3; ia++) { - bbl->stress[ia][X] += p_link->rb[X]*dm*cv[ij][ia]; - bbl->stress[ia][Y] += p_link->rb[Y]*dm*cv[ij][ia]; - bbl->stress[ia][Z] += p_link->rb[Z]*dm*cv[ij][ia]; + bbl->stress[ia][X] += p_link->rb[X]*dm*lb->model.cv[ij][ia]; + bbl->stress[ia][Y] += p_link->rb[Y]*dm*lb->model.cv[ij][ia]; + bbl->stress[ia][Z] += p_link->rb[Z]*dm*lb->model.cv[ij][ia]; } } /* Next link */ diff --git a/src/build.c b/src/build.c index 4df5c6a8d..9ca5410cc 100644 --- a/src/build.c +++ b/src/build.c @@ -9,7 +9,7 @@ * Edinburgh Soft Matter and Statisitical Physics Group and * Edinburgh Parallel Computing Centre * - * (c) 2006-2020 The University of Edinburgh + * (c) 2006-2021 The University of Edinburgh * * Contributing authors: * Kevin Stratford (kevin@epcc.ed.ac.uk) @@ -47,16 +47,21 @@ static int build_remove_order_parameter(lb_t * lb, field_t * f, int index, static int build_replace_order_parameter(fe_t * fe, lb_t * lb, colloids_info_t * cinfo, field_t * f, int index, colloid_t * pc, map_t * map); -static int build_reset_links(cs_t * cs, colloid_t * pc, map_t * map); +static int build_reset_links(cs_t * cs, colloid_t * pc, map_t * map, + const lb_model_t * model); static int build_reconstruct_links(cs_t * cs, colloids_info_t * cinfo, - colloid_t * pc, map_t * map); -static void build_link_mean(colloid_t * pc, int p, const double rb[3]); + colloid_t * pc, map_t * map, + const lb_model_t * model); +static void build_link_mean(colloid_t * pc, double wv, const int8_t cv[3], + const double rb[3]); static int build_colloid_wall_links(cs_t * cs, colloids_info_t * cinfo, - colloid_t * pc, - map_t * map); + colloid_t * pc, map_t * map, + const lb_model_t * model); -int build_conservation_phi(colloids_info_t * cinfo, field_t * phi); -int build_conservation_psi(colloids_info_t * cinfo, psi_t * psi); +int build_conservation_phi(colloids_info_t * cinfo, field_t * phi, + const lb_model_t * model); +int build_conservation_psi(colloids_info_t * cinfo, psi_t * psi, + const lb_model_t * model); /***************************************************************************** * @@ -233,7 +238,7 @@ int build_update_map(cs_t * cs, colloids_info_t * cinfo, map_t * map) { *****************************************************************************/ int build_update_links(cs_t * cs, colloids_info_t * cinfo, wall_t * wall, - map_t * map) { + map_t * map, const lb_model_t * model) { int ia; int ic, jc, kc; @@ -244,6 +249,7 @@ int build_update_links(cs_t * cs, colloids_info_t * cinfo, wall_t * wall, assert(cs); assert(cinfo); assert(map); + assert(model); colloids_info_ncell(cinfo, ncell); colloids_info_nhalo(cinfo, &nhalo); @@ -266,15 +272,15 @@ int build_update_links(cs_t * cs, colloids_info_t * cinfo, wall_t * wall, if (pc->s.rebuild) { /* The shape has changed, so need to reconstruct */ - build_reconstruct_links(cs, cinfo, pc, map); - if (wall) build_colloid_wall_links(cs, cinfo, pc, map); + build_reconstruct_links(cs, cinfo, pc, map, model); + if (wall) build_colloid_wall_links(cs, cinfo, pc, map, model); } else { /* Shape unchanged, so just reset existing links */ - build_reset_links(cs, pc, map); + build_reset_links(cs, pc, map, model); } - build_count_faces_local(pc, &pc->s.sa, &pc->s.saf); + build_count_faces_local(pc, model, &pc->s.sa, &pc->s.saf); /* Next colloid */ @@ -307,7 +313,7 @@ int build_update_links(cs_t * cs, colloids_info_t * cinfo, wall_t * wall, int build_reconstruct_links(cs_t * cs, colloids_info_t * cinfo, colloid_t * p_colloid, - map_t * map) { + map_t * map, const lb_model_t * model) { colloid_link_t * p_link; colloid_link_t * p_last; @@ -327,6 +333,7 @@ int build_reconstruct_links(cs_t * cs, colloids_info_t * cinfo, colloid_t * pc = NULL; assert(cs); + assert(model); cs_nlocal(cs, ntotal); cs_nlocal_offset(cs, offset); @@ -381,13 +388,13 @@ int build_reconstruct_links(cs_t * cs, colloids_info_t * cinfo, /* Index 1 is outside, so cycle through the lattice vectors * to determine if the end is inside, and so requires a link */ - for (p = 1; p < NVEL; p++) { + for (p = 1; p < model->nvel; p++) { /* Find the index of the inside site */ - ii = ic + cv[p][X]; - jj = jc + cv[p][Y]; - kk = kc + cv[p][Z]; + ii = ic + model->cv[p][X]; + jj = jc + model->cv[p][Y]; + kk = kc + model->cv[p][Z]; index0 = cs_index(cs, ii, jj, kk); colloids_info_map(cinfo, index0, &pc); @@ -398,9 +405,9 @@ int build_reconstruct_links(cs_t * cs, colloids_info_t * cinfo, if (p_link) { /* Use existing link (lambda always 0.5 at moment) */ - p_link->rb[X] = rsep[X] + lambda*cv[p][X]; - p_link->rb[Y] = rsep[Y] + lambda*cv[p][Y]; - p_link->rb[Z] = rsep[Z] + lambda*cv[p][Z]; + p_link->rb[X] = rsep[X] + lambda*model->cv[p][X]; + p_link->rb[Y] = rsep[Y] + lambda*model->cv[p][Y]; + p_link->rb[Z] = rsep[Z] + lambda*model->cv[p][Z]; p_link->i = index1; p_link->j = index0; @@ -408,7 +415,8 @@ int build_reconstruct_links(cs_t * cs, colloids_info_t * cinfo, if (status1 == MAP_FLUID) { p_link->status = LINK_FLUID; - build_link_mean(p_colloid, p, p_link->rb); + build_link_mean(p_colloid, model->wv[p], model->cv[p], + p_link->rb); } else { p_link->status = LINK_COLLOID; @@ -424,9 +432,9 @@ int build_reconstruct_links(cs_t * cs, colloids_info_t * cinfo, p_link = colloid_link_allocate(); - p_link->rb[X] = rsep[X] + lambda*cv[p][X]; - p_link->rb[Y] = rsep[Y] + lambda*cv[p][Y]; - p_link->rb[Z] = rsep[Z] + lambda*cv[p][Z]; + p_link->rb[X] = rsep[X] + lambda*model->cv[p][X]; + p_link->rb[Y] = rsep[Y] + lambda*model->cv[p][Y]; + p_link->rb[Z] = rsep[Z] + lambda*model->cv[p][Z]; p_link->i = index1; p_link->j = index0; @@ -434,7 +442,8 @@ int build_reconstruct_links(cs_t * cs, colloids_info_t * cinfo, if (status1 == MAP_FLUID) { p_link->status = LINK_FLUID; - build_link_mean(p_colloid, p, p_link->rb); + build_link_mean(p_colloid, model->wv[p], model->cv[p], + p_link->rb); } else { p_link->status = LINK_COLLOID; @@ -482,7 +491,8 @@ int build_reconstruct_links(cs_t * cs, colloids_info_t * cinfo, * ****************************************************************************/ -int build_reset_links(cs_t * cs, colloid_t * p_colloid, map_t * map) { +int build_reset_links(cs_t * cs, colloid_t * p_colloid, map_t * map, + const lb_model_t * model) { int ia; @@ -498,6 +508,7 @@ int build_reset_links(cs_t * cs, colloid_t * p_colloid, map_t * map) { assert(p_colloid); assert(map); + assert(model); cs_nlocal_offset(cs, offset); @@ -521,15 +532,16 @@ int build_reset_links(cs_t * cs, colloid_t * p_colloid, map_t * map) { } cs_minimum_distance(cs, r0, rsite, rsep); - p_link->rb[X] = rsep[X] + lambda*cv[p_link->p][X]; - p_link->rb[Y] = rsep[Y] + lambda*cv[p_link->p][Y]; - p_link->rb[Z] = rsep[Z] + lambda*cv[p_link->p][Z]; + p_link->rb[X] = rsep[X] + lambda*model->cv[p_link->p][X]; + p_link->rb[Y] = rsep[Y] + lambda*model->cv[p_link->p][Y]; + p_link->rb[Z] = rsep[Z] + lambda*model->cv[p_link->p][Z]; map_status(map, p_link->i, &status); if (status == MAP_FLUID) { + int p = p_link->p; p_link->status = LINK_FLUID; - build_link_mean(p_colloid, p_link->p, p_link->rb); + build_link_mean(p_colloid, model->wv[p], model->cv[p], p_link->rb); } else { if (status == MAP_COLLOID) p_link->status = LINK_COLLOID; @@ -861,14 +873,15 @@ static int build_replace_fluid(lb_t * lb, colloids_info_t * cinfo, int index, /* Check the surrounding sites that were linked to inode, * and accumulate a (weighted) average distribution. */ - for (p = 0; p < NVEL; p++) { + for (p = 0; p < lb->model.nvel; p++) { newf[p] = 0.0; } - for (p = 1; p < NVEL; p++) { + for (p = 1; p < lb->model.nvel; p++) { - indexn = cs_index(lb->cs, ib[X] + cv[p][X], ib[Y] + cv[p][Y], - ib[Z] + cv[p][Z]); + indexn = cs_index(lb->cs, ib[X] + lb->model.cv[p][X], + ib[Y] + lb->model.cv[p][Y], + ib[Z] + lb->model.cv[p][Z]); /* Site must have been fluid before position update */ @@ -877,11 +890,11 @@ static int build_replace_fluid(lb_t * lb, colloids_info_t * cinfo, int index, map_status(map, indexn, &status); if (status == MAP_BOUNDARY) continue; - for (pdash = 0; pdash < NVEL; pdash++) { + for (pdash = 0; pdash < lb->model.nvel; pdash++) { lb_f(lb, indexn, pdash, 0, rtmp); - newf[pdash] += wv[p]*rtmp[0]; + newf[pdash] += lb->model.wv[p]*rtmp[0]; } - weight += wv[p]; + weight += lb->model.wv[p]; nweight += 1; } @@ -895,7 +908,7 @@ static int build_replace_fluid(lb_t * lb, colloids_info_t * cinfo, int index, weight = 1.0/weight; - for (p = 0; p < NVEL; p++) { + for (p = 0; p < lb->model.nvel; p++) { newf[p] *= weight; lb_f_set(lb, index, p, 0, newf[p]); @@ -906,7 +919,7 @@ static int build_replace_fluid(lb_t * lb, colloids_info_t * cinfo, int index, ... correction to colloid momentum */ for (ia = 0; ia < 3; ia++) { - g[ia] -= newf[p]*cv[p][ia]; + g[ia] -= newf[p]*lb->model.cv[p][ia]; } } @@ -956,10 +969,6 @@ int build_replace_fluid_local(colloids_info_t * cinfo, colloid_t * pc, double gnew[3] = {0.0, 0.0, 0.0}; double tnew[3] = {0.0, 0.0, 0.0}; - LB_CS2_DOUBLE(cs2); - LB_RCS2_DOUBLE(rcs2); - KRONECKER_DELTA_CHAR(d_); - assert(cinfo); assert(pc); assert(lb); @@ -969,22 +978,28 @@ int build_replace_fluid_local(colloids_info_t * cinfo, colloid_t * pc, rho0 = lb->param->rho0; /* fluid density */ colloid_rb_ub(cinfo, pc, index, rb, ub); - for (p = 0; p < NVEL; p++) { - udotc = cv[p][X]*ub[X] + cv[p][Y]*ub[Y] + cv[p][Z]*ub[Z]; + for (p = 0; p < lb->model.nvel; p++) { + double cs2 = lb->model.cs2; + double rcs2 = 1.0/cs2; + udotc = lb->model.cv[p][X]*ub[X] + + lb->model.cv[p][Y]*ub[Y] + + lb->model.cv[p][Z]*ub[Z]; sdotq = 0.0; for (ia = 0; ia < 3; ia++) { for (ib = 0; ib < 3; ib++) { - sdotq += (cv[p][ia]*cv[p][ib] - cs2*d_[ia][ib])*ub[ia]*ub[ib]; + double dab = (ia == ib); + double q = lb->model.cv[p][ia]*lb->model.cv[p][ib] - cs2*dab; + sdotq += q*ub[ia]*ub[ib]; } } - f = wv[p]*(rho0 + rcs2*udotc + 0.5*rcs2*rcs2*sdotq); + f = lb->model.wv[p]*(rho0 + rcs2*udotc + 0.5*rcs2*rcs2*sdotq); lb_f_set(lb, index, p, LB_RHO, f); /* Subtract momentum from colloid (contribution to) */ - gnew[X] -= f*cv[p][X]; - gnew[Y] -= f*cv[p][Y]; - gnew[Z] -= f*cv[p][Z]; + gnew[X] -= f*lb->model.cv[p][X]; + gnew[Y] -= f*lb->model.cv[p][Y]; + gnew[Z] -= f*lb->model.cv[p][Z]; } cross_product(rb, gnew, tnew); @@ -1040,7 +1055,7 @@ static int build_replace_order_parameter(fe_t * fe, lb_t * lb, /* Check the surrounding sites that were linked to inode, * and accumulate a (weighted) average distribution. */ - for (p = 0; p < NVEL; p++) { + for (p = 0; p < lb->model.nvel; p++) { newg[p] = 0.0; } @@ -1048,10 +1063,11 @@ static int build_replace_order_parameter(fe_t * fe, lb_t * lb, /* Reset the distribution (distribution index 1) */ - for (p = 1; p < NVEL; p++) { + for (p = 1; p < lb->model.nvel; p++) { - indexn = cs_index(lb->cs, ri[X] + cv[p][X], ri[Y] + cv[p][Y], - ri[Z] + cv[p][Z]); + indexn = cs_index(lb->cs, ri[X] + lb->model.cv[p][X], + ri[Y] + lb->model.cv[p][Y], + ri[Z] + lb->model.cv[p][Z]); /* Site must have been fluid before position update */ @@ -1061,11 +1077,11 @@ static int build_replace_order_parameter(fe_t * fe, lb_t * lb, map_status(map, indexn, &status); if (status == MAP_BOUNDARY) continue; - for (pdash = 0; pdash < NVEL; pdash++) { + for (pdash = 0; pdash < lb->model.nvel; pdash++) { lb_f(lb, indexn, pdash, LB_PHI, &g); - newg[pdash] += wv[p]*g; + newg[pdash] += lb->model.wv[p]*g; } - weight += wv[p]; + weight += lb->model.wv[p]; } /* Set new fluid distributions */ @@ -1083,7 +1099,7 @@ static int build_replace_order_parameter(fe_t * fe, lb_t * lb, weight = 1.0/weight; phi[0] = 0.0; - for (p = 0; p < NVEL; p++) { + for (p = 0; p < lb->model.nvel; p++) { newg[p] *= weight; lb_f_set(lb, index, p, LB_PHI, newg[p]); @@ -1100,10 +1116,11 @@ static int build_replace_order_parameter(fe_t * fe, lb_t * lb, phi[n] = 0.0; } - for (p = 1; p < NVEL; p++) { + for (p = 1; p < lb->model.nvel; p++) { - indexn = cs_index(lb->cs, ri[X] + cv[p][X], ri[Y] + cv[p][Y], - ri[Z] + cv[p][Z]); + indexn = cs_index(lb->cs, ri[X] + lb->model.cv[p][X], + ri[Y] + lb->model.cv[p][Y], + ri[Z] + lb->model.cv[p][Z]); /* Site must have been fluid before position update */ @@ -1114,9 +1131,9 @@ static int build_replace_order_parameter(fe_t * fe, lb_t * lb, field_scalar_array(f, indexn, qs); for (n = 0; n < nf; n++) { - phi[n] += wv[p]*qs[n]; + phi[n] += lb->model.wv[p]*qs[n]; } - weight += wv[p]; + weight += lb->model.wv[p]; nweight += 1; } @@ -1219,23 +1236,24 @@ int build_replace_q_local(fe_t * fe, colloids_info_t * info, colloid_t * pc, * *****************************************************************************/ -static void build_link_mean(colloid_t * p_colloid, int p, const double rb[3]) { +static void build_link_mean(colloid_t * pc, double wv, const int8_t cv[3], + const double rb[3]) { int ia; double c[3]; double rbxc[3]; for (ia = 0; ia < 3; ia++) { - c[ia] = 1.0*cv[p][ia]; + c[ia] = 1.0*cv[ia]; } cross_product(rb, c, rbxc); - p_colloid->sumw += wv[p]; + pc->sumw += wv; for (ia = 0; ia < 3; ia++) { - p_colloid->cbar[ia] += wv[p]*c[ia]; - p_colloid->rxcbar[ia] += wv[p]*rbxc[ia]; + pc->cbar[ia] += wv*c[ia]; + pc->rxcbar[ia] += wv*rbxc[ia]; } return; @@ -1260,8 +1278,8 @@ static void build_link_mean(colloid_t * p_colloid, int p, const double rb[3]) { *****************************************************************************/ int build_colloid_wall_links(cs_t * cs, colloids_info_t * cinfo, - colloid_t * p_colloid, - map_t * map) { + colloid_t * p_colloid, map_t * map, + const lb_model_t * model) { int i_min, i_max, j_min, j_max, k_min, k_max; int i, ic, ii, j, jc, jj, k, kc, kk; @@ -1328,13 +1346,13 @@ int build_colloid_wall_links(cs_t * cs, colloids_info_t * cinfo, rsite1[Z] = 1.0*k; cs_minimum_distance(cs, r0, rsite1, rsep); - for (p = 1; p < NVEL; p++) { + for (p = 1; p < model->nvel; p++) { /* Find the index of the outside site */ - ii = ic + cv[p][X]; - jj = jc + cv[p][Y]; - kk = kc + cv[p][Z]; + ii = ic + model->cv[p][X]; + jj = jc + model->cv[p][Y]; + kk = kc + model->cv[p][Z]; index0 = cs_index(cs, ii, jj, kk); map_status(map, index0, &status); @@ -1345,13 +1363,13 @@ int build_colloid_wall_links(cs_t * cs, colloids_info_t * cinfo, if (p_link) { /* Use existing link (lambda always 0.5 at moment) */ - p_link->rb[X] = rsep[X] + lambda*cv[p][0]; - p_link->rb[Y] = rsep[Y] + lambda*cv[p][1]; - p_link->rb[Z] = rsep[Z] + lambda*cv[p][2]; + p_link->rb[X] = rsep[X] + lambda*model->cv[p][0]; + p_link->rb[Y] = rsep[Y] + lambda*model->cv[p][1]; + p_link->rb[Z] = rsep[Z] + lambda*model->cv[p][2]; p_link->i = index0; p_link->j = index1; - p_link->p = NVEL - p; + p_link->p = model->nvel - p; p_link->status = LINK_BOUNDARY; /* Next link */ @@ -1363,13 +1381,13 @@ int build_colloid_wall_links(cs_t * cs, colloids_info_t * cinfo, p_link = colloid_link_allocate(); - p_link->rb[X] = rsep[X] + lambda*cv[p][0]; - p_link->rb[Y] = rsep[Y] + lambda*cv[p][1]; - p_link->rb[Z] = rsep[Z] + lambda*cv[p][2]; + p_link->rb[X] = rsep[X] + lambda*model->cv[p][X]; + p_link->rb[Y] = rsep[Y] + lambda*model->cv[p][Y]; + p_link->rb[Z] = rsep[Z] + lambda*model->cv[p][Z]; p_link->i = index0; p_link->j = index1; - p_link->p = NVEL - p; + p_link->p = model->nvel - p; p_link->status = LINK_BOUNDARY; /* There must be at least one link in the list. */ @@ -1428,7 +1446,8 @@ int build_count_links_local(colloid_t * colloid, int * nlinks) { * *****************************************************************************/ -int build_count_faces_local(colloid_t * colloid, double * sa, double * saf) { +int build_count_faces_local(colloid_t * colloid, const lb_model_t * model, + double * sa, double * saf) { int p; colloid_link_t * pl = NULL; @@ -1436,6 +1455,7 @@ int build_count_faces_local(colloid_t * colloid, double * sa, double * saf) { assert(colloid); assert(sa); assert(saf); + assert(model); *sa = 0.0; *saf = 0.0; @@ -1443,7 +1463,9 @@ int build_count_faces_local(colloid_t * colloid, double * sa, double * saf) { for (pl = colloid->lnk; pl != NULL; pl = pl->next) { if (pl->status == LINK_UNUSED) continue; p = pl->p; - p = cv[p][X]*cv[p][X] + cv[p][Y]*cv[p][Y] + cv[p][Z]*cv[p][Z]; + p = model->cv[p][X]*model->cv[p][X] + + model->cv[p][Y]*model->cv[p][Y] + + model->cv[p][Z]*model->cv[p][Z]; if (p == 1) { *sa += 1.0; if (pl->status == LINK_FLUID) *saf += 1.0; @@ -1465,12 +1487,13 @@ int build_count_faces_local(colloid_t * colloid, double * sa, double * saf) { * *****************************************************************************/ -int build_conservation(colloids_info_t * cinfo, field_t * phi, psi_t * psi) { +int build_conservation(colloids_info_t * cinfo, field_t * phi, psi_t * psi, + const lb_model_t * model) { assert(cinfo); - if (phi) build_conservation_phi(cinfo, phi); - if (psi) build_conservation_psi(cinfo, psi); + if (phi) build_conservation_phi(cinfo, phi, model); + if (psi) build_conservation_psi(cinfo, psi, model); return 0; } @@ -1487,7 +1510,8 @@ int build_conservation(colloids_info_t * cinfo, field_t * phi, psi_t * psi) { * *****************************************************************************/ -int build_conservation_psi(colloids_info_t * cinfo, psi_t * psi) { +int build_conservation_psi(colloids_info_t * cinfo, psi_t * psi, + const lb_model_t * model) { int p; @@ -1518,7 +1542,7 @@ int build_conservation_psi(colloids_info_t * cinfo, psi_t * psi) { /* Locally, the total we expect to put back is: */ - build_count_faces_local(colloid, &sa_local, &saf_local); + build_count_faces_local(colloid, model, &sa_local, &saf_local); assert(colloid->s.saf > 0.0); colloid->dq[0] *= saf_local/colloid->s.saf; @@ -1529,7 +1553,9 @@ int build_conservation_psi(colloids_info_t * cinfo, psi_t * psi) { if (pl->status != LINK_FLUID) continue; p = pl->p; - p = cv[p][X]*cv[p][X] + cv[p][Y]*cv[p][Y] + cv[p][Z]*cv[p][Z]; + p = model->cv[p][X]*model->cv[p][X] + + model->cv[p][Y]*model->cv[p][Y] + + model->cv[p][Z]*model->cv[p][Z]; if (p == 1) { /* For charge, do not drop densities below zero. */ @@ -1578,7 +1604,8 @@ int build_conservation_psi(colloids_info_t * cinfo, psi_t * psi) { * *****************************************************************************/ -int build_conservation_phi(colloids_info_t * cinfo, field_t * phi) { +int build_conservation_phi(colloids_info_t * cinfo, field_t * phi, + const lb_model_t * model) { int p; @@ -1606,7 +1633,9 @@ int build_conservation_phi(colloids_info_t * cinfo, field_t * phi) { if (pl->status != LINK_FLUID) continue; p = pl->p; - p = cv[p][X]*cv[p][X] + cv[p][Y]*cv[p][Y] + cv[p][Z]*cv[p][Z]; + p = model->cv[p][X]*model->cv[p][X] + + model->cv[p][Y]*model->cv[p][Y] + + model->cv[p][Z]*model->cv[p][Z]; if (p == 1) { /* Replace */ diff --git a/src/build.h b/src/build.h index 47ecc6f60..514886864 100644 --- a/src/build.h +++ b/src/build.h @@ -6,7 +6,7 @@ * Edinburgh Parallel Computing Centre * * Kevin Stratford (kevin@epcc.ed.ac.uk) - * (c) 2012-2017 The University of Edinburgh + * (c) 2012-2021 The University of Edinburgh * *****************************************************************************/ @@ -25,12 +25,14 @@ int build_remove_replace(fe_t * fe, colloids_info_t * cinfo, lb_t * lb, field_t field_t * p, field_t * q, psi_t * psi, map_t * map); int build_update_links(cs_t * cs, colloids_info_t * cinfo, wall_t * wall, - map_t * map); + map_t * map, const lb_model_t * model); int build_update_map(cs_t * cs, colloids_info_t * cinfo, map_t * map); -int build_conservation(colloids_info_t * info, field_t * phi, psi_t * psi); +int build_conservation(colloids_info_t * info, field_t * phi, psi_t * psi, + const lb_model_t * model); int build_count_links_local(colloid_t * colloid, int * nlinks); -int build_count_faces_local(colloid_t * colloid, double * sa, double * saf); +int build_count_faces_local(colloid_t * colloid, const lb_model_t * model, + double * sa, double * saf); #endif diff --git a/src/collision.c b/src/collision.c index f6b560501..f19eb0c35 100644 --- a/src/collision.c +++ b/src/collision.c @@ -999,6 +999,7 @@ __device__ void lb_collision_mrt2_site(lb_t * lb, hydro_t * hydro, #else for (p = 0; p < NVEL; p++) { + LB_CS2_DOUBLE(cs2); int dp0 = (p == 0); @@ -1010,7 +1011,9 @@ __device__ void lb_collision_mrt2_site(lb_t * lb, hydro_t * hydro, for (ia = 0; ia < 3; ia++) { for_simd_v(iv, NSIMDVL) jdotc[iv] += jphi[ia][iv]*_lbp.cv[p][ia]; for (ib = 0; ib < 3; ib++) { - for_simd_v(iv, NSIMDVL) sphidotq[iv] += sphi[ia][ib][iv]*_lbp.q[p][ia][ib]; + for_simd_v(iv, NSIMDVL) { + sphidotq[iv] += sphi[ia][ib][iv]*(_lbp.cv[p][ia]*_lbp.cv[p][ib] - cs2*d[ia][ib]); + } } } diff --git a/src/colloids_rt.c b/src/colloids_rt.c index 290bf095f..19d93b327 100644 --- a/src/colloids_rt.c +++ b/src/colloids_rt.c @@ -51,7 +51,7 @@ int angle_cosine_init(pe_t * pe, cs_t * cs, rt_t * rt, interact_t * interact); int pair_ss_cut_ij_init(pe_t * pe, cs_t * cs, rt_t * rt, interact_t * intrct); int colloids_rt_dynamics(cs_t * cs, colloids_info_t * cinfo, wall_t * wall, - map_t * map); + map_t * map, const lb_model_t * model); int colloids_rt_gravity(pe_t * pe, rt_t * rt, colloids_info_t * cinfo); int colloids_rt_init_few(pe_t * pe, rt_t * rt, colloids_info_t * cinfo, int nc); int colloids_rt_init_from_file(pe_t * pe, rt_t * rt, colloids_info_t * cinfo, @@ -80,7 +80,8 @@ int colloids_rt_cell_list_checks(pe_t * pe, cs_t * cs, colloids_info_t ** pinfo, int colloids_init_rt(pe_t * pe, rt_t * rt, cs_t * cs, colloids_info_t ** pinfo, colloid_io_t ** pcio, - interact_t ** interact, wall_t * wall, map_t * map) { + interact_t ** interact, wall_t * wall, map_t * map, + const lb_model_t * model) { int nc; int init_one = 0; int init_two = 0; @@ -159,7 +160,7 @@ int colloids_init_rt(pe_t * pe, rt_t * rt, cs_t * cs, colloids_info_t ** pinfo, colloids_info_map_init(*pinfo); colloids_halo_state(*pinfo); - colloids_rt_dynamics(cs, *pinfo, wall, map); + colloids_rt_dynamics(cs, *pinfo, wall, map, model); colloids_rt_gravity(pe, rt, *pinfo); /* Set the update frequency and report (non-default values) */ @@ -189,7 +190,7 @@ int colloids_init_rt(pe_t * pe, rt_t * rt, cs_t * cs, colloids_info_t ** pinfo, *****************************************************************************/ int colloids_rt_dynamics(cs_t * cs, colloids_info_t * cinfo, wall_t * wall, - map_t * map) { + map_t * map, const lb_model_t * model) { int nsubgrid_local = 0; int nsubgrid = 0; @@ -210,7 +211,7 @@ int colloids_rt_dynamics(cs_t * cs, colloids_info_t * cinfo, wall_t * wall, /* Assume there are always fully-resolved particles */ build_update_map(cs, cinfo, map); - build_update_links(cs, cinfo, wall, map); + build_update_links(cs, cinfo, wall, map, model); return 0; diff --git a/src/colloids_rt.h b/src/colloids_rt.h index 4d71eb614..253196f31 100644 --- a/src/colloids_rt.h +++ b/src/colloids_rt.h @@ -27,7 +27,8 @@ int colloids_init_rt(pe_t * pe, rt_t * rt, cs_t * cs, colloids_info_t ** pinfo, colloid_io_t ** cio, - interact_t ** interact, wall_t * wall, map_t * map); + interact_t ** interact, wall_t * wall, map_t * map, + const lb_model_t * model); int colloids_init_ewald_rt(pe_t * pe, rt_t * rt, cs_t * cs, colloids_info_t * cinfo, ewald_t ** pewald); int colloids_init_halo_range_check(pe_t * pe, cs_t * cs, diff --git a/src/lb_model_s.h b/src/lb_model_s.h index a2da1124a..0b07785de 100644 --- a/src/lb_model_s.h +++ b/src/lb_model_s.h @@ -29,6 +29,7 @@ struct lb_collide_param_s { int8_t cv[NVEL][3]; int nsite; int ndist; + int nvel; double rho0; double eta_shear; double var_shear; @@ -37,7 +38,6 @@ struct lb_collide_param_s { double rna[NVEL]; /* reciprocal of normaliser[p] */ double rtau[NVEL]; double wv[NVEL]; - double q[NVEL][3][3]; double ma[NVEL][NVEL]; double mi[NVEL][NVEL]; }; diff --git a/src/ludwig.c b/src/ludwig.c index 70a5e4cc0..675820877 100644 --- a/src/ludwig.c +++ b/src/ludwig.c @@ -307,7 +307,8 @@ static int ludwig_rt(ludwig_t * ludwig) { wall_rt_init(pe, cs, rt, ludwig->lb, ludwig->map, &ludwig->wall); colloids_init_rt(pe, rt, cs, &ludwig->collinfo, &ludwig->cio, - &ludwig->interact, ludwig->wall, ludwig->map); + &ludwig->interact, ludwig->wall, ludwig->map, + &ludwig->lb->model); colloids_init_ewald_rt(pe, rt, cs, ludwig->collinfo, &ludwig->ewald); bbl_create(pe, ludwig->cs, ludwig->lb, &ludwig->bbl); @@ -747,7 +748,8 @@ void ludwig_run(const char * inputfile) { } else { pth_force_colloid(ludwig->pth, ludwig->fe, ludwig->collinfo, - ludwig->hydro, ludwig->map, ludwig->wall); + ludwig->hydro, ludwig->map, ludwig->wall, + &ludwig->lb->model); } } @@ -2050,14 +2052,16 @@ int ludwig_colloids_update(ludwig_t * ludwig) { build_update_map(ludwig->cs, ludwig->collinfo, ludwig->map); build_remove_replace(ludwig->fe, ludwig->collinfo, ludwig->lb, ludwig->phi, ludwig->p, ludwig->q, ludwig->psi, ludwig->map); - build_update_links(ludwig->cs, ludwig->collinfo, ludwig->wall, ludwig->map); + build_update_links(ludwig->cs, ludwig->collinfo, ludwig->wall, ludwig->map, + &ludwig->lb->model); TIMER_stop(TIMER_REBUILD); TIMER_start(TIMER_FREE1); if (iconserve) { colloid_sums_halo(ludwig->collinfo, COLLOID_SUM_CONSERVATION); - build_conservation(ludwig->collinfo, ludwig->phi, ludwig->psi); + build_conservation(ludwig->collinfo, ludwig->phi, ludwig->psi, + &ludwig->lb->model); } TIMER_stop(TIMER_FREE1); diff --git a/src/model.c b/src/model.c index e5c61cf4a..30816c957 100644 --- a/src/model.c +++ b/src/model.c @@ -180,7 +180,7 @@ __host__ int lb_memcpy(lb_t * lb, tdpMemcpyKind flag) { } else { - size_t nsz = (size_t) NVEL*lb->nsite*lb->ndist*sizeof(double); + size_t nsz = (size_t) lb->model.nvel*lb->nsite*lb->ndist*sizeof(double); assert(lb->target); @@ -235,7 +235,7 @@ __host__ int lb_init(lb_t * lb) { /* The total number of distribution data is then... */ - ndata = lb->nsite*lb->ndist*NVEL; + ndata = lb->nsite*lb->ndist*lb->model.nvel; #ifdef OLD_DATA lb->f = (double *) calloc(ndata, sizeof(double)); if (lb->f == NULL) pe_fatal(lb->pe, "malloc(distributions) failed\n"); @@ -333,35 +333,30 @@ __host__ int lb_collide_param_commit(lb_t * lb) { static int lb_model_param_init(lb_t * lb) { int ia, ib, p; - LB_CS2_DOUBLE(cs2); - KRONECKER_DELTA_CHAR(d_); assert(lb); assert(lb->param); lb->param->nsite = lb->nsite; lb->param->ndist = lb->ndist; + lb->param->nvel = lb->model.nvel; - for (p = 0; p < NVEL; p++) { - lb->param->wv[p] = wv[p]; - for (ia = 0; ia < 3; ia++) { - lb->param->cv[p][ia] = cv[p][ia]; - } + for (p = 0; p < lb->model.nvel; p++) { + lb->param->wv[p] = lb->model.wv[p]; for (ia = 0; ia < 3; ia++) { - for (ib = 0; ib < 3; ib++) { - lb->param->q[p][ia][ib] = cv[p][ia]*cv[p][ib] - cs2*d_[ia][ib]; - } + lb->param->cv[p][ia] = lb->model.cv[p][ia]; } } - for (ia = 0; ia < NVEL; ia++) { + for (ia = 0; ia < lb->model.nvel; ia++) { lb->param->rna[ia] = 1.0/lb->model.na[ia]; } - for (ia = 0; ia < NVEL; ia++) { - for (ib = 0; ib < NVEL; ib++) { + for (ia = 0; ia < lb->model.nvel; ia++) { + for (ib = 0; ib < lb->model.nvel; ib++) { + double maba = lb->model.ma[ib][ia]; lb->param->ma[ia][ib] = lb->model.ma[ia][ib]; - lb->param->mi[ia][ib] = lb->model.wv[ia]*lb->model.na[ib]*lb->model.ma[ib][ia]; + lb->param->mi[ia][ib] = lb->model.wv[ia]*lb->model.na[ib]*maba; } } @@ -954,13 +949,15 @@ static int lb_f_read(FILE * fp, int index, void * self) { assert(lb); for (n = 0; n < lb->ndist; n++) { - for (p = 0; p < NVEL; p++) { - iread = LB_ADDR(lb->nsite, lb->ndist, NVEL, index, n, p); + for (p = 0; p < lb->model.nvel; p++) { + iread = LB_ADDR(lb->nsite, lb->ndist, lb->model.nvel, index, n, p); nr += fread(lb->f + iread, sizeof(double), 1, fp); } } - if (nr != lb->ndist*NVEL) pe_fatal(lb->pe, "fread(lb) failed at %d\n", index); + if (nr != lb->ndist*lb->model.nvel) { + pe_fatal(lb->pe, "fread(lb) failed at %d\n", index); + } return 0; } @@ -992,13 +989,15 @@ static int lb_f_read_ascii(FILE * fp, int index, void * self) { nr = 0; for (n = 0; n < lb->ndist; n++) { - for (p = 0; p < NVEL; p++) { - nr += fscanf(fp, "%le", - &lb->f[LB_ADDR(lb->nsite, lb->ndist, NVEL, index, n, p)]); + for (p = 0; p < lb->model.nvel; p++) { + int ijkp = LB_ADDR(lb->nsite, lb->ndist, lb->model.nvel, index, n, p); + nr += fscanf(fp, "%le", &lb->f[ijkp]); } } - if (nr != lb->ndist*NVEL) pe_fatal(pe, "fread(lb) failed at %d\n", index); + if (nr != lb->ndist*lb->model.nvel) { + pe_fatal(pe, "fread(lb) failed at %d\n", index); + } return 0; } @@ -1022,13 +1021,15 @@ static int lb_f_write(FILE * fp, int index, void * self) { assert(self); for (n = 0; n < lb->ndist; n++) { - for (p = 0; p < NVEL; p++) { - iwrite = LB_ADDR(lb->nsite, lb->ndist, NVEL, index, n, p); + for (p = 0; p < lb->model.nvel; p++) { + iwrite = LB_ADDR(lb->nsite, lb->ndist, lb->model.nvel, index, n, p); nw += fwrite(lb->f + iwrite, sizeof(double), 1, fp); } } - if (nw != lb->ndist*NVEL) pe_fatal(lb->pe, "fwrite(lb) failed at %d\n", index); + if (nw != lb->ndist*lb->model.nvel) { + pe_fatal(lb->pe, "fwrite(lb) failed at %d\n", index); + } return 0; } @@ -1062,17 +1063,25 @@ static int lb_f_write_ascii(FILE * fp, int index, void * self) { cs_nlocal_offset(cs, noffset); /* write output index */ - fprintf(fp, "%d %d %d ", noffset[X]+coords[X], noffset[Y]+coords[Y], noffset[Z]+coords[Z]); + { + int ic = noffset[X] + coords[X]; + int jc = noffset[Y] + coords[Y]; + int kc = noffset[Z] + coords[Z]; + fprintf(fp, "%d %d %d ", ic, jc, kc); + } for (n = 0; n < lb->ndist; n++) { - for (p = 0; p < NVEL; p++) { - fprintf(fp, "%le ", lb->f[LB_ADDR(lb->nsite, lb->ndist, NVEL, index, n, p)]); + for (p = 0; p < lb->model.nvel; p++) { + int ijkp = LB_ADDR(lb->nsite, lb->ndist, lb->model.nvel, index, n, p); + fprintf(fp, "%le ", lb->f[ijkp]); nw++; } } fprintf(fp, "\n"); - if (nw != lb->ndist*NVEL) pe_fatal(pe, "fwrite(lb) failed at %d\n", index); + if (nw != lb->ndist*lb->model.nvel) { + pe_fatal(pe, "fwrite(lb) failed at %d\n", index); + } return 0; } @@ -1287,9 +1296,10 @@ int lb_1st_moment(lb_t * lb, int index, lb_dist_enum_t nd, double g[3]) { g[n] = 0.0; } - for (p = 0; p < NVEL; p++) { - for (n = 0; n < NDIM; n++) { - g[n] += cv[p][n]*lb->f[LB_ADDR(lb->nsite, lb->ndist, NVEL, index, nd, p)]; + for (p = 0; p < lb->model.nvel; p++) { + for (n = 0; n < lb->model.ndim; n++) { + g[n] += lb->model.cv[p][n] + *lb->f[LB_ADDR(lb->nsite, lb->ndist, lb->model.nvel, index, nd, p)]; } } @@ -1308,24 +1318,25 @@ __host__ int lb_2nd_moment(lb_t * lb, int index, lb_dist_enum_t nd, double s[3][3]) { int p, ia, ib; - LB_CS2_DOUBLE(cs2); - KRONECKER_DELTA_CHAR(d_); assert(lb); assert(nd == LB_RHO); assert(index >= 0 && index < lb->nsite); - for (ia = 0; ia < NDIM; ia++) { - for (ib = 0; ib < NDIM; ib++) { + for (ia = 0; ia < lb->model.ndim; ia++) { + for (ib = 0; ib < lb->model.ndim; ib++) { s[ia][ib] = 0.0; } } - for (p = 0; p < NVEL; p++) { - for (ia = 0; ia < NDIM; ia++) { - for (ib = 0; ib < NDIM; ib++) { - s[ia][ib] += lb->f[LB_ADDR(lb->nsite, lb->ndist, NVEL, index, nd, p)] - *(cv[p][ia]*cv[p][ib] - cs2*d_[ia][ib]); + for (p = 0; p < lb->model.nvel; p++) { + for (ia = 0; ia < lb->model.ndim; ia++) { + for (ib = 0; ib < lb->model.ndim; ib++) { + double f = 0.0; + double cs2 = lb->model.cs2; + double dab = (ia == ib); + f = lb->f[LB_ADDR(lb->nsite, lb->ndist, lb->model.nvel, index, nd, p)]; + s[ia][ib] += f*(lb->model.cv[p][ia]*lb->model.cv[p][ib] - cs2*dab); } } } @@ -1352,8 +1363,9 @@ int lb_0th_moment_equilib_set(lb_t * lb, int index, int n, double rho) { assert (n >= 0 && n < lb->ndist); assert(index >= 0 && index < lb->nsite); - for (p = 0; p < NVEL; p++) { - lb->f[LB_ADDR(lb->nsite, lb->ndist, NVEL, index, n, p)] = wv[p]*rho; + for (p = 0; p < lb->model.nvel; p++) { + double f = lb->model.wv[p]*rho; + lb->f[LB_ADDR(lb->nsite, lb->ndist, lb->model.nvel, index, n, p)] = f; } return 0; @@ -1371,27 +1383,25 @@ __host__ int lb_1st_moment_equilib_set(lb_t * lb, int index, double rho, double u[3]) { int ia, ib, p; - double udotc; - double sdotq; - LB_CS2_DOUBLE(cs2); - LB_RCS2_DOUBLE(rcs2); - KRONECKER_DELTA_CHAR(d_); assert(lb); assert(index >= 0 && index < lb->nsite); - for (p = 0; p < NVEL; p++) { - udotc = 0.0; - sdotq = 0.0; + for (p = 0; p < lb->model.nvel; p++) { + double cs2 = lb->model.cs2; + double rcs2 = 1.0/cs2; + double udotc = 0.0; + double sdotq = 0.0; for (ia = 0; ia < 3; ia++) { - udotc += u[ia]*cv[p][ia]; + udotc += u[ia]*lb->model.cv[p][ia]; for (ib = 0; ib < 3; ib++) { - sdotq += (cv[p][ia]*cv[p][ib] - cs2*d_[ia][ib])*u[ia]*u[ib]; + double dab = (ia == ib); + sdotq += (lb->model.cv[p][ia]*lb->model.cv[p][ib] - cs2*dab)*u[ia]*u[ib]; } } - lb->f[LB_ADDR(lb->nsite, lb->ndist, NVEL, index, LB_RHO, p)] - = rho*wv[p]*(1.0 + rcs2*udotc + 0.5*rcs2*rcs2*sdotq); + lb->f[LB_ADDR(lb->nsite, lb->ndist, lb->model.nvel, index, LB_RHO, p)] + = rho*lb->model.wv[p]*(1.0 + rcs2*udotc + 0.5*rcs2*rcs2*sdotq); } return 0; @@ -1440,7 +1450,7 @@ __host__ int lb_halo_via_copy(lb_t * lb) { /* The x-direction (YZ plane) */ - nsend = NVEL*lb->ndist*nlocal[Y]*nlocal[Z]; + nsend = lb->model.nvel*lb->ndist*nlocal[Y]*nlocal[Z]; sendforw = (double *) malloc(nsend*sizeof(double)); sendback = (double *) malloc(nsend*sizeof(double)); recvforw = (double *) malloc(nsend*sizeof(double)); @@ -1453,7 +1463,7 @@ __host__ int lb_halo_via_copy(lb_t * lb) { if (recvforw == NULL) pe_fatal(lb->pe, "malloc(recvback) failed\n"); count = 0; - for (p = 0; p < NVEL; p++) { + for (p = 0; p < lb->model.nvel; p++) { for (n = 0; n < lb->ndist; n++) { for (jc = 1; jc <= nlocal[Y]; jc++) { for (kc = 1; kc <= nlocal[Z]; kc++) { @@ -1492,7 +1502,7 @@ __host__ int lb_halo_via_copy(lb_t * lb) { } count = 0; - for (p = 0; p < NVEL; p++) { + for (p = 0; p < lb->model.nvel; p++) { for (n = 0; n < lb->ndist; n++) { for (jc = 1; jc <= nlocal[Y]; jc++) { for (kc = 1; kc <= nlocal[Z]; kc++) { @@ -1525,7 +1535,7 @@ __host__ int lb_halo_via_copy(lb_t * lb) { /* The y-direction (XZ plane) */ - nsend = NVEL*lb->ndist*(nlocal[X] + 2)*nlocal[Z]; + nsend = lb->model.nvel*lb->ndist*(nlocal[X] + 2)*nlocal[Z]; sendforw = (double *) malloc(nsend*sizeof(double)); sendback = (double *) malloc(nsend*sizeof(double)); recvforw = (double *) malloc(nsend*sizeof(double)); @@ -1536,7 +1546,7 @@ __host__ int lb_halo_via_copy(lb_t * lb) { if (recvforw == NULL) pe_fatal(lb->pe, "malloc(recvback) failed\n"); count = 0; - for (p = 0; p < NVEL; p++) { + for (p = 0; p < lb->model.nvel; p++) { for (n = 0; n < lb->ndist; n++) { for (ic = 0; ic <= nlocal[X] + 1; ic++) { for (kc = 1; kc <= nlocal[Z]; kc++) { @@ -1576,7 +1586,7 @@ __host__ int lb_halo_via_copy(lb_t * lb) { } count = 0; - for (p = 0; p < NVEL; p++) { + for (p = 0; p < lb->model.nvel; p++) { for (n = 0; n < lb->ndist; n++) { for (ic = 0; ic <= nlocal[X] + 1; ic++) { for (kc = 1; kc <= nlocal[Z]; kc++) { @@ -1607,7 +1617,7 @@ __host__ int lb_halo_via_copy(lb_t * lb) { /* Finally, z-direction (XY plane) */ - nsend = NVEL*lb->ndist*(nlocal[X] + 2)*(nlocal[Y] + 2); + nsend = lb->model.nvel*lb->ndist*(nlocal[X] + 2)*(nlocal[Y] + 2); sendforw = (double *) malloc(nsend*sizeof(double)); sendback = (double *) malloc(nsend*sizeof(double)); recvforw = (double *) malloc(nsend*sizeof(double)); @@ -1618,7 +1628,7 @@ __host__ int lb_halo_via_copy(lb_t * lb) { if (recvforw == NULL) pe_fatal(lb->pe, "malloc(recvback) failed\n"); count = 0; - for (p = 0; p < NVEL; p++) { + for (p = 0; p < lb->model.nvel; p++) { for (n = 0; n < lb->ndist; n++) { for (ic = 0; ic <= nlocal[X] + 1; ic++) { for (jc = 0; jc <= nlocal[Y] + 1; jc++) { @@ -1657,7 +1667,7 @@ __host__ int lb_halo_via_copy(lb_t * lb) { } count = 0; - for (p = 0; p < NVEL; p++) { + for (p = 0; p < lb->model.nvel; p++) { for (n = 0; n < lb->ndist; n++) { for (ic = 0; ic <= nlocal[X] + 1; ic++) { for (jc = 0; jc <= nlocal[Y] + 1; jc++) { diff --git a/src/model_le.c b/src/model_le.c index 5ba41dc04..61bbb5f92 100644 --- a/src/model_le.c +++ b/src/model_le.c @@ -129,11 +129,6 @@ static int le_reproject(lb_t * lb, lees_edw_t * le) { double t; physics_t * phys = NULL; - LB_CS2_DOUBLE(cs2); - LB_RCS2_DOUBLE(rcs2); - KRONECKER_DELTA_CHAR(d_); - const double r2rcs4 = 4.5; /* The constant 1 / 2 c_s^4 */ - assert(lb); assert(le); assert(CVXBLOCK == 1); @@ -188,22 +183,27 @@ static int le_reproject(lb_t * lb, lees_edw_t * le) { for (np = 0; np < xblocklen_cv[0]; np++) { + double cs2 = lb->model.cs2; + double rcs2 = 1.0/cs2; + /* Pick up the correct velocity indices */ p = poffset + np; - udotc = du[Y]*cv[p][Y]; + udotc = du[Y]*lb->model.cv[p][Y]; sdotq = 0.0; for (ia = 0; ia < 3; ia++) { for (ib = 0; ib < 3; ib++) { - sdotq += ds[ia][ib]*(cv[p][ia]*cv[p][ib] - cs2*d_[ia][ib]); + double dab = cs2*(ia == ib); + double q = (lb->model.cv[p][ia]*lb->model.cv[p][ib] - dab); + sdotq += ds[ia][ib]*q; } } /* Project all this back to the distribution. */ lb_f(lb, index, p, n, &fnew); - fnew += wv[p]*(rho*udotc*rcs2 + sdotq*r2rcs4); + fnew += lb->model.wv[p]*(rho*udotc*rcs2 + 0.5*sdotq*rcs2*rcs2); lb_f_set(lb, index, p, n, fnew); } } @@ -284,10 +284,11 @@ static int le_reproject_all(lb_t * lb, lees_edw_t * le) { /* Compute modes */ - for (m = 0; m < NVEL; m++) { + for (m = 0; m < lb->model.nvel; m++) { mode[m] = 0.0; - for (p = 0; p < NVEL; p++) { - mode[m] += lb->f[ndist*NVEL*index + 0 + p]*lb->param->ma[m][p]; + for (p = 0; p < lb->model.nvel; p++) { + int ijk = LB_ADDR(lb->nsite, ndist, lb->model.nvel, index, 0, p); + mode[m] += lb->f[ijk]*lb->param->ma[m][p]; } } @@ -309,9 +310,12 @@ static int le_reproject_all(lb_t * lb, lees_edw_t * le) { for (np = 0; np < xblocklen_cv[0]; np++) { p = poffset + np; - lb->f[ndist*NVEL*index + 0 + p] = 0.0; - for (m = 0; m < NVEL; m++) { - lb->f[ndist*NVEL*index + 0 + p] += mode[m]*lb->param->mi[p][m]; + { + int ijk = LB_ADDR(lb->nsite, ndist, lb->model.nvel, index, 0, p); + lb->f[ijk] = 0.0; + for (m = 0; m < lb->model.nvel; m++) { + lb->f[ijk] += mode[m]*lb->param->mi[p][m]; + } } } @@ -401,9 +405,9 @@ int le_displace_and_interpolate(lb_t * lb, lees_edw_t * le) { for (p = 0; p < nprop; p++) { int pcv = xdisp_fwd_cv[0] + p; recv_buff[ndata++] = (1.0 - fr)* - lb->f[LB_ADDR(lb->nsite,ndist,NVEL,index0,n, pcv)] + lb->f[LB_ADDR(lb->nsite,ndist,lb->model.nvel,index0,n, pcv)] + fr* - lb->f[LB_ADDR(lb->nsite,ndist,NVEL,index1,n, pcv)]; + lb->f[LB_ADDR(lb->nsite,ndist,lb->model.nvel,index1,n, pcv)]; } } /* Next site */ @@ -421,7 +425,8 @@ int le_displace_and_interpolate(lb_t * lb, lees_edw_t * le) { for (n = 0; n < ndist; n++) { for (p = 0; p < nprop; p++) { int pcv = xdisp_fwd_cv[0] + p; - lb->f[LB_ADDR(lb->nsite, ndist, NVEL, index0, n, pcv)] = recv_buff[ndata++]; + int la = LB_ADDR(lb->nsite, ndist, lb->model.nvel, index0, n, pcv); + lb->f[la] = recv_buff[ndata++]; } } /* Next site */ @@ -452,9 +457,9 @@ int le_displace_and_interpolate(lb_t * lb, lees_edw_t * le) { for (n = 0; n < ndist; n++) { for (p = 0; p < nprop; p++) { int pcv = xdisp_bwd_cv[0] + p; - recv_buff[ndata++] = (1.0 - fr)* - lb->f[LB_ADDR(lb->nsite,ndist,NVEL,index0, n, pcv)] + fr* - lb->f[LB_ADDR(lb->nsite, ndist, NVEL, index1, n, pcv)]; + int l0 = LB_ADDR(lb->nsite, ndist, lb->model.nvel, index0, n, pcv); + int l1 = LB_ADDR(lb->nsite, ndist, lb->model.nvel, index1, n, pcv); + recv_buff[ndata++] = (1.0 - fr)*lb->f[l0] + fr*lb->f[l1]; } } /* Next site */ @@ -472,7 +477,8 @@ int le_displace_and_interpolate(lb_t * lb, lees_edw_t * le) { for (n = 0; n < ndist; n++) { for (p = 0; p < nprop; p++) { int pcv = xdisp_bwd_cv[0] + p; - lb->f[LB_ADDR(lb->nsite, ndist, NVEL, index0, n, pcv)] = recv_buff[ndata++]; + int ijkp = LB_ADDR(lb->nsite, ndist, lb->model.nvel,index0,n,pcv); + lb->f[ijkp] = recv_buff[ndata++]; } } } @@ -606,7 +612,9 @@ static int le_displace_and_interpolate_parallel(lb_t * lb, lees_edw_t * le) { for (n = 0; n < ndist; n++) { for (p = 0; p < nprop; p++) { - send_buff[ndata++] = lb->f[LB_ADDR(lb->nsite, ndist, NVEL, index, n, xdisp_fwd_cv[0] + p)]; + int ijkp = LB_ADDR(lb->nsite, ndist, lb->model.nvel, index, n, + xdisp_fwd_cv[0] + p); + send_buff[ndata++] = lb->f[ijkp]; } } /* Next site */ @@ -635,7 +643,9 @@ static int le_displace_and_interpolate_parallel(lb_t * lb, lees_edw_t * le) { ind2 = ind0 + ndist*nprop*nlocal[Z] + n*nprop; for (p = 0; p < nprop; p++) { - lb->f[LB_ADDR(lb->nsite, ndist, NVEL, index, n, xdisp_fwd_cv[0] + p)] = (1.0-fr)*recv_buff[ind1 + p] + fr*recv_buff[ind2 + p]; + int ijk = LB_ADDR(lb->nsite, ndist, lb->model.nvel, index, n, + xdisp_fwd_cv[0] + p); + lb->f[ijk] = (1.0-fr)*recv_buff[ind1 + p] + fr*recv_buff[ind2 + p]; } } /* Next site */ @@ -687,7 +697,9 @@ static int le_displace_and_interpolate_parallel(lb_t * lb, lees_edw_t * le) { for (n = 0; n < ndist; n++) { for (p = 0; p < nprop; p++) { - send_buff[ndata++] = lb->f[LB_ADDR(lb->nsite, ndist, NVEL, index, n, xdisp_bwd_cv[0] + p)]; + int ijkp = LB_ADDR(lb->nsite, ndist, lb->model.nvel, index, n, + xdisp_bwd_cv[0] + p); + send_buff[ndata++] = lb->f[ijkp]; } } /* Next site */ @@ -716,7 +728,9 @@ static int le_displace_and_interpolate_parallel(lb_t * lb, lees_edw_t * le) { ind2 = ind0 + ndist*nprop*nlocal[Z] + n*nprop; for (p = 0; p < nprop; p++) { - lb->f[LB_ADDR(lb->nsite, ndist, NVEL, index, n, xdisp_bwd_cv[0] + p)] = (1.0-fr)*recv_buff[ind1 + p] + fr*recv_buff[ind2 + p]; + int ijk = LB_ADDR(lb->nsite, ndist, lb->model.nvel, index, n, + xdisp_bwd_cv[0] + p); + lb->f[ijk] = (1.0-fr)*recv_buff[ind1 + p] + fr*recv_buff[ind2 + p]; } } /* Next site */ @@ -749,9 +763,6 @@ int lb_le_init_shear_profile(lb_t * lb, lees_edw_t * le) { int nlocal[3]; double rho0, u[NDIM], gradu[NDIM][NDIM]; double eta; - LB_CS2_DOUBLE(cs2); - LB_RCS2_DOUBLE(rcs2); - KRONECKER_DELTA_CHAR(d_); physics_t * phys = NULL; @@ -768,9 +779,9 @@ int lb_le_init_shear_profile(lb_t * lb, lees_edw_t * le) { lees_edw_nlocal(le, nlocal); - for (i = 0; i< NDIM; i++) { + for (i = 0; i< lb->model.ndim; i++) { u[i] = 0.0; - for (j = 0; j < NDIM; j++) { + for (j = 0; j < lb->model.ndim; j++) { gradu[i][j] = 0.0; } } @@ -790,19 +801,22 @@ int lb_le_init_shear_profile(lb_t * lb, lees_edw_t * le) { index = lees_edw_index(le, ic, jc, kc); - for (p = 0; p < NVEL; p++) { + for (p = 0; p < lb->model.nvel; p++) { double f = 0.0; double cdotu = 0.0; double sdotq = 0.0; - - for (i = 0; i < NDIM; i++) { - cdotu += cv[p][i]*u[i]; - for (j = 0; j < NDIM; j++) { - double q_ij = cv[p][i]*cv[p][j] - cs2*d_[i][j]; - sdotq += (rho0*u[i]*u[j] - eta*gradu[i][j])*q_ij; + double cs2 = lb->model.cs2; + double rcs2 = 1.0/cs2; + + for (i = 0; i < lb->model.ndim; i++) { + cdotu += lb->model.cv[p][i]*u[i]; + for (j = 0; j < lb->model.ndim; j++) { + double dij = (i == j); + double qij = lb->model.cv[p][i]*lb->model.cv[p][j] - cs2*dij; + sdotq += (rho0*u[i]*u[j] - eta*gradu[i][j])*qij; } } - f = wv[p]*(rho0 + rcs2*rho0*cdotu + 0.5*rcs2*rcs2*sdotq); + f = lb->model.wv[p]*(rho0 + rcs2*rho0*cdotu + 0.5*rcs2*rcs2*sdotq); lb_f_set(lb, index, p, 0, f); } /* Next site */ diff --git a/src/phi_force_colloid.c b/src/phi_force_colloid.c index 146974b9d..eb9eb5f12 100644 --- a/src/phi_force_colloid.c +++ b/src/phi_force_colloid.c @@ -64,7 +64,8 @@ #include "timer.h" int pth_force_driver(pth_t * pth, colloids_info_t * cinfo, - hydro_t * hydro, map_t * map, wall_t * wall); + hydro_t * hydro, map_t * map, wall_t * wall, + const lb_model_t * model); __global__ void pth_force_map_kernel(kernel_ctxt_t * ktx, pth_t * pth, hydro_t * hydro, map_t * map); @@ -83,7 +84,8 @@ __global__ void pth_force_fluid_kernel_v(kernel_ctxt_t * ktx, pth_t * pth, *****************************************************************************/ __host__ int pth_force_colloid(pth_t * pth, fe_t * fe, colloids_info_t * cinfo, - hydro_t * hydro, map_t * map, wall_t * wall) { + hydro_t * hydro, map_t * map, wall_t * wall, + const lb_model_t * model) { int ncolloid; @@ -95,7 +97,7 @@ __host__ int pth_force_colloid(pth_t * pth, fe_t * fe, colloids_info_t * cinfo, if (pth->method == PTH_METHOD_DIVERGENCE) { pth_stress_compute(pth, fe); - pth_force_driver(pth, cinfo, hydro, map, wall); + pth_force_driver(pth, cinfo, hydro, map, wall, model); } return 0; @@ -116,7 +118,8 @@ __host__ int pth_force_colloid(pth_t * pth, fe_t * fe, colloids_info_t * cinfo, static __device__ double fs[3]; __host__ int pth_force_driver(pth_t * pth, colloids_info_t * cinfo, - hydro_t * hydro, map_t * map, wall_t * wall) { + hydro_t * hydro, map_t * map, wall_t * wall, + const lb_model_t * model) { int ia; int nlocal[3]; dim3 nblk, ntpb; @@ -189,16 +192,18 @@ __host__ int pth_force_driver(pth_t * pth, colloids_info_t * cinfo, int cmod; p = p_link->p; - cmod = cv[p][X]*cv[p][X] + cv[p][Y]*cv[p][Y] + cv[p][Z]*cv[p][Z]; + cmod = model->cv[p][X]*model->cv[p][X] + + model->cv[p][Y]*model->cv[p][Y] + + model->cv[p][Z]*model->cv[p][Z]; if (cmod != 1) continue; id = -1; - if (cv[p][X]) id = X; - if (cv[p][Y]) id = Y; - if (cv[p][Z]) id = Z; + if (model->cv[p][X]) id = X; + if (model->cv[p][Y]) id = Y; + if (model->cv[p][Z]) id = Z; for (ia = 0; ia < 3; ia++) { - pc->force[ia] += 1.0*cv[p][id] + pc->force[ia] += 1.0*model->cv[p][id] *pth->str[addr_rank2(pth->nsites, 3, 3, p_link->i, ia, id)]; } } diff --git a/src/phi_force_colloid.h b/src/phi_force_colloid.h index 9a9a8ee0f..e30b7dc37 100644 --- a/src/phi_force_colloid.h +++ b/src/phi_force_colloid.h @@ -27,6 +27,7 @@ __host__ int pth_force_fluid_driver(pth_t * pth, hydro_t * hydro); __host__ int pth_force_fluid_wall_driver(pth_t * pth, hydro_t * hydro, map_t * map, wall_t * wall); __host__ int pth_force_colloid(pth_t * pth, fe_t * fe, colloids_info_t * cinfo, - hydro_t * hydro, map_t * map, wall_t * wall); + hydro_t * hydro, map_t * map, wall_t * wall, + const lb_model_t * model); #endif diff --git a/src/wall.c b/src/wall.c index e364d3a8b..a1a66eb83 100644 --- a/src/wall.c +++ b/src/wall.c @@ -65,6 +65,7 @@ __host__ int wall_create(pe_t * pe, cs_t * cs, map_t * map, lb_t * lb, assert(pe); assert(cs); + assert(lb); assert(p); wall = (wall_t *) calloc(1, sizeof(wall_t)); @@ -385,6 +386,7 @@ __host__ int wall_init_boundaries(wall_t * wall, wall_init_enum_t init) { int ndevice; assert(wall); + assert(wall->lb); tdpGetDeviceCount(&ndevice); @@ -427,17 +429,19 @@ __host__ int wall_init_boundaries(wall_t * wall, wall_init_enum_t init) { for (jc = 1; jc <= nlocal[Y]; jc++) { for (kc = 1; kc <= nlocal[Z]; kc++) { + lb_t * lb = wall->lb; + indexi = cs_index(wall->cs, ic, jc, kc); map_status(wall->map, indexi, &status); if (status != MAP_FLUID) continue; /* Look for non-solid -> solid links */ - for (p = 1; p < NVEL; p++) { + for (p = 1; p < lb->model.nvel; p++) { - ic1 = ic + cv[p][X]; - jc1 = jc + cv[p][Y]; - kc1 = kc + cv[p][Z]; + ic1 = ic + lb->model.cv[p][X]; + jc1 = jc + lb->model.cv[p][Y]; + kc1 = kc + lb->model.cv[p][Z]; indexj = cs_index(wall->cs, ic1, jc1, kc1); map_status(wall->map, indexj, &status); @@ -532,6 +536,8 @@ __host__ int wall_init_boundaries_slip(wall_t * wall) { for (int n = 0; n < nlink; n++) { + lb_t * lb = wall->lb; + /* Identify the wall normal wn, and project cv[p] into the * plane orthogonal to the normal to find the tangetial * direction which takes us to the fluid site paired with @@ -549,15 +555,16 @@ __host__ int wall_init_boundaries_slip(wall_t * wall) { /* tangent = cv[p] - (cv[p].n/n.n) n */ /* But we are in integers, so watch any division */ - cvdotwn = cv[p][X]*wn[X] + cv[p][Y]*wn[Y] + cv[p][Z]*wn[Z]; + cvdotwn = lb->model.cv[p][X]*wn[X] + lb->model.cv[p][Y]*wn[Y] + + lb->model.cv[p][Z]*wn[Z]; modwn = wn[X]*wn[X] + wn[Y]*wn[Y] + wn[Z]*wn[Z]; assert(cvdotwn == -1 || cvdotwn == -2 || cvdotwn == -3); assert(modwn == -cvdotwn); - wt[X] = (cv[p][X] - cvdotwn*wn[X]/modwn); - wt[Y] = (cv[p][Y] - cvdotwn*wn[Y]/modwn); - wt[Z] = (cv[p][Z] - cvdotwn*wn[Z]/modwn); + wt[X] = (lb->model.cv[p][X] - cvdotwn*wn[X]/modwn); + wt[Y] = (lb->model.cv[p][Y] - cvdotwn*wn[Y]/modwn); + wt[Z] = (lb->model.cv[p][Z] - cvdotwn*wn[Z]/modwn); modwt = wt[X]*wt[X] + wt[Y]*wt[Y] + wt[Z]*wt[Z]; if (modwt == 0) { @@ -603,6 +610,8 @@ __host__ int wall_link_normal(wall_t * wall, int n, int wn[3]) { if (wall->param->iswall) { + lb_t * lb = wall->lb; + int i0[3] = {0}; int p = wall->linkp[n]; int ic, jc, kc, index; @@ -610,20 +619,20 @@ __host__ int wall_link_normal(wall_t * wall, int n, int wn[3]) { cs_index_to_ijk(wall->cs, wall->linki[n], i0); - ic = i0[X] + cv[p][X]; jc = i0[Y], kc = i0[Z]; + ic = i0[X] + lb->model.cv[p][X]; jc = i0[Y], kc = i0[Z]; index = cs_index(wall->cs, ic, jc, kc); map_status(wall->map, index, &status); - if (status != MAP_FLUID) wn[X] = -cv[p][X]; + if (status != MAP_FLUID) wn[X] = -lb->model.cv[p][X]; - ic = i0[X]; jc = i0[Y] + cv[p][Y]; kc = i0[Z]; + ic = i0[X]; jc = i0[Y] + lb->model.cv[p][Y]; kc = i0[Z]; index = cs_index(wall->cs, ic, jc, kc); map_status(wall->map, index, &status); - if (status != MAP_FLUID) wn[Y] = -cv[p][Y]; + if (status != MAP_FLUID) wn[Y] = -lb->model.cv[p][Y]; - ic = i0[X]; jc = i0[Y]; kc = i0[Z] + cv[p][Z]; + ic = i0[X]; jc = i0[Y]; kc = i0[Z] + lb->model.cv[p][Z]; index = cs_index(wall->cs, ic, jc, kc); map_status(wall->map, index, &status); - if (status != MAP_FLUID) wn[Z] = -cv[p][Z]; + if (status != MAP_FLUID) wn[Z] = -lb->model.cv[p][Z]; } return 0; @@ -652,6 +661,8 @@ __host__ int wall_link_slip_direction(wall_t * wall, int n) { if (wall->param->iswall) { + lb_t * lb = wall->lb; + int cq[3] = {0}; int wn[3] = {0}; int pn = wall->linkp[n]; @@ -661,16 +672,18 @@ __host__ int wall_link_slip_direction(wall_t * wall, int n) { wall_link_normal(wall, n, wn); - cq[X] = -2*wn[X] - cv[pn][X]; - cq[Y] = -2*wn[Y] - cv[pn][Y]; - cq[Z] = -2*wn[Z] - cv[pn][Z]; + cq[X] = -2*wn[X] - lb->model.cv[pn][X]; + cq[Y] = -2*wn[Y] - lb->model.cv[pn][Y]; + cq[Z] = -2*wn[Z] - lb->model.cv[pn][Z]; /* Find the appropriate index */ - for (int p = 0; p < NVEL; p++) { - if (cq[X] == cv[p][X] && cq[Y] == cv[p][Y] && cq[Z] == cv[p][Z]) q = p; + for (int p = 0; p < lb->model.nvel; p++) { + if (cq[X] == lb->model.cv[p][X] && + cq[Y] == lb->model.cv[p][Y] && + cq[Z] == lb->model.cv[p][Z]) q = p; } - assert(0 < q && q < NVEL); + assert(0 < q && q < lb->model.nvel); } return q; @@ -856,6 +869,7 @@ __host__ int wall_init_uw(wall_t * wall) { + wall->param->isboundary[Z]; if (nwall == 1) { + lb_t * lb = wall->lb; /* All links are either top or bottom */ iw = -1; if (wall->param->isboundary[X]) iw = X; @@ -864,8 +878,8 @@ __host__ int wall_init_uw(wall_t * wall) { assert(iw == X || iw == Y || iw == Z); for (n = 0; n < wall->nlink; n++) { - if (cv[wall->linkp[n]][iw] == -1) wall->linku[n] = WALL_UWBOT; - if (cv[wall->linkp[n]][iw] == +1) wall->linku[n] = WALL_UWTOP; + if (lb->model.cv[wall->linkp[n]][iw] == -1) wall->linku[n] = WALL_UWBOT; + if (lb->model.cv[wall->linkp[n]][iw] == +1) wall->linku[n] = WALL_UWTOP; } } @@ -922,7 +936,7 @@ __global__ void wall_setu_kernel(wall_t * wall, lb_t * lb) { for_simt_parallel(n, wall->nlink, 1) { - p = NVEL - wall->linkp[n]; + p = lb->param->nvel - wall->linkp[n]; fp = lb->param->wv[p]*(lb->param->rho0 + rcs2*ux*lb->param->cv[p][X]); lb_f_set(lb, wall->linkj[n], p, LB_RHO, fp); @@ -1018,9 +1032,9 @@ __global__ void wall_bbl_kernel(wall_t * wall, lb_t * lb, map_t * map) { i = wall->linki[n]; j = wall->linkj[n]; - ij = wall->linkp[n]; /* Link index direction solid->fluid */ - ji = NVEL - ij; /* Opposite direction index */ - ia = wall->linku[n]; /* Wall velocity lookup */ + ij = wall->linkp[n]; /* Link index direction solid->fluid */ + ji = lb->param->nvel - ij; /* Opposite direction index */ + ia = wall->linku[n]; /* Wall velocity lookup */ cdotu = lb->param->cv[ij][X]*uw[ia][X] + lb->param->cv[ij][Y]*uw[ia][Y] + @@ -1125,8 +1139,8 @@ __global__ void wall_bbl_slip_kernel(wall_t * wall, lb_t * lb, map_t * map) { i = wall->linki[n]; j = wall->linkj[n]; - ij = wall->linkp[n]; /* Link index direction solid->fluid */ - ji = NVEL - ij; /* Opposite direction index */ + ij = wall->linkp[n]; /* Link index direction solid->fluid */ + ji = lb->param->nvel - ij; /* Opposite direction index */ map_status(map, i, &status); @@ -1391,8 +1405,6 @@ __host__ int wall_shear_init(wall_t * wall) { double uxtop; double ltot[3]; - LB_CS2_DOUBLE(cs2); - LB_RCS2_DOUBLE(rcs2); KRONECKER_DELTA_CHAR(d_); physics_t * phys = NULL; @@ -1436,25 +1448,29 @@ __host__ int wall_shear_init(wall_t * wall) { for (jc = 1; jc <= nlocal[Y]; jc++) { for (kc = 1; kc <= nlocal[Z]; kc++) { + lb_t * lb = wall->lb; + double cs2 = lb->model.cs2; + double rcs2 = 1.0/cs2; + /* Linearly interpolate between top and bottom to get velocity; * the - 1.0 accounts for kc starting at 1. */ u[X] = uxbottom + (noffset[Z] + kc - 0.5)*(uxtop - uxbottom)/ltot[Z]; index = cs_index(wall->cs, ic, jc, kc); - for (p = 0; p < NVEL; p++) { + for (p = 0; p < lb->model.nvel; p++) { cdotu = 0.0; sdotq = 0.0; for (ia = 0; ia < 3; ia++) { - cdotu += cv[p][ia]*u[ia]; + cdotu += lb->model.cv[p][ia]*u[ia]; for (ib = 0; ib < 3; ib++) { - double q_ab = cv[p][ia]*cv[p][ib] - cs2*d_[ia][ib]; + double q_ab = lb->model.cv[p][ia]*lb->model.cv[p][ib] - cs2*d_[ia][ib]; sdotq += (rho*u[ia]*u[ib] - eta*gradu[ia][ib])*q_ab; } } - f = wv[p]*rho*(1.0 + rcs2*cdotu + 0.5*rcs2*rcs2*sdotq); + f = lb->model.wv[p]*rho*(1.0 + rcs2*cdotu + 0.5*rcs2*rcs2*sdotq); lb_f_set(wall->lb, index, p, 0, f); } /* Next site */ diff --git a/tests/unit/test_build.c b/tests/unit/test_build.c index e3508903e..99b0f5ca5 100644 --- a/tests/unit/test_build.c +++ b/tests/unit/test_build.c @@ -26,9 +26,12 @@ #include "build.h" #include "tests.h" -static int test_build_links_model_c1(pe_t * pe, cs_t * cs, double a0, double r0[3]); -static int test_build_links_model_c2(pe_t * pe, cs_t * cs, double a0, double r0[3]); -static int test_build_rebuild_c1(pe_t * pe, cs_t * cs, double a0, double r0[3]); +static int test_build_links_model_c1(pe_t * pe, cs_t * cs, int nvel, + double a0, double r0[3]); +static int test_build_links_model_c2(pe_t * pe, cs_t * cs, int nvel, + double a0, double r0[3]); +static int test_build_rebuild_c1(pe_t * pe, cs_t * cs, int nvel, + double a0, double r0[3]); /***************************************************************************** * @@ -38,6 +41,7 @@ static int test_build_rebuild_c1(pe_t * pe, cs_t * cs, double a0, double r0[3]); int test_build_suite(void) { + int nvel = NVEL; double a0; double r0[3]; double delta = 1.0; /* A small lattice offset */ @@ -56,21 +60,21 @@ int test_build_suite(void) { a0 = 2.3; r0[X] = 0.5*ltot[X]; r0[Y] = 0.5*ltot[Y]; r0[Z] = 0.5*ltot[Z]; - test_build_links_model_c1(pe, cs, a0, r0); - test_build_links_model_c2(pe, cs, a0, r0); - test_build_rebuild_c1(pe, cs, a0, r0); + test_build_links_model_c1(pe, cs, nvel, a0, r0); + test_build_links_model_c2(pe, cs, nvel, a0, r0); + test_build_rebuild_c1(pe, cs, nvel, a0, r0); a0 = 4.77; r0[X] = lmin[X] + delta; r0[Y] = 0.5*ltot[Y]; r0[Z] = 0.5*ltot[Z]; - test_build_links_model_c1(pe, cs, a0, r0); - test_build_links_model_c2(pe, cs, a0, r0); - test_build_rebuild_c1(pe, cs, a0, r0); + test_build_links_model_c1(pe, cs, nvel, a0, r0); + test_build_links_model_c2(pe, cs, nvel, a0, r0); + test_build_rebuild_c1(pe, cs, nvel, a0, r0); a0 = 3.84; r0[X] = ltot[X]; r0[Y] = ltot[Y]; r0[Z] = ltot[Z]; - test_build_links_model_c1(pe, cs, a0, r0); - test_build_links_model_c2(pe, cs, a0, r0); - test_build_rebuild_c1(pe, cs, a0, r0); + test_build_links_model_c1(pe, cs, nvel, a0, r0); + test_build_links_model_c2(pe, cs, nvel, a0, r0); + test_build_rebuild_c1(pe, cs, nvel, a0, r0); /* Some known cases: place the colloid in the centre and test only * in serial, as there is no quick way to compute in parallel. */ @@ -99,12 +103,14 @@ int test_build_suite(void) { * *****************************************************************************/ -static int test_build_links_model_c1(pe_t * pe, cs_t * cs, double a0, double r0[3]) { +static int test_build_links_model_c1(pe_t * pe, cs_t * cs, int nvel, + double a0, double r0[3]) { int ncolloid; int ncell[3] = {2, 2, 2}; map_t * map = NULL; + lb_model_t model = {}; colloid_t * pc = NULL; colloids_info_t * cinfo = NULL; @@ -114,6 +120,7 @@ static int test_build_links_model_c1(pe_t * pe, cs_t * cs, double a0, double r0[ colloids_info_create(pe, cs, ncell, &cinfo); colloids_info_map_init(cinfo); map_create(pe, cs, 0, &map); + lb_model_create(nvel, &model); /* Place the single colloid and construct the links */ @@ -123,7 +130,7 @@ static int test_build_links_model_c1(pe_t * pe, cs_t * cs, double a0, double r0[ colloids_halo_state(cinfo); build_update_map(cs, cinfo, map); - build_update_links(cs, cinfo, NULL, map); + build_update_links(cs, cinfo, NULL, map, &model); colloid_sums_halo(cinfo, COLLOID_SUM_STRUCTURE); colloids_info_ntotal(cinfo, &ncolloid); @@ -145,6 +152,7 @@ static int test_build_links_model_c1(pe_t * pe, cs_t * cs, double a0, double r0[ assert(fabs(pc->deltam - 0.0) < DBL_EPSILON); } + lb_model_free(&model); map_free(map); colloids_info_free(cinfo); @@ -157,13 +165,15 @@ static int test_build_links_model_c1(pe_t * pe, cs_t * cs, double a0, double r0[ * *****************************************************************************/ -static int test_build_links_model_c2(pe_t * pe, cs_t * cs, double a0, double r0[3]) { +static int test_build_links_model_c2(pe_t * pe, cs_t * cs, int nvel, + double a0, double r0[3]) { int ic, jc, kc; int ncolloid; int ncell[3] = {4, 4, 4}; map_t * map = NULL; + lb_model_t model = {}; colloid_t * pc = NULL; colloids_info_t * cinfo = NULL; @@ -173,6 +183,7 @@ static int test_build_links_model_c2(pe_t * pe, cs_t * cs, double a0, double r0[ colloids_info_create(pe, cs, ncell, &cinfo); colloids_info_map_init(cinfo); map_create(pe, cs, 0, &map); + lb_model_create(nvel, &model); /* Place the single colloid and construct the links */ @@ -182,7 +193,7 @@ static int test_build_links_model_c2(pe_t * pe, cs_t * cs, double a0, double r0[ colloids_halo_state(cinfo); build_update_map(cs, cinfo, map); - build_update_links(cs, cinfo, NULL, map); + build_update_links(cs, cinfo, NULL, map, &model); colloid_sums_halo(cinfo, COLLOID_SUM_STRUCTURE); colloids_info_ntotal(cinfo, &ncolloid); @@ -214,6 +225,7 @@ static int test_build_links_model_c2(pe_t * pe, cs_t * cs, double a0, double r0[ } } + lb_model_free(&model); map_free(map); colloids_info_free(cinfo); @@ -226,13 +238,15 @@ static int test_build_links_model_c2(pe_t * pe, cs_t * cs, double a0, double r0[ * *****************************************************************************/ -static int test_build_rebuild_c1(pe_t * pe, cs_t * cs, double a0, double r0[3]) { +static int test_build_rebuild_c1(pe_t * pe, cs_t * cs, int nvel, + double a0, double r0[3]) { int ic, jc, kc; int ncolloid; int ncell[3] = {2, 2, 2}; map_t * map = NULL; + lb_model_t model = {}; colloid_t * pc = NULL; colloids_info_t * cinfo = NULL; @@ -242,6 +256,7 @@ static int test_build_rebuild_c1(pe_t * pe, cs_t * cs, double a0, double r0[3]) colloids_info_create(pe, cs, ncell, &cinfo); colloids_info_map_init(cinfo); map_create(pe, cs, 0, &map); + lb_model_create(nvel, &model); /* Place the single colloid and construct the links */ @@ -258,7 +273,7 @@ static int test_build_rebuild_c1(pe_t * pe, cs_t * cs, double a0, double r0[3]) colloids_halo_state(cinfo); build_update_map(cs, cinfo, map); - build_update_links(cs, cinfo, NULL, map); + build_update_links(cs, cinfo, NULL, map, &model); colloids_info_ntotal(cinfo, &ncolloid); assert(ncolloid == 1); @@ -270,7 +285,7 @@ static int test_build_rebuild_c1(pe_t * pe, cs_t * cs, double a0, double r0[3]) colloids_halo_state(cinfo); build_update_map(cs, cinfo, map); - build_update_links(cs, cinfo, NULL, map); + build_update_links(cs, cinfo, NULL, map, &model); colloid_sums_halo(cinfo, COLLOID_SUM_STRUCTURE); for (ic = 0; ic <= ncell[X] + 1; ic++) { @@ -297,6 +312,7 @@ static int test_build_rebuild_c1(pe_t * pe, cs_t * cs, double a0, double r0[3]) } } + lb_model_free(&model); map_free(map); colloids_info_free(cinfo); diff --git a/tests/unit/test_halo.c b/tests/unit/test_halo.c index 594e7f3b3..dc9042a7c 100644 --- a/tests/unit/test_halo.c +++ b/tests/unit/test_halo.c @@ -71,6 +71,7 @@ int test_halo_suite(void) { int do_test_const_blocks(void) { +#ifdef TEST_TO_BE_REMOVED_WITH_GLOBAL_SYMBOLS int i, k; for (i = 0; i < CVXBLOCK; i++) { @@ -93,7 +94,7 @@ int do_test_const_blocks(void) { test_assert(cv[zdisp_bwd_cv[i] + k][Z] == -1); } } - +#endif return 0; } @@ -143,7 +144,7 @@ int do_test_halo_null(pe_t * pe, cs_t * cs, lb_halo_enum_t halo) { index = cs_index(cs, n[X], n[Y], n[Z]); for (nd = 0; nd < ndist; nd++) { - for (p = 0; p < NVEL; p++) { + for (p = 0; p < lb->model.nvel; p++) { lb_f_set(lb, index, p, nd, 1.0); } } @@ -161,7 +162,7 @@ int do_test_halo_null(pe_t * pe, cs_t * cs, lb_halo_enum_t halo) { index = cs_index(cs, n[X], n[Y], n[Z]); for (nd = 0; nd < ndist; nd++) { - for (p = 0; p < NVEL; p++) { + for (p = 0; p < lb->model.nvel; p++) { lb_f_set(lb, index, p, nd, 0.0); } } @@ -183,7 +184,7 @@ int do_test_halo_null(pe_t * pe, cs_t * cs, lb_halo_enum_t halo) { index = cs_index(cs, n[X], n[Y], n[Z]); for (nd = 0; nd < ndist; nd++) { - for (p = 0; p < NVEL; p++) { + for (p = 0; p < lb->model.nvel; p++) { lb_f(lb, index, p, nd, &f_actual); /* everything should still be zero inside the lattice */ @@ -255,7 +256,7 @@ int do_test_halo(pe_t * pe, cs_t * cs, int dim, lb_halo_enum_t halo) { index = cs_index(cs, n[X], n[Y], n[Z]); for (nd = 0; nd < ndist; nd++) { - for (p = 0; p < NVEL; p++) { + for (p = 0; p < lb->model.nvel; p++) { lb_f_set(lb, index, p, nd, -1.0); } } @@ -278,7 +279,7 @@ int do_test_halo(pe_t * pe, cs_t * cs, int dim, lb_halo_enum_t halo) { n[Z] <= nhalo || n[Z] > nlocal[Z] - nhalo) { for (nd = 0; nd < ndist; nd++) { - for (p = 0; p < NVEL; p++) { + for (p = 0; p < lb->model.nvel; p++) { lb_f_set(lb, index, p, nd, 1.0*(offset[dim] + n[dim])); } } @@ -314,7 +315,7 @@ int do_test_halo(pe_t * pe, cs_t * cs, int dim, lb_halo_enum_t halo) { f_expect = offset[dim]; if (mpi_cartcoords[dim] == 0) f_expect = ltot[dim]; - for (p = 0; p < NVEL; p++) { + for (p = 0; p < lb->model.nvel; p++) { lb_f(lb, index, p, nd, &f_actual); test_assert(fabs(f_actual-f_expect) < DBL_EPSILON); } @@ -326,7 +327,7 @@ int do_test_halo(pe_t * pe, cs_t * cs, int dim, lb_halo_enum_t halo) { f_expect = offset[dim] + nlocal[dim] + 1.0; if (mpi_cartcoords[dim] == mpi_cartsz[dim] - 1) f_expect = 1.0; - for (p = 0; p < NVEL; p++) { + for (p = 0; p < lb->model.nvel; p++) { lb_f(lb, index, p, nd, &f_actual); test_assert(fabs(f_actual-f_expect) < DBL_EPSILON); } diff --git a/tests/unit/test_model.c b/tests/unit/test_model.c index 91b2713b1..3a03dd174 100644 --- a/tests/unit/test_model.c +++ b/tests/unit/test_model.c @@ -80,6 +80,7 @@ int test_model_suite(void) { static void test_model_constants(void) { +#ifdef TEST_TO_BE_REMOVED_WITH_GLOBAL_SYMBOLS int i, k, p; for (i = 0; i < CVXBLOCK; i++) { @@ -114,7 +115,7 @@ static void test_model_constants(void) { test_assert(cv[p][Z] == -1); } } - +#endif return; } @@ -129,45 +130,8 @@ static void test_model_constants(void) { static void test_model_velocity_set(void) { - int i, j, k, p; - double sum; - - LB_CS2_DOUBLE(cs2); - LB_RCS2_DOUBLE(rcs2); - KRONECKER_DELTA_CHAR(d_); - test_assert(NHYDRO == (1 + NDIM + NDIM*(NDIM+1)/2)); - /* Speed of sound */ - - test_assert(fabs(rcs2 - 3.0) < TEST_DOUBLE_TOLERANCE); - - /* Checking wv[p]*q_[p][i][j]... */ - - for (i = 0; i < NDIM; i++) { - for (j = 0; j < NDIM; j++) { - sum = 0.0; - for (p = 0; p < NVEL; p++) { - sum += wv[p]*(cv[p][i]*cv[p][j] - cs2*d_[i][j]); - } - test_assert(fabs(sum - 0.0) < TEST_DOUBLE_TOLERANCE); - } - } - - /* Checking wv[p]*cv[p][i]*q_[p][j][k]... */ - - for (i = 0; i < NDIM; i++) { - for (j = 0; j < NDIM; j++) { - for (k = 0; k < NDIM; k++) { - sum = 0.0; - for (p = 0; p < NVEL; p++) { - sum += wv[p]*cv[p][i]*(cv[p][i]*cv[p][j] - cs2*d_[i][j]); - } - test_assert(fabs(sum - 0.0) < TEST_DOUBLE_TOLERANCE); - } - } - } - return; } @@ -208,8 +172,8 @@ int do_test_model_distributions(pe_t * pe, cs_t * cs) { assert(n == ndist); for (n = 0; n < ndist; n++) { - for (p = 0; p < NVEL; p++) { - fvalue_expected = 0.01*n + wv[p]; + for (p = 0; p < lb->model.nvel; p++) { + fvalue_expected = 0.01*n + lb->model.wv[p]; lb_f_set(lb, index, p, n, fvalue_expected); lb_f(lb, index, p, n, &fvalue); assert(fabs(fvalue - fvalue_expected) < DBL_EPSILON); @@ -217,7 +181,7 @@ int do_test_model_distributions(pe_t * pe, cs_t * cs) { /* Check zeroth moment... */ - fvalue_expected = 0.01*n*NVEL + 1.0; + fvalue_expected = 0.01*n*lb->model.nvel + 1.0; lb_0th_moment(lb, index, (lb_dist_enum_t) n, &fvalue); assert(fabs(fvalue - fvalue_expected) <= DBL_EPSILON); @@ -225,7 +189,7 @@ int do_test_model_distributions(pe_t * pe, cs_t * cs) { lb_1st_moment(lb, index, (n == 0) ? LB_RHO : LB_PHI, u); - for (i = 0; i < NDIM; i++) { + for (i = 0; i < lb->model.ndim; i++) { assert(fabs(u[i] - 0.0) < DBL_EPSILON); } } @@ -282,7 +246,7 @@ int do_test_model_halo_swap(pe_t * pe, cs_t * cs) { lb_f_set(lb, index, Y, n, (double) (j)); lb_f_set(lb, index, Z, n, (double) (k)); - for (p = 3; p < NVEL; p++) { + for (p = 3; p < lb->model.nvel; p++) { lb_f_set(lb, index, p, n, (double) p); } } @@ -319,7 +283,7 @@ int do_test_model_halo_swap(pe_t * pe, cs_t * cs) { lb_f(lb, index, Z, n, &f_actual); test_assert(fabs(f_actual - f_expect) < DBL_EPSILON); - for (p = 3; p < NVEL; p++) { + for (p = 3; p < lb->model.nvel; p++) { lb_f(lb, index, p, n, &f_actual); f_expect = (double) p; test_assert(fabs(f_actual - f_expect) < DBL_EPSILON); @@ -371,8 +335,8 @@ int do_test_model_reduced_halo_swap(pe_t * pe, cs_t * cs) { for (k = 1; k <= nlocal[Z]; k++) { index = cs_index(cs, i, j, k); for (n = 0; n < ndist; n++) { - for (p = 0; p < NVEL; p++) { - f_expect = 1.0*(n*NVEL + p); + for (p = 0; p < lb->model.nvel; p++) { + f_expect = 1.0*(n*lb->model.nvel + p); lb_f_set(lb, index, p, n, f_expect); } } @@ -389,9 +353,9 @@ int do_test_model_reduced_halo_swap(pe_t * pe, cs_t * cs) { for (k = 1; k <= nlocal[Z]; k++) { index = cs_index(cs, i, j, k); for (n = 0; n < ndist; n++) { - for (p = 0; p < NVEL; p++) { + for (p = 0; p < lb->model.nvel; p++) { lb_f(lb, index, p, n, &f_actual); - f_expect = 1.0*(n*NVEL + p); + f_expect = 1.0*(n*lb->model.nvel + p); test_assert(fabs(f_expect - f_actual) < DBL_EPSILON); } } @@ -413,14 +377,14 @@ int do_test_model_reduced_halo_swap(pe_t * pe, cs_t * cs) { index = cs_index(cs, i, j, k); for (n = 0; n < ndist; n++) { - for (p = 0; p < NVEL; p++) { + for (p = 0; p < lb->model.nvel; p++) { lb_f(lb, index, p, n, &f_actual); - f_expect = 1.0*(n*NVEL + p); + f_expect = 1.0*(n*lb->model.nvel + p); - icdt = i + cv[p][X]; - jcdt = j + cv[p][Y]; - kcdt = k + cv[p][Z]; + icdt = i + lb->model.cv[p][X]; + jcdt = j + lb->model.cv[p][Y]; + kcdt = k + lb->model.cv[p][Z]; if (test_model_is_domain(cs, icdt, jcdt, kcdt)) { test_assert(fabs(f_actual - f_expect) < DBL_EPSILON); diff --git a/tests/unit/test_wall.c b/tests/unit/test_wall.c index ba0d563fe..67b5282fd 100644 --- a/tests/unit/test_wall.c +++ b/tests/unit/test_wall.c @@ -9,7 +9,7 @@ * Edinburgh Soft Matter and Statistical Physics Group and * Edinburgh Parallel Computing Centre * - * (c) 2020 The University of Edinburgh + * (c) 2020-2021 The University of Edinburgh * * Contributing authors: * Kevin Stratford (kevin@epcc.ed.ac.uk) @@ -61,8 +61,8 @@ __host__ int test_wall_suite(void) { test_wall_link_normal(pe, cs); test_wall_link_slip_direction(pe, cs); test_wall_link_slip(pe, cs); - test_wall_commit1(pe, cs); + test_wall_commit1(pe, cs); test_wall_commit2(pe, cs); pe_info(pe, "PASS ./unit/test_wall\n"); @@ -163,6 +163,7 @@ __host__ int test_wall_slip(void) { __host__ int test_wall_link_normal(pe_t * pe, cs_t * cs) { + lb_t * lb = NULL; map_t * map = NULL; wall_t * wall = NULL; wall_param_t param = {0}; @@ -170,8 +171,11 @@ __host__ int test_wall_link_normal(pe_t * pe, cs_t * cs) { assert(pe); assert(cs); + lb_create(pe, cs, &lb); + lb_init(lb); + map_create(pe, cs, 1, &map); - wall_create(pe, cs, map, NULL, &wall); + wall_create(pe, cs, map, lb, &wall); /* This will probe all possible normal directions for the model */ param.iswall = 1; @@ -187,26 +191,28 @@ __host__ int test_wall_link_normal(pe_t * pe, cs_t * cs) { int modcv; wall_link_normal(wall, n, wn); - modcv = cv[p][X]*cv[p][X] + cv[p][Y]*cv[p][Y] + cv[p][Z]*cv[p][Z]; + modcv = lb->model.cv[p][X]*lb->model.cv[p][X] + + lb->model.cv[p][Y]*lb->model.cv[p][Y] + + lb->model.cv[p][Z]*lb->model.cv[p][Z]; switch (modcv) { case 1: /* A link with |cv| = 1 is always normal to the face */ - assert(wn[X] == -cv[p][X]); - assert(wn[Y] == -cv[p][Y]); - assert(wn[Z] == -cv[p][Z]); + assert(wn[X] == -lb->model.cv[p][X]); + assert(wn[Y] == -lb->model.cv[p][Y]); + assert(wn[Z] == -lb->model.cv[p][Z]); break; case 2: /* A link with |cv| = 2 may be face or edge */ - if (wn[X] != 0) assert(wn[X] == -cv[p][X]); - if (wn[Y] != 0) assert(wn[Y] == -cv[p][Y]); - if (wn[Z] != 0) assert(wn[Z] == -cv[p][Z]); + if (wn[X] != 0) assert(wn[X] == -lb->model.cv[p][X]); + if (wn[Y] != 0) assert(wn[Y] == -lb->model.cv[p][Y]); + if (wn[Z] != 0) assert(wn[Z] == -lb->model.cv[p][Z]); break; case 3: /* A link with |cv| = 3 may be face, edge, or corner */ - if (wn[X] != 0) assert(wn[X] == -cv[p][X]); - if (wn[Y] != 0) assert(wn[Y] == -cv[p][Y]); - if (wn[Z] != 0) assert(wn[Z] == -cv[p][Z]); + if (wn[X] != 0) assert(wn[X] == -lb->model.cv[p][X]); + if (wn[Y] != 0) assert(wn[Y] == -lb->model.cv[p][Y]); + if (wn[Z] != 0) assert(wn[Z] == -lb->model.cv[p][Z]); break; default: assert(0); @@ -215,6 +221,7 @@ __host__ int test_wall_link_normal(pe_t * pe, cs_t * cs) { wall_free(wall); map_free(map); + lb_free(lb); return 0; } @@ -227,6 +234,7 @@ __host__ int test_wall_link_normal(pe_t * pe, cs_t * cs) { __host__ int test_wall_link_slip_direction(pe_t * pe, cs_t * cs) { + lb_t * lb = NULL; map_t * map = NULL; wall_t * wall = NULL; wall_param_t param = {0}; @@ -234,8 +242,11 @@ __host__ int test_wall_link_slip_direction(pe_t * pe, cs_t * cs) { assert(pe); assert(cs); + lb_create(pe, cs, &lb); + lb_init(lb); + map_create(pe, cs, 1, &map); - wall_create(pe, cs, map, NULL, &wall); + wall_create(pe, cs, map, lb, &wall); /* This will probe all possible normal directions for the model */ param.iswall = 1; @@ -251,18 +262,18 @@ __host__ int test_wall_link_slip_direction(pe_t * pe, cs_t * cs) { int wn[3] = {0}; q = wall_link_slip_direction(wall, n); - assert(0 < q && q < NVEL); + assert(0 < q && q < lb->model.nvel); /* This test is slightly circular, but at least consistent... */ wall_link_normal(wall, n, wn); - assert((cv[p][X] + cv[q][X]) == -2*wn[X]); - assert((cv[p][Y] + cv[q][Y]) == -2*wn[Y]); - assert((cv[p][Z] + cv[q][Z]) == -2*wn[Z]); + assert((lb->model.cv[p][X] + lb->model.cv[q][X]) == -2*wn[X]); + assert((lb->model.cv[p][Y] + lb->model.cv[q][Y]) == -2*wn[Y]); + assert((lb->model.cv[p][Z] + lb->model.cv[q][Z]) == -2*wn[Z]); - wn[X] += (cv[p][X] + cv[q][X])/2; - wn[Y] += (cv[p][Y] + cv[q][Y])/2; - wn[Z] += (cv[p][Z] + cv[q][Z])/2; + wn[X] += (lb->model.cv[p][X] + lb->model.cv[q][X])/2; + wn[Y] += (lb->model.cv[p][Y] + lb->model.cv[q][Y])/2; + wn[Z] += (lb->model.cv[p][Z] + lb->model.cv[q][Z])/2; assert(wn[X] == 0); assert(wn[Y] == 0); assert(wn[Z] == 0); @@ -270,6 +281,7 @@ __host__ int test_wall_link_slip_direction(pe_t * pe, cs_t * cs) { wall_free(wall); map_free(map); + lb_free(lb); return 0; } @@ -282,6 +294,7 @@ __host__ int test_wall_link_slip_direction(pe_t * pe, cs_t * cs) { __host__ int test_wall_link_slip(pe_t * pe, cs_t * cs) { + lb_t * lb = NULL; map_t * map = NULL; wall_t * wall = NULL; wall_param_t param = {0}; @@ -289,8 +302,11 @@ __host__ int test_wall_link_slip(pe_t * pe, cs_t * cs) { assert(pe); assert(cs); + lb_create(pe, cs, &lb); + lb_init(lb); + map_create(pe, cs, 1, &map); - wall_create(pe, cs, map, NULL, &wall); + wall_create(pe, cs, map, lb, &wall); /* This will probe all possible normal directions for the model */ param.iswall = 1; @@ -307,17 +323,18 @@ __host__ int test_wall_link_slip(pe_t * pe, cs_t * cs) { assert(WALL_NO_SLIP <= s && s < WALL_SLIP_MAX); /* Make sure these are at least consistent */ - if (s == WALL_SLIP_XBOT) assert(cv[p][X] == -1); - if (s == WALL_SLIP_XTOP) assert(cv[p][X] == +1); - if (s == WALL_SLIP_YBOT) assert(cv[p][Y] == -1); - if (s == WALL_SLIP_YTOP) assert(cv[p][Y] == +1); - if (s == WALL_SLIP_ZBOT) assert(cv[p][Z] == -1); - if (s == WALL_SLIP_ZTOP) assert(cv[p][Z] == +1); + if (s == WALL_SLIP_XBOT) assert(lb->model.cv[p][X] == -1); + if (s == WALL_SLIP_XTOP) assert(lb->model.cv[p][X] == +1); + if (s == WALL_SLIP_YBOT) assert(lb->model.cv[p][Y] == -1); + if (s == WALL_SLIP_YTOP) assert(lb->model.cv[p][Y] == +1); + if (s == WALL_SLIP_ZBOT) assert(lb->model.cv[p][Z] == -1); + if (s == WALL_SLIP_ZTOP) assert(lb->model.cv[p][Z] == +1); if (p == 0) assert(0); } wall_free(wall); map_free(map); + lb_free(lb); return 0; } @@ -330,6 +347,7 @@ __host__ int test_wall_link_slip(pe_t * pe, cs_t * cs) { __host__ int test_wall_commit1(pe_t * pe, cs_t * cs) { + lb_t * lb = NULL; map_t * map = NULL; wall_t * wall = NULL; wall_param_t param = {0}; @@ -337,8 +355,11 @@ __host__ int test_wall_commit1(pe_t * pe, cs_t * cs) { assert(pe); assert(cs); + lb_create(pe, cs, &lb); + lb_init(lb); + map_create(pe, cs, 1, &map); - wall_create(pe, cs, map, NULL, &wall); + wall_create(pe, cs, map, lb, &wall); /* This will probe all possible normal directions for the model */ param.iswall = 1; @@ -360,6 +381,7 @@ __host__ int test_wall_commit1(pe_t * pe, cs_t * cs) { wall_free(wall); map_free(map); + lb_free(lb); return 0; } @@ -372,6 +394,7 @@ __host__ int test_wall_commit1(pe_t * pe, cs_t * cs) { __host__ int test_wall_commit2(pe_t * pe, cs_t * cs) { + lb_t * lb = NULL; map_t * map = NULL; wall_t * wall = NULL; wall_param_t param = {0}; @@ -379,8 +402,11 @@ __host__ int test_wall_commit2(pe_t * pe, cs_t * cs) { assert(pe); assert(cs); + lb_create(pe, cs, &lb); + lb_init(lb); + map_create(pe, cs, 1, &map); - wall_create(pe, cs, map, NULL, &wall); + wall_create(pe, cs, map, lb, &wall); /* This will probe all possible normal directions for the model */ param.iswall = 1; @@ -403,6 +429,7 @@ __host__ int test_wall_commit2(pe_t * pe, cs_t * cs) { wall_free(wall); map_free(map); + lb_free(lb); return 0; } From 72e15fc0d315593e2481bb9ef89b7b18721a0579 Mon Sep 17 00:00:00 2001 From: not populated Date: Tue, 14 Dec 2021 12:20:15 +0000 Subject: [PATCH 103/117] Watch sign of active stress --- src/lc_droplet.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/lc_droplet.c b/src/lc_droplet.c index a33a909f5..c978f0744 100644 --- a/src/lc_droplet.c +++ b/src/lc_droplet.c @@ -594,8 +594,16 @@ int fe_lc_droplet_str_symm(fe_lc_droplet_t * fe, int index, double sth[3][3]){ } } + /* Additional minus sign. */ + + for (ia = 0; ia < 3; ia++) { + for (ib = 0; ib < 3; ib++) { + sth[ia][ib] = -sth[ia][ib]; + } + } + - /* Put active stress here (even if zero) */ + /* Put active stress here (even if zero). No additional -ve sign. */ { double phi = 0.0; @@ -610,14 +618,6 @@ int fe_lc_droplet_str_symm(fe_lc_droplet_t * fe, int index, double sth[3][3]){ } } - /* Additional minus sign. */ - - for (ia = 0; ia < 3; ia++) { - for (ib = 0; ib < 3; ib++) { - sth[ia][ib] = -sth[ia][ib]; - } - } - return 0; } From fbdc92f754ea45ff8dd0d3e75b3a3277a340cd4f Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Fri, 17 Dec 2021 15:07:14 +0000 Subject: [PATCH 104/117] Add MPI_Init_thread; allow Isend, Irecv --- mpi_s/mpi.h | 8 ++++++++ mpi_s/mpi_serial.c | 47 +++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/mpi_s/mpi.h b/mpi_s/mpi.h index cbcf14417..1ac0425c9 100644 --- a/mpi_s/mpi.h +++ b/mpi_s/mpi.h @@ -107,6 +107,13 @@ enum reserved_communicators{MPI_COMM_WORLD, MPI_COMM_SELF}; #define MPI_IN_PLACE ((void *) 1) +/* Thread support level */ + +#define MPI_THREAD_SINGLE 1 +#define MPI_THREAD_FUNNELED 2 +#define MPI_THREAD_SERIALIZED 3 +#define MPI_THREAD_MULTIPLE 4 + /* Interface */ int MPI_Barrier(MPI_Comm comm); @@ -200,6 +207,7 @@ double MPI_Wtime(void); double MPI_Wtick(void); int MPI_Init(int * argc, char *** argv); +int MPI_Init_thread(int * argc, char *** argv, int required, int * provided); int MPI_Finalize(void); int MPI_Initialized(int * flag); int MPI_Abort(MPI_Comm comm, int errorcode); diff --git a/mpi_s/mpi_serial.c b/mpi_s/mpi_serial.c index d5344ba50..3758bc9d2 100644 --- a/mpi_s/mpi_serial.c +++ b/mpi_s/mpi_serial.c @@ -144,6 +144,29 @@ int MPI_Init(int * argc, char *** argv) { return MPI_SUCCESS; } +/***************************************************************************** + * + * MPI_Init_thread + * + *****************************************************************************/ + +int MPI_Init_thread(int * argc, char *** argv, int required, int * provided) { + + assert(argc); + assert(argv); + assert(MPI_THREAD_SINGLE <= required && required <= MPI_THREAD_MULTIPLE); + assert(provided); + + MPI_Init(argc, argv); + + /* We are going to say that MPI_THREAD_SERIALIZED is available */ + /* Not MPI_THREAD_MULTIPLE */ + + *provided = MPI_THREAD_SERIALIZED; + + return MPI_SUCCESS; +} + /***************************************************************************** * * MPI_Initialized @@ -309,8 +332,8 @@ int MPI_Irecv(void * buf, int count, MPI_Datatype datatype, int source, assert(buf); assert(request); - printf("MPI_Irecv should not be called in serial.\n"); - exit(0); + /* Could assert tag is ok */ + *request = tag; return MPI_SUCCESS; } @@ -345,8 +368,8 @@ int MPI_Isend(void * buf, int count, MPI_Datatype datatype, int dest, assert(buf); assert(request); - printf("MPI_Isend should not be called in serial\n"); - exit(0); + /* Could assert tag is ok */ + *request = tag; return MPI_SUCCESS; } @@ -394,12 +417,26 @@ int MPI_Waitall(int count, MPI_Request * requests, MPI_Status * statuses) { *****************************************************************************/ int MPI_Waitany(int count, MPI_Request requests[], int * index, - MPI_Status * statuses) { + MPI_Status * status) { assert(count >= 0); assert(requests); assert(index); + *index = MPI_UNDEFINED; + + for (int ireq = 0; ireq < count; ireq++) { + if (requests[ireq] != MPI_REQUEST_NULL) { + *index = ireq; + requests[ireq] = MPI_REQUEST_NULL; + if (status) { + status->MPI_SOURCE = 0; + status->MPI_TAG = requests[ireq]; + } + break; + } + } + return MPI_SUCCESS; } From 3c297d6ba198ade0186150e20386f86ceb53be67 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Fri, 17 Dec 2021 15:08:05 +0000 Subject: [PATCH 105/117] Correction for missing ndim --- src/lb_d3q27.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lb_d3q27.c b/src/lb_d3q27.c index cdd8bd775..907f0d0d0 100644 --- a/src/lb_d3q27.c +++ b/src/lb_d3q27.c @@ -34,6 +34,7 @@ int lb_d3q27_create(lb_model_t * model) { *model = (lb_model_t) {}; + model->ndim = 3; model->nvel = NVEL_D3Q27; model->cv = (int8_t (*)[3]) calloc(NVEL_D3Q27, sizeof(int8_t[3])); model->wv = (double *) calloc(NVEL_D3Q27, sizeof(double)); @@ -126,7 +127,7 @@ int lb_d3q27_create(lb_model_t * model) { * [18] H_iyyzz (c_iy c_iy - cs2)*(c_iz c_iz - cs2) * [19] H_izzxx ... * - * Four 4th order polynomials H_ixxyz, etc + * Three 4th order polynomials H_ixxyz, etc * [20] H_ixxyz (c_ix c_ix - cs2) c_iy c_iz * [21] H_iyyzx ... * [22] H_izzxy ... From e74d80947d07b2c63da8b89b7a83cd99d7b13081 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Fri, 17 Dec 2021 15:26:03 +0000 Subject: [PATCH 106/117] Remove global symbols --- src/d2q9.c | 3 --- src/d2q9.h | 3 --- src/d3q15.c | 2 -- src/d3q15.h | 3 --- src/d3q19.c | 4 ---- src/d3q19.h | 3 --- 6 files changed, 18 deletions(-) diff --git a/src/d2q9.c b/src/d2q9.c index 3997bfebe..afb79a7f9 100644 --- a/src/d2q9.c +++ b/src/d2q9.c @@ -68,9 +68,6 @@ const char * model_name_d2q9 = "D2Q9"; #define w1 (4.0/36.0) #define w2 (1.0/36.0) -LB_CV_D2Q9(cv); -LB_WEIGHTS_D2Q9(wv); - #define c0 0.0 #define c1 1.0 #define c2 2.0 diff --git a/src/d2q9.h b/src/d2q9.h index 9d7095193..a802bba42 100644 --- a/src/d2q9.h +++ b/src/d2q9.h @@ -26,9 +26,6 @@ enum {CVZBLOCK9 = 1}; #ifdef _D2Q9_ -extern const int8_t cv[NVEL9][3]; -extern const double wv[NVEL9]; - extern const int xblocklen_cv[CVXBLOCK9]; extern const int xdisp_fwd_cv[CVXBLOCK9]; extern const int xdisp_bwd_cv[CVXBLOCK9]; diff --git a/src/d3q15.c b/src/d3q15.c index ddde706fc..8fd9bd6f0 100644 --- a/src/d3q15.c +++ b/src/d3q15.c @@ -83,8 +83,6 @@ const char * model_name_d3q15 = "D3Q15"; #define wb ( 9.0/72.0) #define wc ( 4.0/72.0) -LB_CV_D3Q15(cv); -LB_WEIGHTS_D3Q15(wv); /* const double ma_[NVEL15][NVEL15] = {{ c1, c1, c1, c1, c1, c1, c1, c1, c1, c1, c1, c1, c1, c1, c1}, diff --git a/src/d3q15.h b/src/d3q15.h index 0eb8ae533..3121127ad 100644 --- a/src/d3q15.h +++ b/src/d3q15.h @@ -26,9 +26,6 @@ enum {CVZBLOCK15 = 5}; #ifdef _D3Q15_ -extern const int8_t cv[NVEL15][3]; -extern const double wv[NVEL15]; - extern const int xblocklen_cv[CVXBLOCK15]; extern const int xdisp_fwd_cv[CVXBLOCK15]; extern const int xdisp_bwd_cv[CVXBLOCK15]; diff --git a/src/d3q19.c b/src/d3q19.c index 50cda9b29..153fed780 100644 --- a/src/d3q19.c +++ b/src/d3q19.c @@ -74,8 +74,6 @@ const char * model_name_d3q19 = "D3Q19"; * *****************************************************************************/ -LB_CV_D3Q19(cv); - #define w0 (12.0/36.0) #define w1 (2.0/36.0) #define w2 (1.0/36.0) @@ -97,8 +95,6 @@ LB_CV_D3Q19(cv); #define wd ( 1.0/48.0) #define we ( 3.0/48.0) -LB_WEIGHTS_D3Q19(wv); - /* Global symbols are replaced by lb_model_t ... const double ma_[NVEL19][NVEL19] = { { c1, c1, c1, c1, c1, c1, c1, c1, c1, c1, c1, c1, c1, c1, c1, c1, c1, c1, c1}, diff --git a/src/d3q19.h b/src/d3q19.h index 913d5a130..b53e8a101 100644 --- a/src/d3q19.h +++ b/src/d3q19.h @@ -28,9 +28,6 @@ enum {CVZBLOCK19 = 5}; #ifdef _D3Q19_ -extern const int8_t cv[NVEL19][3]; -extern const double wv[NVEL19]; - extern const int xblocklen_cv[CVXBLOCK19]; extern const int xdisp_fwd_cv[CVXBLOCK19]; extern const int xdisp_bwd_cv[CVXBLOCK19]; From 3fb2090259c44f847f52a3b902348975faa36969 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Fri, 17 Dec 2021 15:26:34 +0000 Subject: [PATCH 107/117] Use explicit model --- src/stats_colloid_force_split.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/stats_colloid_force_split.c b/src/stats_colloid_force_split.c index 45a234f66..aad4aa4a4 100644 --- a/src/stats_colloid_force_split.c +++ b/src/stats_colloid_force_split.c @@ -235,9 +235,13 @@ int stat_diagnostic_write(colloid_diagnostic_t * array, int count, int colloid_force_from_pth(colloid_t * pc, pth_t * pth, double f[3]) { + lb_model_t model = {}; + assert(pc); assert(pth); + lb_model_create(NVEL, &model); + f[X] = 0.0; f[Y] = 0.0; f[Z] = 0.0; for (colloid_link_t * link = pc->lnk; link; link = link->next) { @@ -246,20 +250,24 @@ int colloid_force_from_pth(colloid_t * pc, pth_t * pth, double f[3]) { int id = -1; int p = link->p; - int cmod = cv[p][X]*cv[p][X] + cv[p][Y]*cv[p][Y] + cv[p][Z]*cv[p][Z]; + int cmod = model.cv[p][X]*model.cv[p][X] + + model.cv[p][Y]*model.cv[p][Y] + + model.cv[p][Z]*model.cv[p][Z]; if (cmod != 1) continue; - if (cv[p][X]) id = X; - if (cv[p][Y]) id = Y; - if (cv[p][Z]) id = Z; + if (model.cv[p][X]) id = X; + if (model.cv[p][Y]) id = Y; + if (model.cv[p][Z]) id = Z; for (int ia = 0; ia < 3; ia++) { - f[ia] += 1.0*cv[p][id] + f[ia] += 1.0*model.cv[p][id] *pth->str[addr_rank2(pth->nsites, 3, 3, link->i, ia, id)]; } } + lb_model_free(&model); + return 0; } From a47b264bd75dfc7e388fc887a9a6aa3a03a9d8ac Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Fri, 17 Dec 2021 15:27:06 +0000 Subject: [PATCH 108/117] Extra information added --- src/lb_model_s.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lb_model_s.h b/src/lb_model_s.h index 0b07785de..75cdd8e33 100644 --- a/src/lb_model_s.h +++ b/src/lb_model_s.h @@ -44,6 +44,8 @@ struct lb_collide_param_s { struct lb_data_s { + int ndim; + int nvel; int ndist; /* Number of distributions (default one) */ int nsite; /* Number of lattice sites (local) */ From 3e366008630652f2f529d5f21847aeea88b773af Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Fri, 17 Dec 2021 15:27:48 +0000 Subject: [PATCH 109/117] Temporary code for new halo swap --- tests/unit/test_model.c | 686 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 686 insertions(+) diff --git a/tests/unit/test_model.c b/tests/unit/test_model.c index 3a03dd174..a047cc344 100644 --- a/tests/unit/test_model.c +++ b/tests/unit/test_model.c @@ -22,6 +22,7 @@ #include "pe.h" #include "coords.h" #include "util.h" +#include "cs_limits.h" #include "lb_model_s.h" #include "tests.h" @@ -34,6 +35,688 @@ int do_test_model_reduced_halo_swap(pe_t * pe, cs_t * cs); int do_test_lb_model_io(pe_t * pe, cs_t * cs); static int test_model_is_domain(cs_t * cs, int ic, int jc, int kc); + + + + +typedef struct lb_data_options_s { + int ndim; + int nvel; + int ndist; +} lb_data_options_t; + + +/* Utility to return a unique value for global (ic,jc,kc,p) */ +/* This allows e.g., tests to check distribution values in parallel + * exchanges. */ + +/* (ic, jc, kc) are local indices */ +/* Result could be unsigned integer... */ + +#include + +int64_t lb_data_index(lb_t * lb, int ic, int jc, int kc, int p) { + + int64_t index = INT64_MIN; + int64_t nall[3] = {}; + int64_t nstr[3] = {}; + int64_t pstr = 0; + + int ntotal[3] = {}; + int offset[3] = {}; + int nhalo = 0; + + assert(lb); + assert(0 <= p && p < lb->model.nvel); + + cs_ntotal(lb->cs, ntotal); + cs_nlocal_offset(lb->cs, offset); + cs_nhalo(lb->cs, &nhalo); + + nall[X] = ntotal[X] + 2*nhalo; + nall[Y] = ntotal[Y] + 2*nhalo; + nall[Z] = ntotal[Z] + 2*nhalo; + nstr[Z] = 1; + nstr[Y] = nstr[Z]*nall[Z]; + nstr[X] = nstr[Y]*nall[Y]; + pstr = nstr[X]*nall[X]; + + { + int igl = offset[X] + ic; + int jgl = offset[Y] + jc; + int kgl = offset[Z] + kc; + + /* A periodic system */ + igl = igl % ntotal[X]; + jgl = jgl % ntotal[Y]; + kgl = kgl % ntotal[Z]; + if (igl < 1) igl = igl + ntotal[X]; + if (jgl < 1) jgl = jgl + ntotal[Y]; + if (kgl < 1) kgl = kgl + ntotal[Z]; + + assert(1 <= igl && igl <= ntotal[X]); + assert(1 <= jgl && jgl <= ntotal[Y]); + assert(1 <= kgl && kgl <= ntotal[Z]); + + index = pstr*p + nstr[X]*igl + nstr[Y]*jgl + nstr[Z]*kgl; + } + + return index; +} + +int lb_data_create(pe_t * pe, cs_t * cs, const lb_data_options_t * options, + lb_t ** lb); + +int lb_data_create(pe_t * pe, cs_t * cs, const lb_data_options_t * options, + lb_t ** lb) { + + lb_t * obj = NULL; + + assert(pe); + assert(cs); + assert(options); + assert(lb); + + obj = (lb_t *) calloc(1, sizeof(lb_t)); + assert(obj); + if (obj == NULL) pe_fatal(pe, "calloc(1, lb_t) failed\n"); + + /* Check options */ + + obj->pe = pe; + obj->cs = cs; + obj->ndim = options->ndim; + obj->nvel = options->nvel; + obj->ndist = options->ndist; + + lb_model_create(obj->nvel, &obj->model); + + /* Storage */ + + { + /* Allocate storage following cs specification */ + int nhalo = 1; + int nlocal[3] = {}; + cs_nhalo(cs, &nhalo); + cs_nlocal(cs, nlocal); + + { + int nx = nlocal[X] + 2*nhalo; + int ny = nlocal[Y] + 2*nhalo; + int nz = nlocal[Z] + 2*nhalo; + obj->nsite = nx*ny*nz; + } + { + size_t sz = sizeof(double)*obj->nsite*obj->nvel; + assert(sz > 0); /* Should not overflow in size_t I hope! */ + obj->f = (double *) mem_aligned_malloc(MEM_PAGESIZE, sz); + assert(obj->f); + if (obj->f == NULL) pe_fatal(pe, "malloc(lb->f) failed\n"); + } + } + + *lb = obj; + + return 0; +} + +int lb_data_free(lb_t * lb) { + + assert(lb); + + free(lb->f); + lb_model_free(&lb->model); + free(lb); + + return 0; +} + +/* We will not exceed 27 directions! Direction index 0, in keeping + * with the LB model definition, is (0,0,0) - so no communication. */ + +typedef struct lb_halo_s { + + MPI_Comm comm; /* coords: Cartesian communicator */ + int nbrrank[3][3][3]; /* coords: neighbour rank look-up */ + int nlocal[3]; /* coords: local domain size */ + + lb_model_t map; /* Communication map 2d or 3d */ + int tagbase; /* send/recv tag */ + int full; /* All velocities at each site required. */ + int count[27]; /* halo: item data count per direction */ + cs_limits_t slim[27]; /* halo: send data region (rectangular) */ + cs_limits_t rlim[27]; /* halo: recv data region (rectangular) */ + double * send[27]; /* halo: send buffer per direction */ + double * recv[27]; /* halo: recv buffer per direction */ + MPI_Request request[2*27]; /* halo: array of requests */ + +} lb_halo_t; + +/***************************************************************************** + * + * lb_halo_size + * + * Utility to compute a number of sites from cs_limits_t. + * + *****************************************************************************/ + +int cs_limits_size(cs_limits_t lim) { + + int szx = 1 + lim.imax - lim.imin; + int szy = 1 + lim.jmax - lim.jmin; + int szz = 1 + lim.kmax - lim.kmin; + + return szx*szy*szz; +} + +/***************************************************************************** + * + * lb_halo_enqueue_send + * + * Pack the send buffer. The ireq determines the direction of the + * communication. + * + *****************************************************************************/ + +int lb_halo_enqueue_send(const lb_t * lb, const lb_halo_t * h, int ireq) { + + assert(1 <= ireq && ireq < h->map.nvel); + assert(lb->ndist == 1); + + if (h->count[ireq] > 0) { + + int8_t mx = h->map.cv[ireq][X]; + int8_t my = h->map.cv[ireq][Y]; + int8_t mz = h->map.cv[ireq][Z]; + int8_t mm = mx*mx + my*my + mz*mz; + + int ib = 0; /* Buffer index */ + + assert(mm == 1 || mm == 2 || mm == 3); + + for (int ic = h->slim[ireq].imin; ic <= h->slim[ireq].imax; ic++) { + for (int jc = h->slim[ireq].jmin; jc <= h->slim[ireq].jmax; jc++) { + for (int kc = h->slim[ireq].kmin; kc <= h->slim[ireq].kmax; kc++) { + /* If full, we need p = 0 */ + for (int p = 0; p < lb->nvel; p++) { + int8_t px = lb->model.cv[p][X]; + int8_t py = lb->model.cv[p][Y]; + int8_t pz = lb->model.cv[p][Z]; + int dot = mx*px + my*py + mz*pz; + if (h->full || dot == mm) { + int index = cs_index(lb->cs, ic, jc, kc); + int laddr = LB_ADDR(lb->nsite, lb->ndist, lb->nvel, index, 0, p); + h->send[ireq][ib++] = lb->f[laddr]; + } + } + } + } + } + assert(ib == h->count[ireq]*cs_limits_size(h->slim[ireq])); + } + + return 0; +} + +/***************************************************************************** + * + * lb_halo_dequeue_recv + * + * Unpack the recv buffer into place in the distributions. + * + *****************************************************************************/ + +int lb_halo_dequeue_recv(lb_t * lb, const lb_halo_t * h, int ireq) { + + assert(lb); + assert(h); + assert(0 < ireq && ireq < h->map.nvel); + assert(lb->ndist == 1); + + if (h->count[ireq] > 0) { + + /* The communication direction is reversed cf. the send... */ + int8_t mx = h->map.cv[h->map.nvel-ireq][X]; + int8_t my = h->map.cv[h->map.nvel-ireq][Y]; + int8_t mz = h->map.cv[h->map.nvel-ireq][Z]; + int8_t mm = mx*mx + my*my + mz*mz; + + int ib = 0; /* Buffer index */ + double * recv = h->recv[ireq]; + + { + int i = 1 + mx; + int j = 1 + my; + int k = 1 + mz; + /* If Cartesian neighbour is self, just copy out of send buffer. */ + if (h->nbrrank[i][j][k] == h->nbrrank[1][1][1]) recv = h->send[ireq]; + } + + assert(mm == 1 || mm == 2 || mm == 3); + + for (int ic = h->rlim[ireq].imin; ic <= h->rlim[ireq].imax; ic++) { + for (int jc = h->rlim[ireq].jmin; jc <= h->rlim[ireq].jmax; jc++) { + for (int kc = h->rlim[ireq].kmin; kc <= h->rlim[ireq].kmax; kc++) { + for (int p = 0; p < lb->nvel; p++) { + /* For reduced swap, we must have -cv[p] here... */ + int8_t px = lb->model.cv[lb->nvel-p][X]; + int8_t py = lb->model.cv[lb->nvel-p][Y]; + int8_t pz = lb->model.cv[lb->nvel-p][Z]; + int dot = mx*px + my*py + mz*pz; + if (h->full || dot == mm) { + int index = cs_index(lb->cs, ic, jc, kc); + int laddr = LB_ADDR(lb->nsite, lb->ndist, lb->nvel, index, 0, p); + lb->f[laddr] = recv[ib++]; + } + } + } + } + } + assert(ib == h->count[ireq]*cs_limits_size(h->rlim[ireq])); + } + + return 0; +} + +/***************************************************************************** + * + * lb_halo_create + * + * Currently: generate all send and receive requests. + * + *****************************************************************************/ + +int lb_halo_create(const lb_t * lb, lb_halo_t * h, int full) { + + lb_halo_t hnull = {}; + + assert(lb); + assert(h); + + *h = hnull; + + /* Communication model */ + if (lb->model.ndim == 2) lb_model_create( 9, &h->map); + if (lb->model.ndim == 3) lb_model_create(27, &h->map); + + assert(h->map.ndim == lb->model.ndim); + + cs_nlocal(lb->cs, h->nlocal); + cs_cart_comm(lb->cs, &h->comm); + h->tagbase = 211216; + h->full = full; + + /* Determine look-up table of ranks of neighbouring processes */ + { + int dims[3]; + int periods[3]; + int coords[3]; + + MPI_Cart_get(h->comm, h->map.ndim, dims, periods, coords); + + for (int p = 0; p < h->map.nvel; p++) { + int nbr[3] = {}; + int out[3] = {}; /* Out-of-range is erroneous for non-perioidic dims */ + int i = 1 + h->map.cv[p][X]; + int j = 1 + h->map.cv[p][Y]; + int k = 1 + h->map.cv[p][Z]; + + nbr[X] = coords[X] + h->map.cv[p][X]; + nbr[Y] = coords[Y] + h->map.cv[p][Y]; + nbr[Z] = coords[Z] + h->map.cv[p][Z]; + out[X] = (!periods[X] && (nbr[X] < 0 || nbr[X] > dims[X])); + out[Y] = (!periods[Y] && (nbr[Y] < 0 || nbr[Y] > dims[Y])); + out[Z] = (!periods[Z] && (nbr[Z] < 0 || nbr[Z] > dims[Z])); + + if (out[X] || out[Y] || out[Z]) { + h->nbrrank[i][j][k] = MPI_PROC_NULL; + } + else { + MPI_Cart_rank(h->comm, nbr, &h->nbrrank[i][j][k]); + } + } + /* I must be in the middle */ + assert(h->nbrrank[1][1][1] == cs_cart_rank(lb->cs)); + } + + + /* Limits of the halo regions in each communication direction */ + + for (int p = 1; p < h->map.nvel; p++) { + + /* Limits for send and recv regions*/ + int8_t cx = h->map.cv[p][X]; + int8_t cy = h->map.cv[p][Y]; + int8_t cz = h->map.cv[p][Z]; + + cs_limits_t send = {1, h->nlocal[X], 1, h->nlocal[Y], 1, h->nlocal[Z]}; + cs_limits_t recv = {1, h->nlocal[X], 1, h->nlocal[Y], 1, h->nlocal[Z]}; + + if (cx == -1) send.imax = 1; + if (cx == +1) send.imin = send.imax; + if (cy == -1) send.jmax = 1; + if (cy == +1) send.jmin = send.jmax; + if (cz == -1) send.kmax = 1; + if (cz == +1) send.kmin = send.kmax; + + /* velocity is reversed... */ + if (cx == +1) recv.imax = recv.imin = 0; + if (cx == -1) recv.imin = recv.imax = recv.imax + 1; + if (cy == +1) recv.jmax = recv.jmin = 0; + if (cy == -1) recv.jmin = recv.jmax = recv.jmax + 1; + if (cz == +1) recv.kmax = recv.kmin = 0; + if (cz == -1) recv.kmin = recv.kmax = recv.kmax + 1; + + h->slim[p] = send; + h->rlim[p] = recv; + } + + /* Message count (velocities) for each communication direction */ + + for (int p = 1; p < h->map.nvel; p++) { + + int count = 0; + + if (h->full) { + count = lb->model.nvel; + } + else { + int8_t mx = h->map.cv[p][X]; + int8_t my = h->map.cv[p][Y]; + int8_t mz = h->map.cv[p][Z]; + int8_t mm = mx*mx + my*my + mz*mz; + + /* Consider each model velocity in turn */ + for (int q = 1; q < lb->model.nvel; q++) { + int8_t qx = lb->model.cv[q][X]; + int8_t qy = lb->model.cv[q][Y]; + int8_t qz = lb->model.cv[q][Z]; + int8_t dot = mx*qx + my*qy + mz*qz; + + if (mm == 3 && dot == mm) count +=1; /* This is a corner */ + if (mm == 2 && dot == mm) count +=1; /* This is an edge */ + if (mm == 1 && dot == mm) count +=1; /* This is a side */ + } + } + + h->count[p] = count; + /* Allocate send buffer for send region */ + if (count > 0) { + int scount = count*cs_limits_size(h->slim[p]); + h->send[p] = (double *) malloc(scount*sizeof(double)); + assert(h->send[p]); + } + /* Allocate recv buffer */ + if (count > 0) { + int rcount = count*cs_limits_size(h->rlim[p]); + h->recv[p] = (double *) malloc(rcount*sizeof(double)); + assert(h->recv[p]); + } + } + + /* Post recvs (from opposite direction cf send) */ + + for (int ireq = 0; ireq < h->map.nvel; ireq++) { + + h->request[ireq] = MPI_REQUEST_NULL; + + if (h->count[ireq] > 0) { + int i = 1 + h->map.cv[h->map.nvel-ireq][X]; + int j = 1 + h->map.cv[h->map.nvel-ireq][Y]; + int k = 1 + h->map.cv[h->map.nvel-ireq][Z]; + int mcount = h->count[ireq]*cs_limits_size(h->rlim[ireq]); + + if (h->nbrrank[i][j][k] == h->nbrrank[1][1][1]) mcount = 0; + + MPI_Irecv(h->recv[ireq], mcount, MPI_DOUBLE, h->nbrrank[i][j][k], + h->tagbase + ireq, h->comm, h->request + ireq); + } + } + + /* Enqueue sends (upper half of request array) */ + + #pragma omp parallel for schedule(dynamic, 1) + for (int ireq = 0; ireq < h->map.nvel; ireq++) { + + h->request[27+ireq] = MPI_REQUEST_NULL; + + if (h->count[ireq] > 0) { + int i = 1 + h->map.cv[ireq][X]; + int j = 1 + h->map.cv[ireq][Y]; + int k = 1 + h->map.cv[ireq][Z]; + int mcount = h->count[ireq]*cs_limits_size(h->slim[ireq]); + + lb_halo_enqueue_send(lb, h, ireq); + + /* Short circuit messages to self. */ + if (h->nbrrank[i][j][k] == h->nbrrank[1][1][1]) mcount = 0; + + #pragma omp critical + { + MPI_Isend(h->send[ireq], mcount, MPI_DOUBLE, h->nbrrank[i][j][k], + h->tagbase + ireq, h->comm, h->request + 27 + ireq); + } + } + } + + return 0; +} + +/***************************************************************************** + * + * lb_halo_free + * + * Complete all the send and receive requests. + * + *****************************************************************************/ + +int lb_halo_free(lb_t * lb, lb_halo_t * h) { + + assert(lb); + assert(h); + + /* Can free() be used with thread safety? */ + + #pragma omp parallel for schedule(dynamic, 1) + for (int ireq = 0; ireq < 2*h->map.nvel; ireq++) { + + int issatisfied = -1; + MPI_Status status = {}; + + #pragma omp critical + { + MPI_Waitany(2*h->map.nvel, h->request, &issatisfied, &status); + } + /* Check status is what we expect? */ + + if (issatisfied == MPI_UNDEFINED) { + /* No action e.g., for (0,0,0) case */ + } + else { + /* Handle either send or recv request completion */ + if (issatisfied < h->map.nvel) { + /* This is a recv */ + int irreq = issatisfied; + lb_halo_dequeue_recv(lb, h, irreq); + free(h->recv[irreq]); + } + else { + /* This was a send */ + int isreq = issatisfied - 27; + free(h->send[isreq]); + } + } + } + + return 0; +} + +/***************************************************************************** + * + * util_lb_data_check_set + * + * Set unique test values in the distribution. + * + *****************************************************************************/ + +int util_lb_data_check_set(lb_t * lb) { + + int nlocal[3] = {}; + + assert(lb); + + cs_nlocal(lb->cs, nlocal); + + for (int ic = 1; ic <= nlocal[X]; ic++) { + for (int jc = 1; jc <= nlocal[Y]; jc++) { + for (int kc = 1; kc <= nlocal[Z]; kc++) { + for (int p = 0 ; p < lb->model.nvel; p++) { + int index = cs_index(lb->cs, ic, jc, kc); + int laddr = LB_ADDR(lb->nsite, lb->ndist, lb->nvel, index, 0, p); + lb->f[laddr] = 1.0*lb_data_index(lb, ic, jc, kc, p); + } + } + } + } + + return 0; +} + +/***************************************************************************** + * + * util_lb_data_check + * + * Examine halo values and check they are as expected. + * + *****************************************************************************/ + +int util_lb_data_check(lb_t * lb, int full) { + + int ifail = 0; + int nh = 1; + int nhk = nh; + int nlocal[3] = {}; + + assert(lb); + + cs_nlocal(lb->cs, nlocal); + + /* Fix for 2d, where there should be no halo regions in Z */ + if (lb->ndim == 2) nhk = 0; + + for (int ic = 1 - nh; ic <= nlocal[X] + nh; ic++) { + for (int jc = 1 - nh; jc <= nlocal[Y] + nh; jc++) { + for (int kc = 1 - nhk; kc <= nlocal[Z] + nhk; kc++) { + + int is_halo = (ic < 1 || jc < 1 || kc < 1 || + ic > nlocal[X] || jc > nlocal[Y] || kc > nlocal[Z]); + + if (is_halo == 0) continue; + + int index = cs_index(lb->cs, ic, jc, kc); + + for (int p = 0; p < lb->model.nvel; p++) { + + /* Look for propagating distributions (into domain). */ + int icdt = ic + lb->model.cv[p][X]; + int jcdt = jc + lb->model.cv[p][Y]; + int kcdt = kc + lb->model.cv[p][Z]; + + is_halo = (icdt < 1 || jcdt < 1 || kcdt < 1 || + icdt > nlocal[X] || jcdt > nlocal[Y] || kcdt > nlocal[Z]); + + if (full || is_halo == 0) { + /* Check */ + int laddr = LB_ADDR(lb->nsite, lb->ndist, lb->nvel, index, 0, p); + double fex = 1.0*lb_data_index(lb, ic, jc, kc, p); + if (fabs(fex - lb->f[laddr]) > DBL_EPSILON) ifail += 1; + assert(fabs(fex - lb->f[laddr]) < DBL_EPSILON); + } + } + } + } + } + + return ifail; +} + +/***************************************************************************** + * + * test_lb_halo_create + * + *****************************************************************************/ + +int test_lb_halo_create(pe_t * pe, cs_t * cs, int ndim, int nvel, int full) { + + lb_data_options_t options = {.ndim = ndim, .nvel = nvel, .ndist = 1}; + lb_t * lb = NULL; + + assert(pe); + assert(cs); + + lb_data_create(pe, cs, &options, &lb); + + util_lb_data_check_set(lb); + + { + lb_halo_t h = {}; + lb_halo_create(lb, &h, full); + lb_halo_free(lb, &h); + } + + util_lb_data_check(lb, full); + + lb_data_free(lb); + + return 0; +} + +/***************************************************************************** + * + * test_lb_halo + * + *****************************************************************************/ + +int test_lb_halo(pe_t * pe) { + + assert(pe); + + /* Two dimensional system */ + { + cs_t * cs = NULL; + int ntotal[3] = {64, 64, 1}; + + cs_create(pe, &cs); + cs_ntotal_set(cs, ntotal); + cs_init(cs); + + test_lb_halo_create(pe, cs, 2, 9, 0); + test_lb_halo_create(pe, cs, 2, 9, 1); + + cs_free(cs); + } + + /* Three dimensional system */ + { + cs_t * cs = NULL; + + cs_create(pe, &cs); + cs_init(cs); + + test_lb_halo_create(pe, cs, 3, 15, 0); + test_lb_halo_create(pe, cs, 3, 15, 1); + test_lb_halo_create(pe, cs, 3, 19, 0); + test_lb_halo_create(pe, cs, 3, 19, 1); + test_lb_halo_create(pe, cs, 3, 27, 0); + test_lb_halo_create(pe, cs, 3, 27, 1); + + cs_free(cs); + } + + return 0; +} + + /***************************************************************************** * * test_model_suite @@ -46,6 +729,9 @@ int test_model_suite(void) { cs_t * cs = NULL; pe_create(MPI_COMM_WORLD, PE_QUIET, &pe); + + test_lb_halo(pe); + cs_create(pe, &cs); cs_init(cs); From 47809f06aae393f655408baefdd2c2f54d47d5d0 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Fri, 17 Dec 2021 15:39:10 +0000 Subject: [PATCH 110/117] Use OpenMP --- config/codeql-g++.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/codeql-g++.mk b/config/codeql-g++.mk index e9faf9de6..3a39f9471 100644 --- a/config/codeql-g++.mk +++ b/config/codeql-g++.mk @@ -9,7 +9,7 @@ BUILD = serial MODEL = -D_D3Q19_ -CC = g++ +CC = g++ -fopenmp CFLAGS = -O -g -Wall -Werror AR = ar From 7999f3c99bd7bf11e40ca7e54f325bb152b04493 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Tue, 21 Dec 2021 14:26:00 +0000 Subject: [PATCH 111/117] Fix initialisation --- tests/unit/test_model.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/unit/test_model.c b/tests/unit/test_model.c index a047cc344..e308635f4 100644 --- a/tests/unit/test_model.c +++ b/tests/unit/test_model.c @@ -348,9 +348,9 @@ int lb_halo_create(const lb_t * lb, lb_halo_t * h, int full) { /* Determine look-up table of ranks of neighbouring processes */ { - int dims[3]; - int periods[3]; - int coords[3]; + int dims[3] = {}; + int periods[3] = {}; + int coords[3] = {}; MPI_Cart_get(h->comm, h->map.ndim, dims, periods, coords); From 765310a60c2d4fa8449b1dbe66a5411ebafdd496 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Tue, 21 Dec 2021 15:01:09 +0000 Subject: [PATCH 112/117] Bug fix --- src/hydro.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hydro.c b/src/hydro.c index 65d113461..9c0dd2dad 100644 --- a/src/hydro.c +++ b/src/hydro.c @@ -1111,9 +1111,9 @@ __global__ void hydro_accumulate_kernel_v(kernel_ctxt_t * ktx, hydro_t * hydro, double fyb = 0.0; double fzb = 0.0; for (int it = 0; it < blockDim.x; it++) { - fxb += fx[8*it]; - fyb += fy[8*it]; - fzb += fz[8*it]; + fxb += fx[TARGET_PAD*it]; + fyb += fy[TARGET_PAD*it]; + fzb += fz[TARGET_PAD*it]; } tdpAtomicAddDouble(fnet + X, fxb); tdpAtomicAddDouble(fnet + Y, fyb); From 438fcfd150bcf7183da0d67b8cf710f52ddd4abf Mon Sep 17 00:00:00 2001 From: not populated Date: Thu, 23 Dec 2021 13:23:22 +0000 Subject: [PATCH 113/117] Make pe_time() available --- src/pe.c | 2 -- src/pe.h | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pe.c b/src/pe.c index 5f0ce74c4..34b37d9f9 100644 --- a/src/pe.c +++ b/src/pe.c @@ -42,8 +42,6 @@ struct pe_s { char subdirectory[FILENAME_MAX]; }; -__host__ int pe_time(char * strctime, int bufsiz); - /***************************************************************************** * * pe_create diff --git a/src/pe.h b/src/pe.h index f9b9668d1..4e2046055 100644 --- a/src/pe.h +++ b/src/pe.h @@ -37,4 +37,6 @@ __host__ int pe_info(pe_t * pe, const char * fmt, ...); __host__ int pe_fatal(pe_t * pe, const char * fmt, ...); __host__ int pe_verbose(pe_t * pe, const char * fmt, ...); +__host__ int pe_time(char * strctime, int bufsiz); + #endif From a27c6c42d9db60c6daded9865241852af20185ce Mon Sep 17 00:00:00 2001 From: not populated Date: Thu, 23 Dec 2021 13:23:55 +0000 Subject: [PATCH 114/117] Add code for lap timer --- src/timer.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++--- src/timer.h | 27 +++++++++++++++++--- 2 files changed, 92 insertions(+), 6 deletions(-) diff --git a/src/timer.c b/src/timer.c index 662b6d269..82ccc5a0f 100644 --- a/src/timer.c +++ b/src/timer.c @@ -7,12 +7,10 @@ * There are a number of separate 'timers', each of which can * be started, and stopped, independently. * - * $Id: timer.c,v 1.5 2010-10-15 12:40:03 kevin Exp $ - * * Edinburgh Soft Matter and Statistical Physics Group and * Edinburgh Parallel Computing Centre * - * (c) 2010-2017 The University of Edinburgh + * (c) 2010-2021 The University of Edinburgh * * Contributing authors: * Kevin Stratford (kevin@epcc.ed.ac.uk) @@ -73,6 +71,7 @@ static const char * timer_name[] = {"Total", "Electrokinetics", "Poisson equation", "Nernst Planck", + "Lap timer (no report)", "Free1", "Free2", "Free3" @@ -141,6 +140,7 @@ double timer_lapse(const int id) { tlapse = tnow - timer[id].t_start; timer[id].t_start = tnow; + timer[id].nsteps = 0; } return tlapse; @@ -198,7 +198,10 @@ void TIMER_statistics() { for (n = 0; n < TIMER_NTIMERS; n++) { /* Report the stats for active timers */ + /* Not the lap timer. */ + if (n == TIMER_LAP) continue; + if (timer[n].nsteps != 0) { t_min = timer[n].t_min; @@ -219,3 +222,65 @@ void TIMER_statistics() { return; } + +/***************************************************************************** + * + * timekeeper_create + * + *****************************************************************************/ + +__host__ int timekeeper_create(pe_t * pe, const timekeeper_options_t * opts, + timekeeper_t * tk) { + assert(pe); + assert(opts); + assert(tk); + + *tk = (timekeeper_t) {}; + tk->pe = pe; + tk->options = *opts; + + return 0; +} + +/***************************************************************************** + * + * timekeeper_step + * + * We anticipate calling this once at end of each time step .. + * + *****************************************************************************/ + +__host__ int timekeeper_step(timekeeper_t * tk) { + + assert(tk); + + tk->timestep += 1; + + if (tk->options.lap_report) { + if (tk->timestep % tk->options.lap_report_freq == 0) { + /* Recell strctime from pe_time() has a new line */ + pe_t * pe = tk->pe; + char strctime[BUFSIZ] = {}; + pe_time(strctime, BUFSIZ); + pe_info(pe, "\nLap time at step %9d is: %8.3f seconds at %s", + tk->timestep, timer_lapse(TIMER_LAP), strctime); + } + } + + return 0; +} + +/***************************************************************************** + * + * timekeeper_free + * + *****************************************************************************/ + +__host__ int timekeeper_free(timekeeper_t * tk) { + + assert(tk); + + *tk = (timekeeper_t) {}; + + return 0; +} diff --git a/src/timer.h b/src/timer.h index 5f06e0c93..49e1e2fa3 100644 --- a/src/timer.h +++ b/src/timer.h @@ -5,12 +5,10 @@ * Note that the number of timers, their ids, and their descriptive * names must match here. * - * $Id: timer.h,v 1.4 2010-10-15 12:40:03 kevin Exp $ - * * Edinburgh Soft Matter and Statistical Physics Group and * Edinburgh Parallel Computing Centre * - * (c) 2010-2017 The University of Edinburgh + * (c) 2010-2021 The University of Edinburgh * * Contributing authors: * Kevin Stratford (kevin@epcc.ed.ac.uk) @@ -22,6 +20,28 @@ #include "pe.h" +/* The aim here is to replace static data in timer.c with something + * more flexible in timerkeeper_t */ + +typedef struct timekeeper_options_s timekeeper_options_t; +typedef struct timekeeper_s timekeeper_t; + +struct timekeeper_options_s { + int lap_report; + int lap_report_freq; +}; + +struct timekeeper_s { + pe_t * pe; + int timestep; + timekeeper_options_t options; +}; + +__host__ int timekeeper_create(pe_t * pe, const timekeeper_options_t * opts, + timekeeper_t * tk); +__host__ int timekeeper_step(timekeeper_t * tk); +__host__ int timerkeeper_free(timekeeper_t * tk); + __host__ int TIMER_init(pe_t * pe); __host__ void TIMER_start(const int); __host__ void TIMER_stop(const int); @@ -63,6 +83,7 @@ enum timer_id {TIMER_TOTAL = 0, TIMER_ELECTRO_TOTAL, TIMER_ELECTRO_POISSON, TIMER_ELECTRO_NPEQ, + TIMER_LAP, TIMER_FREE1, TIMER_FREE2, TIMER_FREE3, From ca1b818d24c104d897f0ecb588df9e3c347e266d Mon Sep 17 00:00:00 2001 From: not populated Date: Thu, 23 Dec 2021 13:25:07 +0000 Subject: [PATCH 115/117] Add timekeeper for lap timer --- src/ludwig.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/src/ludwig.c b/src/ludwig.c index 5fffea251..070d65c97 100644 --- a/src/ludwig.c +++ b/src/ludwig.c @@ -165,6 +165,7 @@ struct ludwig_s { stats_ahydro_t * stat_ah; /* Hydrodynamic radius calibration */ stats_rheo_t * stat_rheo; /* Rheology diagnostics */ stats_turb_t * stat_turb; /* Turbulent diagnostics */ + timekeeper_t tk; /* Time keeper */ }; static int ludwig_rt(ludwig_t * ludwig); @@ -172,6 +173,7 @@ static int ludwig_report_momentum(ludwig_t * ludwig); static int ludwig_colloids_update(ludwig_t * ludwig); static int ludwig_colloids_update_low_freq(ludwig_t * ludwig); +int ludwig_timekeeper_init(ludwig_t * ludwig); int free_energy_init_rt(ludwig_t * ludwig); int visc_model_init_rt(pe_t * pe, rt_t * rt, ludwig_t * ludwig); int io_replace_values(field_t * field, map_t * map, int map_id, double value); @@ -201,7 +203,7 @@ static int ludwig_rt(ludwig_t * ludwig) { io_info_t * iohandler = NULL; assert(ludwig); - + TIMER_init(ludwig->pe); TIMER_start(TIMER_TOTAL); @@ -219,6 +221,7 @@ static int ludwig_rt(ludwig_t * ludwig) { cs = ludwig->cs; rt = ludwig->rt; + ludwig_timekeeper_init(ludwig); init_control(pe, rt); physics_init_rt(rt, ludwig->phys); @@ -486,6 +489,9 @@ void ludwig_run(const char * inputfile) { if (ludwig->p) field_memcpy(ludwig->p, tdpMemcpyHostToDevice); if (ludwig->q) field_memcpy(ludwig->q, tdpMemcpyHostToDevice); + /* Lap timer: include initial statistics in first trip */ + TIMER_start(TIMER_LAP); + pe_info(ludwig->pe, "Initial conditions.\n"); wall_is_pm(ludwig->wall, &is_porous_media); @@ -906,7 +912,10 @@ void ludwig_run(const char * inputfile) { /* Print progress report */ + timekeeper_step(&ludwig->tk); + if (is_statistics_step()) { + lb_memcpy(ludwig->lb, tdpMemcpyDeviceToHost); stats_distribution_print(ludwig->lb, ludwig->map); lb_ndist(ludwig->lb, &im); @@ -2064,3 +2073,33 @@ int io_replace_values(field_t * field, map_t * map, int map_id, double value) { return 0; } + +/***************************************************************************** + * + * ludwig_timekeeper_init + * + *****************************************************************************/ + +__host__ int ludwig_timekeeper_init(ludwig_t * ludwig) { + + timekeeper_options_t opts = {}; + + assert(ludwig); + + { + pe_t * pe = ludwig->pe; + rt_t * rt = ludwig->rt; + + if (rt_switch(rt, "timer_lap_report")) opts.lap_report = 1; + rt_int_parameter(rt, "timer_lap_report_freq", &opts.lap_report_freq); + + if (opts.lap_report && opts.lap_report_freq == 0) { + pe_fatal(pe, "Please specify a timer_lap_report_freq " + "(timer_lap_report is on)\n"); + } + + timekeeper_create(pe, &opts, &ludwig->tk); + } + + return 0; +} From f5b8e3fd69fee5aaba1fa50951fb6656346f1d4a Mon Sep 17 00:00:00 2001 From: not populated Date: Thu, 23 Dec 2021 13:30:21 +0000 Subject: [PATCH 116/117] Pending ultimate check of the -ve sign in active stress --- src/lc_droplet.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/lc_droplet.c b/src/lc_droplet.c index c978f0744..195ff24a1 100644 --- a/src/lc_droplet.c +++ b/src/lc_droplet.c @@ -594,16 +594,7 @@ int fe_lc_droplet_str_symm(fe_lc_droplet_t * fe, int index, double sth[3][3]){ } } - /* Additional minus sign. */ - - for (ia = 0; ia < 3; ia++) { - for (ib = 0; ib < 3; ib++) { - sth[ia][ib] = -sth[ia][ib]; - } - } - - - /* Put active stress here (even if zero). No additional -ve sign. */ + /* Put active stress here (even if zero). */ { double phi = 0.0; @@ -618,6 +609,14 @@ int fe_lc_droplet_str_symm(fe_lc_droplet_t * fe, int index, double sth[3][3]){ } } + /* Additional minus sign. */ + + for (ia = 0; ia < 3; ia++) { + for (ib = 0; ib < 3; ib++) { + sth[ia][ib] = -sth[ia][ib]; + } + } + return 0; } From 08c07f08cff1d50924e2f747cbe58f6ffbdb3887 Mon Sep 17 00:00:00 2001 From: Kevin Stratford Date: Thu, 23 Dec 2021 15:01:19 +0000 Subject: [PATCH 117/117] Version 0.15.0 --- CHANGES.md | 7 +++++++ version.h | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 91437451b..8c77e2361 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,13 @@ version 0.15.0 - A diagnostic computation and output of the force breakdown on each colloid has been added. This is currently via a static switch in stats_colloid_force_split.c +- An option for a "lap timer" is now provided. +- Some simple open boundary conditions for fluid and binary composition + are available. See the "Open boundaries" section at + https://ludwig.epcc.ed.ac.uk/ +- Some refactoring of the lattice Boltzmann basis information has been + performed in order to be able to move to a more flexible approach. + This should have no practical impact at present. version 0.14.0 diff --git a/version.h b/version.h index 6f564aae1..7640c7583 100644 --- a/version.h +++ b/version.h @@ -5,7 +5,7 @@ * The version is MAJOR.MINOR.PATCH * See, e.g., https://apr.apache.org/versioning.html * - * (c) 2014-2020 The University of Edinburgh + * (c) 2014-2021 The University of Edinburgh * *****************************************************************************/ @@ -13,7 +13,7 @@ #define LUDWIG_VERSION_H #define LUDWIG_MAJOR_VERSION 0 -#define LUDWIG_MINOR_VERSION 14 +#define LUDWIG_MINOR_VERSION 15 #define LUDWIG_PATCH_VERSION 0 #endif