From eabe6f33d8be10e726cf6499d7915c28a348051c Mon Sep 17 00:00:00 2001 From: astellhorn <93910032+astellhorn@users.noreply.github.com> Date: Fri, 19 Jan 2024 17:07:31 +0100 Subject: [PATCH] parallelepiped chains based on MagneticOrientedChains have inserted the option for chains (taken form MagneticOrientedCHains) into the parallelepiped script from sasview --- sasmodels/models/ParallelepipedChain.c | 218 ++++++++++++++++++++++++ sasmodels/models/ParallelepipedChain.py | 92 ++++++++++ 2 files changed, 310 insertions(+) create mode 100644 sasmodels/models/ParallelepipedChain.c create mode 100644 sasmodels/models/ParallelepipedChain.py diff --git a/sasmodels/models/ParallelepipedChain.c b/sasmodels/models/ParallelepipedChain.c new file mode 100644 index 00000000..4676a024 --- /dev/null +++ b/sasmodels/models/ParallelepipedChain.c @@ -0,0 +1,218 @@ +static double +form_volume(double length_a, double length_b, double length_c) +{ + return length_a * length_b * length_c; +} + +static double +radius_from_excluded_volume(double length_a, double length_b, double length_c) +{ + double r_equiv, length; + double lengths[3] = {length_a, length_b, length_c}; + double lengthmax = fmax(lengths[0],fmax(lengths[1],lengths[2])); + double length_1 = lengthmax; + double length_2 = lengthmax; + double length_3 = lengthmax; + + for(int ilen=0; ilen<3; ilen++) { + if (lengths[ilen] < length_1) { + length_2 = length_1; + length_1 = lengths[ilen]; + } else { + if (lengths[ilen] < length_2) { + length_2 = lengths[ilen]; + } + } + } + if(length_2-length_1 > length_3-length_2) { + r_equiv = sqrt(length_2*length_3/M_PI); + length = length_1; + } else { + r_equiv = sqrt(length_1*length_2/M_PI); + length = length_3; + } + + return 0.5*cbrt(0.75*r_equiv*(2.0*r_equiv*length + (r_equiv + length)*(M_PI*r_equiv + length))); +} + +static double +radius_effective(int mode, double length_a, double length_b, double length_c) +{ + switch (mode) { + default: + case 1: // equivalent cylinder excluded volume + return radius_from_excluded_volume(length_a,length_b,length_c); + case 2: // equivalent volume sphere + return cbrt(length_a*length_b*length_c/M_4PI_3); + case 3: // half length_a + return 0.5 * length_a; + case 4: // half length_b + return 0.5 * length_b; + case 5: // half length_c + return 0.5 * length_c; + case 6: // equivalent circular cross-section + return sqrt(length_a*length_b/M_PI); + case 7: // half ab diagonal + return 0.5*sqrt(length_a*length_a + length_b*length_b); + case 8: // half diagonal + return 0.5*sqrt(length_a*length_a + length_b*length_b + length_c*length_c); + } +} + +static void +Fq(double q, + double *F1, + double *F2, + double sld, + double solvent_sld, + double length_a, + double length_b, + double length_c) +{ + const double mu = 0.5 * q * length_b; + + // Scale sides by B + const double a_scaled = length_a / length_b; + const double c_scaled = length_c / length_b; + + // outer integral (with gauss points), integration limits = 0, 1 + double outer_total_F1 = 0.0; //initialize integral + double outer_total_F2 = 0.0; //initialize integral + for( int i=0; i