/** This page contains all functions associated with the fan. Note that this is the 3D extension off the well documented [fan page](http://basilisk.fr/sandbox/vheusinkveld/fan.c) */ #include "fractions.h" // Needed to compute fan fractions struct sRotor rot; // Rotor details structure scalar fan[]; // Fan volume fraction struct sRotor { bool fan; double start; // Starting time double stop; // Stopping time double rampT; // Time to start up rotor double P, Prho; // Power, powerdensity double R, W, A, V; // Diameter, Thickness, Area ,Volume double diaVol; // Diagnosed rotor volume double x0, y0, z0; // Origin of rotor double xt, yt, zt; // Translation angles double theta, phi; // Polar and Azimuthal angle double thetat, phit; // Translation angles double Work; // Work done by rotor double cu; // Characteristic velocity bool rotate; // Rotation yes or no coord nf, nr; // Normal vector fan, rotation }; /** Functions */ void init_rotor(); void rotor_update(); void rotor_coord(); void rotor_forcing(); /** Function returning the sRotor structure, includign default properties */ void init_rotor() { rot.Work = 0.; if(!rot.start) rot.start = 0.; if(!rot.stop) rot.stop = 1E10; if(!rot.rampT) rot.rampT = 30.; if(!rot.R) rot.R = 2.5; if(!rot.W) rot.W = 0.3; if(!rot.Prho) rot.Prho = 2000.; if(!rot.x0) rot.x0 = L0/2.; if(!rot.y0) rot.y0 = 10.5; if(!rot.z0){ #if dimension == 2 rot.z0 = 0.; #elif dimension == 3 rot.z0 = L0/2.; #endif } if(!rot.theta) rot.theta = 97*M_PI/180.; // Polar angle if(!rot.phi) rot.phi = 0.*M_PI/180.; // Azimuthal angle if(rot.rotate) { if(!rot.phit){ rot.phit = 2*M_PI/240; } if(!rot.xt){ rot.xt = 0; } if(!rot.yt){ rot.yt = 0; } if(!rot.zt){ rot.zt = 0; } if(!rot.thetat){ rot.thetat = 0.; } } else { rot.xt = 0; rot.yt = 0; rot.zt = 0; rot.thetat = 0.; rot.phit = 0.; } rotor_update(); } /** Forcing by the rotor */ event forcing(i++) { if(rot.fan && t>rot.start && trot.start && t t ? (t-rot.start)/rot.rampT : 1.; w = wsgn*damp*sq(rot.nf.x)*(2.)*rot.P/pow(Delta,3)*dt; tempW += fabs(w)/2*pow(Delta,3); // New kinetic energy utemp = sq(u.x[]) + w; usgn = 1.*(u.x[] >= 0)*(utemp > 0) + -1.*(u.x[] >= 0)*(utemp < 0) + 1.*(u.x[] < 0)*(utemp < 0) + -1.*(u.x[] < 0)*(utemp > 0); u.x[] = usgn*min(sqrt(fabs(utemp)), sq(damp)*1.5*rot.cu); // Limiting the maximum speed } } else { foreach(reduction(+:tempW)) { if(fan[] > 0.) { foreach_dimension() { // Work in respective direction wsgn = sign(rot.nf.x*u.x[]) + (sign(rot.nf.x*u.x[]) == 0)*sign(rot.nf.x); damp = rot.rampT + rot.start > t ? (t-rot.start)/rot.rampT : 1.; corrP = rot.diaVol > 0. ? rot.V/rot.diaVol : 1.; w = wsgn*fan[]*damp*sq(rot.nf.x)*(2./rho[])*(corrP*rot.P/rot.V)*dt; tempW += dv()*fabs(w)/2; // New kinetic energy utemp = sq(u.x[]) + w; usgn = 1.*(u.x[] >= 0)*(utemp > 0) + -1.*(u.x[] >= 0)*(utemp < 0) + 1.*(u.x[] < 0)*(utemp < 0) + -1.*(u.x[] < 0)*(utemp > 0); u.x[] = usgn*min(sqrt(fabs(utemp)), sq(damp)*1.5*rot.cu); // Limiting the maximum speed } } } } rot.Work += tempW; }