/** * Input Variables: * * Date: * UTC: * u: Input position vector in GSM * nAlpha: Number of Pitch Angles to compute * Alpha: Pitch Angles to compute * * Input/OutPut Variables: * * MagEphemInfo: Structure used to input and output parameters/settings/results to/from routine. * */ void Lgm_ComputeLstarVersusPA( long int Date, double UTC, Lgm_Vector *u, int nAlpha, double *Alpha, int Colorize, Lgm_MagEphemInfo *MagEphemInfo ) { Lgm_LstarInfo *LstarInfo, *LstarInfo2, *LstarInfo3; Lgm_Vector v1, v2, v3, vv1, Bvec; double sa, sa2, Blocal; double Lam, CosLam, LSimple; int i, k, LS_Flag, nn, tk, TraceFlag; char *PreStr, *PostStr; /* These should be set by the user in the setup up MagEphemInfo no in here */ //MagEphemInfo->LstarInfo->SaveShellLines = FALSE; //MagEphemInfo->LstarInfo->FindShellPmin = FALSE; //MagEphemInfo->LstarInfo->ComputeVgc = FALSE; //MagEphemInfo->LstarInfo->ComputeVgc = FALSE; LstarInfo = MagEphemInfo->LstarInfo; // Save Date, UTC to MagEphemInfo structure MagEphemInfo->Date = Date; MagEphemInfo->UTC = UTC; // Save nAlpha, and Alpha array to MagEphemInfo structure MagEphemInfo->nAlpha = nAlpha; for (i=0; i<MagEphemInfo->nAlpha; i++) MagEphemInfo->Alpha[i] = Alpha[i]; // Set Tolerances Lgm_SetLstarTolerances( MagEphemInfo->LstarQuality, MagEphemInfo->nFLsInDriftShell, LstarInfo ); // set coord transformation Lgm_Set_Coord_Transforms( Date, UTC, LstarInfo->mInfo->c ); /* * Blocal at sat location. */ MagEphemInfo->P = *u; LstarInfo->mInfo->Bfield( u, &Bvec, LstarInfo->mInfo ); Blocal = Lgm_Magnitude( &Bvec ); MagEphemInfo->B = Blocal; //printf("Blocal = %g\n", Blocal); for ( i=0; i<MagEphemInfo->nAlpha; i++ ){ sa = sin( MagEphemInfo->Alpha[i]*RadPerDeg ); sa2 = sa*sa; MagEphemInfo->Bm[i] = Blocal/sa2; //printf("Bm[%d] = %g\n", i, MagEphemInfo->Bm[i] ); } /* * Compute Field-related quantities for each Pitch Angle. * * * First do a trace to identify the FL type and some of its critical points. * */ TraceFlag = Lgm_Trace( u, &v1, &v2, &v3, LstarInfo->mInfo->Lgm_LossConeHeight, TRACE_TOL, TRACE_TOL2, LstarInfo->mInfo ); MagEphemInfo->FieldLineType = TraceFlag; //printf("P = %g %g %g Blocal = %lf Bmin = %lf \n", u->x, u->y, u->z, Blocal, MagEphemInfo->Bmin ); if ( TraceFlag > 0 ) { MagEphemInfo->Ellipsoid_Footprint_Ps = v1; MagEphemInfo->Ellipsoid_Footprint_Pn = v2; MagEphemInfo->Pmin = v3; MagEphemInfo->Snorth = LstarInfo->mInfo->Snorth; MagEphemInfo->Ssouth = LstarInfo->mInfo->Ssouth; MagEphemInfo->Smin = LstarInfo->mInfo->Smin; MagEphemInfo->Bmin = LstarInfo->mInfo->Bmin; //printf("P = %g %g %g Blocal = %lf Bmin = %lf \n", u->x, u->y, u->z, Blocal, MagEphemInfo->Bmin ); //MagEphemInfo->Mref = LstarInfo->mInfo->c->M_cd_McIllwain; MagEphemInfo->Mref = LstarInfo->mInfo->c->M_cd_2010; MagEphemInfo->Mcurr = LstarInfo->mInfo->c->M_cd; MagEphemInfo->Mused = MagEphemInfo->Mref; } if ( TraceFlag != 1 ) { /* * FL not closed. */ for ( i=0; i<MagEphemInfo->nAlpha; i++ ){ MagEphemInfo->Lstar[i] = LGM_FILL_VALUE; MagEphemInfo->I[i] = LGM_FILL_VALUE; MagEphemInfo->K[i] = LGM_FILL_VALUE; MagEphemInfo->Sb[i] = LGM_FILL_VALUE; } MagEphemInfo->Sb0 = LGM_FILL_VALUE; MagEphemInfo->d2B_ds2 = LGM_FILL_VALUE; MagEphemInfo->RofC = LGM_FILL_VALUE; } if ( TraceFlag == 1 ) { MagEphemInfo->Sb0 = LstarInfo->mInfo->Sb0; // Sb Integral for equatorially mirroring particles. MagEphemInfo->d2B_ds2 = LstarInfo->mInfo->d2B_ds2; // second deriv of B wrt s at equator. MagEphemInfo->RofC = LstarInfo->mInfo->RofC; // radius of curvature at Bmin point. /* * Get a simple measure of how big L is */ Lgm_Convert_Coords( &v1, &vv1, GSM_TO_SM, LstarInfo->mInfo->c ); Lam = asin( vv1.z/Lgm_Magnitude( &vv1 ) ); CosLam = cos( Lam ); //LSimple = (1.0+LstarInfo->mInfo->Lgm_LossConeHeight/WGS84_A)/( CosLam*CosLam ); LSimple = Lgm_Magnitude( &LstarInfo->mInfo->Pmin ); { // ***** BEGIN PARALLEL EXECUTION ***** /* * Do all of the PAs in parallel. To control how many threads get run * use the enironment variable OMP_NUM_THREADS. For example, * setenv OMP_NUM_THREADS 8 * will use 8 threads to do the loop in parallel. Be very careful what gets * set private here -- the threads must not interfere with each other. */ #if USE_OPENMP #pragma omp parallel private(LstarInfo2,LstarInfo3,sa,sa2,LS_Flag,nn,tk,PreStr,PostStr) #pragma omp for schedule(dynamic, 1) #endif for ( i=0; i<MagEphemInfo->nAlpha; i++ ){ // LOOP OVER PITCH ANGLES /* * make a local copy of LstarInfo structure -- needed for multi-threading */ LstarInfo3 = Lgm_CopyLstarInfo( LstarInfo ); /* * colorize the diagnostic messages. */ if ( Colorize ){ sprintf( LstarInfo3->PreStr, "\033[38;5;%dm", Colors[i%9]); sprintf( LstarInfo3->PostStr, "\033[0m"); } else { LstarInfo3->PreStr[0] = '\0'; LstarInfo3->PostStr[0] = '\0'; } PreStr = LstarInfo3->PreStr; PostStr = LstarInfo3->PostStr; /* * Set Bmirror */ LstarInfo3->mInfo->Bm = MagEphemInfo->Bm[i]; NewTimeLstarInfo( Date, UTC, MagEphemInfo->Alpha[i], LstarInfo3->mInfo->Bfield, LstarInfo3 ); /* * Compute L* */ if ( LSimple < LstarInfo3->LSimpleMax ){ LstarInfo2 = Lgm_CopyLstarInfo( LstarInfo3 ); LstarInfo2->mInfo->Bm = LstarInfo3->mInfo->Bm; if (LstarInfo3->VerbosityLevel >= 2 ) { printf("\n\n\t\t%sComputing L* for: UTC = %g (Local) PA = %d (%g)%s\n", PreStr, UTC, i, MagEphemInfo->Alpha[i], PostStr ); //printf(" \t\t%s I = %g PA = %d (%g)%s\n", PreStr, MagEphemInfo->I[i], i, MagEphemInfo->Alpha[i], PostStr ); } //////////////////////////////NOTE //////////////////////////////NOTE We are giving Lstar the Min B point ALREADY!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //////////////////////////////NOTE //////////////////////////////NOTE //////////////////////////////NOTE //printf("LstarInfo2->mInfo->Bm = %g\n", LstarInfo2->mInfo->Bm); LS_Flag = Lstar( &v3, LstarInfo2); if (LstarInfo3->VerbosityLevel >= 2 ) { printf("\t\t%sUTC, L* = %g %g%s\n", PreStr, UTC, LstarInfo2->LS, PostStr ); printf("\t\t%sUTC, L*_McIlwain = %g %g%s\n", PreStr, UTC, LstarInfo2->LS_McIlwain_M, PostStr ); printf("\t\t%sUTC, LSimple = %g %g%s\n\n\n", PreStr, UTC, LSimple, PostStr ); } MagEphemInfo->Lstar[i] = ( LS_Flag >= 0 ) ? LstarInfo2->LS : LGM_FILL_VALUE; MagEphemInfo->I[i] = LstarInfo2->I[0]; // I[0] is I for the FL that the sat is on. MagEphemInfo->K[i] = LstarInfo2->I[0]*sqrt(MagEphemInfo->Bm[i]*1e-5); // Second invariant MagEphemInfo->Sb[i] = LstarInfo2->SbIntegral0; // SbIntegral0 is Sb for the FL that the sat is on. /* * Determine the type of the orbit */ if ( LS_Flag >= 0 ) { LstarInfo2->DriftOrbitType = LGM_DRIFT_ORBIT_CLOSED; for ( k=0; k<LstarInfo2->nMinMax; ++k ) { if ( LstarInfo2->nMinima[k] > 1 ) LstarInfo2->DriftOrbitType = LGM_DRIFT_ORBIT_CLOSED_SHABANSKY; } } else { LstarInfo2->DriftOrbitType = LGM_DRIFT_ORBIT_OPEN; for ( k=0; k<LstarInfo2->nMinMax; ++k ) { if ( LstarInfo2->nMinima[k] > 1 ) LstarInfo2->DriftOrbitType = LGM_DRIFT_ORBIT_OPEN_SHABANSKY; } } MagEphemInfo->DriftOrbitType[i] = LstarInfo2->DriftOrbitType; //printf("\t %sL* [ %g Deg. ]: Date: %ld UTC: %g Lsimple:%g L*:%.15g%s\n", PreStr, MagEphemInfo->Alpha[i], Date, UTC, LSimple, LstarInfo2->LS, PostStr ); if (LstarInfo3->VerbosityLevel > 0 ) { printf("\t %sL* [ %g\u00b0 ]: Date: %ld UTC: %g Lsimple:%g L*:%.15g%s\n", PreStr, MagEphemInfo->Alpha[i], Date, UTC, LSimple, LstarInfo2->LS, PostStr ); } /* * Save detailed results to the MagEphemInfo structure. */ MagEphemInfo->nShellPoints[i] = LstarInfo2->nPnts; for (nn=0; nn<LstarInfo2->nPnts; nn++ ){ MagEphemInfo->Shell_Pmin[i][nn] = LstarInfo2->Pmin[nn]; MagEphemInfo->Shell_Bmin[i][nn] = LstarInfo2->Bmin[nn]; MagEphemInfo->Shell_GradI[i][nn] = LstarInfo2->GradI[nn]; MagEphemInfo->Shell_Vgc[i][nn] = LstarInfo2->Vgc[nn]; MagEphemInfo->ShellI[i][nn] = LstarInfo2->I[nn]; MagEphemInfo->ShellSphericalFootprint_Pn[i][nn] = LstarInfo2->Spherical_Footprint_Pn[nn]; MagEphemInfo->ShellSphericalFootprint_Sn[i][nn] = LstarInfo2->Spherical_Footprint_Sn[nn]; MagEphemInfo->ShellSphericalFootprint_Bn[i][nn] = LstarInfo2->Spherical_Footprint_Bn[nn]; MagEphemInfo->ShellSphericalFootprint_Ps[i][nn] = LstarInfo2->Spherical_Footprint_Ps[nn]; MagEphemInfo->ShellSphericalFootprint_Ss[i][nn] = LstarInfo2->Spherical_Footprint_Ss[nn]; MagEphemInfo->ShellSphericalFootprint_Bs[i][nn] = LstarInfo2->Spherical_Footprint_Bs[nn]; MagEphemInfo->ShellEllipsoidFootprint_Pn[i][nn] = LstarInfo2->Ellipsoid_Footprint_Pn[nn]; MagEphemInfo->ShellEllipsoidFootprint_Sn[i][nn] = LstarInfo2->Ellipsoid_Footprint_Sn[nn]; MagEphemInfo->ShellEllipsoidFootprint_Bn[i][nn] = LstarInfo2->Ellipsoid_Footprint_Bn[nn]; MagEphemInfo->ShellEllipsoidFootprint_Ps[i][nn] = LstarInfo2->Ellipsoid_Footprint_Ps[nn]; MagEphemInfo->ShellEllipsoidFootprint_Ss[i][nn] = LstarInfo2->Ellipsoid_Footprint_Ss[nn]; MagEphemInfo->ShellEllipsoidFootprint_Bs[i][nn] = LstarInfo2->Ellipsoid_Footprint_Bs[nn]; MagEphemInfo->ShellMirror_Pn[i][nn] = LstarInfo2->Mirror_Pn[nn]; //MagEphemInfo->ShellMirror_Sn[i][nn] = LstarInfo2->mInfo->Sm_North; MagEphemInfo->ShellMirror_Sn[i][nn] = LstarInfo2->Mirror_Sn[nn]; MagEphemInfo->ShellMirror_Ps[i][nn] = LstarInfo2->Mirror_Ps[nn]; //MagEphemInfo->ShellMirror_Ss[i][nn] = LstarInfo2->mInfo->Sm_South; MagEphemInfo->ShellMirror_Ss[i][nn] = LstarInfo2->Mirror_Ss[nn]; /* * Save all of the drift shell FLs in MagEphemInfo structure */ MagEphemInfo->nFieldPnts[i][nn] = LstarInfo2->nFieldPnts[nn]; for (tk=0; tk<LstarInfo2->nFieldPnts[nn]; tk++){ // loop over points in a FL MagEphemInfo->s_gsm[i][nn][tk] = LstarInfo2->s_gsm[nn][tk]; MagEphemInfo->Bmag[i][nn][tk] = LstarInfo2->Bmag[nn][tk]; MagEphemInfo->x_gsm[i][nn][tk] = LstarInfo2->x_gsm[nn][tk]; MagEphemInfo->y_gsm[i][nn][tk] = LstarInfo2->y_gsm[nn][tk]; MagEphemInfo->z_gsm[i][nn][tk] = LstarInfo2->z_gsm[nn][tk]; } //printf("LstarInfo2->nFieldPnts[%d] = %d\n", nn, LstarInfo2->nFieldPnts[nn]); MagEphemInfo->nMinima[i][nn] = LstarInfo2->nMinima[nn]; MagEphemInfo->nMaxima[i][nn] = LstarInfo2->nMaxima[nn]; } FreeLstarInfo( LstarInfo2 ); } else { printf(" Lsimple >= %g ( Not doing L* calculation )\n", LstarInfo3->LSimpleMax ); MagEphemInfo->Lstar[i] = LGM_FILL_VALUE; //printf("Bm = %g\n", MagEphemInfo->Bm[i]); MagEphemInfo->I[i] = LGM_FILL_VALUE; MagEphemInfo->K[i] = LGM_FILL_VALUE; MagEphemInfo->nShellPoints[i] = 0; } FreeLstarInfo( LstarInfo3 ); } } // ***** END PARALLEL EXECUTION ***** } return; }
/* * Input Variables: * * Date: * UTC: * brac1: Radial distance for inner edge of search bracket * brac2: Radial distance for outer edge of search bracket * Alpha: Equatorial pitch angle to compute * Quality: Quality factor (0-8) * * Input/OutPut Variables: * K: K value for LCDS at given alpha * LstarInfo: LstarInfo structure to specify B-field model, store last valid Lstar, etc. * */ int LCDS( long int Date, double UTC, double brac1, double brac2, double MLT, double Alpha, double tol, int Quality, double *K, Lgm_LstarInfo *LstarInfo ) { Lgm_LstarInfo *LstarInfo_brac1, *LstarInfo_brac2, *LstarInfo_test; Lgm_Vector v1, v2, v3, LCDSv3, Bvec, Ptest, PtestSM, Pinner, PinnerSM, Pouter, PouterSM; double Blocal, Xtest, sa, sa2, LCDS; double nTtoG = 1.0e-5; int LS_Flag, nn, k, TFlag; int maxIter = 50; //Start by creating necessary structures... need an Lstar info for each bracket, plus test point. LstarInfo_brac1 = Lgm_CopyLstarInfo( LstarInfo ); LstarInfo_brac2 = Lgm_CopyLstarInfo( LstarInfo ); LstarInfo_test = Lgm_CopyLstarInfo( LstarInfo ); // Set Tolerances Lgm_SetLstarTolerances( Quality, 24, LstarInfo_brac1 ); Lgm_SetLstarTolerances( Quality, 24, LstarInfo_brac2 ); Lgm_SetLstarTolerances( Quality, 24, LstarInfo_test ); // set coord transformation Lgm_Set_Coord_Transforms( Date, UTC, LstarInfo_brac1->mInfo->c ); Lgm_Set_Coord_Transforms( Date, UTC, LstarInfo_brac2->mInfo->c ); Lgm_Set_Coord_Transforms( Date, UTC, LstarInfo_test->mInfo->c ); //Check for closed drift shell at brackets PinnerSM.x = brac1*cos(MLT); PinnerSM.y = brac1*sin(MLT); PinnerSM.z = 0.0; Lgm_Convert_Coords( &PinnerSM, &Pinner, SM_TO_GSM, LstarInfo_test->mInfo->c ); /* * Test inner bracket location. */ LstarInfo_brac1->mInfo->Bfield( &Pinner, &Bvec, LstarInfo_brac1->mInfo ); Blocal = Lgm_Magnitude( &Bvec ); sa = sin( LstarInfo->PitchAngle*RadPerDeg ); sa2 = sa*sa; //Trace to minimum-B if ( Lgm_Trace( &Pinner, &v1, &v2, &v3, 120.0, 0.01, TRACE_TOL, LstarInfo_brac1->mInfo ) == LGM_CLOSED ) { //Only continue if bracket 1 is closed FL //Get L* LstarInfo_brac1->mInfo->Bm = LstarInfo_brac1->mInfo->Bmin/sa2; LS_Flag = Lstar( &v3, LstarInfo_brac1); LCDS = LstarInfo_brac1->LS; *K = (LstarInfo_brac1->I0)*sqrt(Lgm_Magnitude(&LstarInfo_brac1->Bmin[0])); if (LstarInfo->VerbosityLevel > 1) printf("Found valid inner bracket. Pinner_GSM, Pmin_GSM = (%g, %g, %g), (%g, %g, %g)\n", Pinner.x, Pinner.y, Pinner.z, LstarInfo_brac1->mInfo->Pmin.x, LstarInfo_brac1->mInfo->Pmin.y, LstarInfo_brac1->mInfo->Pmin.z); } else { FreeLstarInfo( LstarInfo_brac1 ); FreeLstarInfo( LstarInfo_brac2 ); FreeLstarInfo( LstarInfo_test ); return(-8); //Inner bracket is bad - bail } /* * Test outer bracket location. */ PouterSM.x = brac2*cos(MLT); PouterSM.y = brac2*sin(MLT); PouterSM.z = 0.0; Lgm_Convert_Coords( &PouterSM, &Pouter, SM_TO_GSM, LstarInfo_test->mInfo->c ); LstarInfo_brac2->mInfo->Bfield( &Pouter, &Bvec, LstarInfo_brac2->mInfo ); Blocal = Lgm_Magnitude( &Bvec ); //Trace to minimum-B if ( Lgm_Trace( &Pouter, &v1, &v2, &v3, 120.0, 0.01, TRACE_TOL, LstarInfo_brac2->mInfo ) == LGM_CLOSED ) { //If bracket 2 is closed FL then check for undefined L*. If L* is defined, we have a problem //Get L* LstarInfo_brac2->mInfo->Bm = LstarInfo_brac2->mInfo->Bmin/sa2; LS_Flag = Lstar( &v3, LstarInfo_brac2); if (LstarInfo_brac2->LS != LGM_FILL_VALUE) { //move outer bracket out and try again PouterSM.x = 1.7*Lgm_Magnitude(&Pouter)*cos(MLT); PouterSM.y = 1.7*Lgm_Magnitude(&Pouter)*sin(MLT); PouterSM.z = 0.0; Lgm_Convert_Coords( &PouterSM, &Pouter, SM_TO_GSM, LstarInfo_test->mInfo->c ); if ( Lgm_Trace( &Pouter, &v1, &v2, &v3, 120.0, 0.01, TRACE_TOL, LstarInfo_brac2->mInfo ) == LGM_CLOSED ) { LS_Flag = Lstar( &v3, LstarInfo_brac2); if (LstarInfo_brac2->LS != LGM_FILL_VALUE) { FreeLstarInfo( LstarInfo_brac1 ); FreeLstarInfo( LstarInfo_brac2 ); FreeLstarInfo( LstarInfo_test ); return(-9); //Outer bracket is bad - bail } } } } if (LstarInfo->VerbosityLevel > 1) { printf("Found valid outer bracket. Pouter_GSM, Pmin_GSM = (%g, %g, %g), (%g, %g, %g)\n", Pouter.x, Pouter.y, Pouter.z, LstarInfo_brac2->mInfo->Pmin.x, LstarInfo_brac2->mInfo->Pmin.y, LstarInfo_brac2->mInfo->Pmin.z); } //if brackets are okay, we've moved on without changing anything except setting initial LCDS value as L* at inner bracket nn = 0; while (Lgm_Magnitude(&Pouter)-Lgm_Magnitude(&Pinner) > tol){ if (LstarInfo->VerbosityLevel > 1) printf("Current LCDS iteration, bracket width = %d, %g\n", nn, Lgm_Magnitude(&Pouter)-Lgm_Magnitude(&Pinner)); if (nn > maxIter) { printf("********* EXCEEDED MAXITER\n"); //free structures before returning FreeLstarInfo( LstarInfo_brac1 ); FreeLstarInfo( LstarInfo_brac2 ); FreeLstarInfo( LstarInfo_test ); return(-2); //reached max iterations without achieving tolerance - bail } Xtest = (Lgm_Magnitude(&Pinner) + (Lgm_Magnitude(&Pouter)-Lgm_Magnitude(&Pinner))/2.0); PtestSM.x = -1.0*Xtest*cos(MLT); PtestSM.y = -1.0*Xtest*sin(MLT); PtestSM.z = 0.0; Lgm_Convert_Coords( &PtestSM, &Ptest, SM_TO_GSM, LstarInfo_test->mInfo->c ); LstarInfo_test->mInfo->Bfield( &Ptest, &Bvec, LstarInfo_test->mInfo ); Blocal = Lgm_Magnitude( &Bvec ); //Trace to minimum-B TFlag = Lgm_Trace( &Ptest, &v1, &v2, &v3, 120.0, 0.01, TRACE_TOL, LstarInfo_test->mInfo ); if ( TFlag == LGM_CLOSED ) { //If test point is closed FL then check for undefined L*. //Get L* LstarInfo_test->mInfo->Bm = LstarInfo_test->mInfo->Bmin/sa2; LS_Flag = Lstar( &v3, LstarInfo_test); if ( (LS_Flag > 0) || (LstarInfo_test->LS != LGM_FILL_VALUE) ){ //Drift shell defined Pinner = Ptest; LCDSv3 = v3; LCDS = LstarInfo_test->LS; *K = (LstarInfo_test->I0)*sqrt(LstarInfo_test->mInfo->Bm*nTtoG); //Determine the type of the orbit LstarInfo_test->DriftOrbitType = LGM_DRIFT_ORBIT_CLOSED; for ( k=0; k<LstarInfo_test->nMinMax; ++k ) { if ( LstarInfo_test->nMinima[k] > 1 ) LstarInfo_test->DriftOrbitType = LGM_DRIFT_ORBIT_CLOSED_SHABANSKY; if ( LstarInfo_test->nMinima[k] < 1 ) {printf("Less than one minimum defined on field line: Exit due to impossibility."); exit(-1); } } if (LstarInfo->VerbosityLevel > 1) printf("Current LCDS, K, PtestSM is %g, %g, (%g, %g, %g)\n", LCDS, *K, PtestSM.x, PtestSM.y, PtestSM.z); LstarInfo->mInfo->Bm = LstarInfo_test->mInfo->Bm; LstarInfo->DriftOrbitType = LstarInfo_test->DriftOrbitType; } else { Pouter = Ptest; Lgm_Convert_Coords( &Ptest, &PtestSM, GSM_TO_SM, LstarInfo_test->mInfo->c ); printf("Failed DS trace at test point (%g %g %g GSM; %g %g %g SM; TFlag = %d), moving outer bracket to current location\n", Ptest.x, Ptest.y, Ptest.z, PtestSM.x, PtestSM.y, PtestSM.z, TFlag); } } else { //FL open -> drift shell open Lgm_Convert_Coords( &Ptest, &PtestSM, GSM_TO_SM, LstarInfo_test->mInfo->c ); printf("Failed FL trace at test point (%g %g %g GSM; %g %g %g SM; TFlag = %d), moving outer bracket to current location\n", Ptest.x, Ptest.y, Ptest.z, PtestSM.x, PtestSM.y, PtestSM.z, TFlag); Pouter = Ptest; } nn++; } if (LstarInfo->VerbosityLevel > 0) printf("Final LCDS, K is %g, %g. Eq. radius = %g \n", LCDS, *K, Lgm_Magnitude( &LCDSv3 )); LstarInfo->LS = LCDS; //free structures FreeLstarInfo( LstarInfo_brac1 ); FreeLstarInfo( LstarInfo_brac2 ); FreeLstarInfo( LstarInfo_test ); return(0); }
/*! Compute the interaction matrix related to the set of visual features. \return Ls */ vpMatrix vpServo::computeInteractionMatrix() { try { switch (interactionMatrixType) { case CURRENT: { try { computeInteractionMatrixFromList(this ->featureList, this ->featureSelectionList, L); dim_task = L.getRows() ; interactionMatrixComputed = true ; } catch(vpException me) { vpERROR_TRACE("Error caught") ; throw ; } } break ; case DESIRED: { try { if (interactionMatrixComputed == false || forceInteractionMatrixComputation == true) { computeInteractionMatrixFromList(this ->desiredFeatureList, this ->featureSelectionList, L); dim_task = L.getRows() ; interactionMatrixComputed = true ; } } catch(vpException me) { vpERROR_TRACE("Error caught") ; throw ; } } break ; case MEAN: { vpMatrix Lstar (L.getRows(), L.getCols()); try { computeInteractionMatrixFromList(this ->featureList, this ->featureSelectionList, L); computeInteractionMatrixFromList(this ->desiredFeatureList, this ->featureSelectionList, Lstar); } catch(vpException me) { vpERROR_TRACE("Error caught") ; throw ; } L = (L+Lstar)/2; dim_task = L.getRows() ; interactionMatrixComputed = true ; } break ; case USER_DEFINED: // dim_task = L.getRows() ; interactionMatrixComputed = false ; break; } } catch(vpException me) { vpERROR_TRACE("Error caught") ; throw ; } return L ; }
// This file should be identical to DogSolveRK_Unst, with the exception that all // output printing statements are silenced. // // Advance the solution qold to qnew over time interval tstart to tend. // // All local information is allocated within this function. The only part // that gets shared are time values passed through dogStateUnst2. This class // should be modified to accept the state variable, q and aux in place of only // containing time information as is currently the case. (-DS) double DogSolveRK_Unst_Quiet( const dTensor2* vel_vec, const mesh& Mesh, const edge_data_Unst& EdgeData, dTensor3& aux, dTensor3& qold, dTensor3& qnew, const double tstart, const double tend, DogStateUnst2& dogStateUnst2) { const int mx = qnew.getsize(1); const int meqn = qnew.getsize(2); const int kmax = qnew.getsize(3); const int maux = aux.getsize(2); const double* cflv = dogParams.get_cflv(); const int nv = dogParams.get_nv(); RKinfo rk; SetRKinfo(dogParams.get_time_order(),rk); // define local variables int n_step = 0; double t = tstart; double dt = dogStateUnst2.get_initial_dt(); const double CFL_max = cflv[1]; const double CFL_target = cflv[2]; double cfl = 0.0; double dtmin = dt; double dtmax = dt; const int NumElems = Mesh.get_NumElems(); // Number of total elements in mesh const int NumNodes = Mesh.get_NumNodes(); // Number of nodes in mesh const int NumEdges = Mesh.get_NumEdges(); // Number of edges in mesh dTensor3 qstar(NumElems,meqn,kmax); dTensor3 q1(NumElems,meqn,kmax); dTensor3 q2(NumElems,meqn,kmax); dTensor3 auxstar(NumElems,maux,kmax); dTensor3 Lstar(NumElems,meqn,kmax); dTensor3 Lold(NumElems,meqn,kmax); dTensor3 auxold(NumElems,maux,kmax); dTensor1 smax(NumEdges); void L2Project_Unst( const dTensor2* vel_vec, const int istart, const int iend, const int QuadOrder, const int BasisOrder_qin, const int BasisOrder_auxin, const int BasisOrder_fout, const mesh& Mesh, const dTensor3* qin, const dTensor3* auxin, dTensor3* fout, void (*Func)(const dTensor2* vel_vec, const dTensor2&,const dTensor2&, const dTensor2&,dTensor2&)); // JUNK here: void AuxFuncWrapper( const dTensor2* vel_vec, const dTensor2& xpts, const dTensor2& NOT_USED_1, const dTensor2& NOT_USED_2, dTensor2& auxvals); const int space_order = dogParams.get_space_order(); if( maux > 0 ) { printf("WARNING: maux = %d should be zero for Vlasov routines.", maux); printf(" Modify parameters.ini to remove this warning\n" ); L2Project_Unst(vel_vec,1,NumElems, space_order,space_order,space_order,space_order, Mesh,&qnew,&aux,&aux,&AuxFuncWrapper); } // Set initialize qstar and auxstar values qstar.copyfrom(qold); auxstar.copyfrom(aux); // Runge-Kutta time stepping while (t<tend) { // initialize time step int m_accept = 0; n_step = n_step + 1; // check if max number of time steps exceeded if( n_step > nv ) { eprintf(" Error in DogSolveRK_Unst.cpp: " " Exceeded allowed # of time steps \n" " n_step = %d\n" " nv = %d\n\n", n_step, nv); } // copy qnew into qold qold.copyfrom(qnew); auxold.copyfrom(aux); // keep trying until we get a dt that does not violate CFL condition while (m_accept==0) { // set current time double told = t; if (told+dt > tend) { dt = tend - told; } t = told + dt; // TODO - this needs to be performed at the 'local' level dogStateUnst2.set_time ( told ); dogStateUnst2.set_dt ( dt ); // Set initial maximum wave speed to zero smax.setall(0.); // Take a full time step of size dt switch ( dogParams.get_time_order() ) { case 1: // First order in time (1-stage) // ----------------------------------------------- // Stage #1 (the only one in this case) rk.mstage = 1; BeforeStep_Unst(dt,Mesh,aux,qnew); ConstructL_Unst(told, vel_vec,Mesh,EdgeData,aux,qnew,Lstar,smax); UpdateSoln_Unst(rk.alpha1->get(rk.mstage),rk.alpha2->get(rk.mstage), rk.beta->get(rk.mstage),dt,Mesh,aux, qnew, Lstar, qnew); AfterStep_Unst(dt,Mesh,aux,qnew); // ----------------------------------------------- break; case 2: // Second order in time (2-stages) // ----------------------------------------------- // Stage #1 rk.mstage = 1; dogStateUnst2.set_time(told); BeforeStep_Unst(dt,Mesh,aux,qnew); ConstructL_Unst(told,vel_vec,Mesh,EdgeData,aux,qnew,Lstar,smax); UpdateSoln_Unst( rk.alpha1->get(rk.mstage),rk.alpha2->get(rk.mstage), rk.beta->get(rk.mstage), dt, Mesh, aux, qnew, Lstar, qstar); AfterStep_Unst(dt, Mesh, auxstar, qstar); // ------------------------------------------------ // Stage #2 rk.mstage = 2; dogStateUnst2.set_time(told+dt); BeforeStep_Unst(dt, Mesh, auxstar, qstar); ConstructL_Unst(told+1.0*dt, vel_vec, Mesh, EdgeData, aux, qstar, Lstar, smax); UpdateSoln_Unst(rk.alpha1->get(rk.mstage), rk.alpha2->get(rk.mstage), rk.beta->get(rk.mstage), dt, Mesh, auxstar, qstar, Lstar, qnew); AfterStep_Unst(dt, Mesh, aux, qnew); // ------------------------------------------------ break; case 3: // Third order in time (3-stages) // qnew = alpha1 * qstar + alpha2 * qnew + beta * dt * L( qstar ) // alpha1 = 1.0 // alpha2 = 0.0 // beta = 1.0 // ------------------------------------------------ // Stage #1 rk.mstage = 1; dogStateUnst2.set_time(told); BeforeStep_Unst(dt,Mesh,aux,qnew); ConstructL_Unst(told, vel_vec,Mesh,EdgeData,aux,qnew,Lstar,smax); Lold.copyfrom(Lstar); UpdateSoln_Unst(rk.alpha1->get(rk.mstage),rk.alpha2->get(rk.mstage), rk.beta->get(rk.mstage),dt,Mesh,aux,qnew,Lstar,qstar); AfterStep_Unst(dt,Mesh,aux,qstar); // ------------------------------------------------- // alpha1 = 0.75 // alpha2 = 0.25 // beta = 0.25 // Stage #2 rk.mstage = 2; dogStateUnst2.set_time(told+0.5*dt); BeforeStep_Unst(dt,Mesh,aux,qstar); ConstructL_Unst(told+dt, vel_vec,Mesh,EdgeData,aux,qstar,Lstar,smax); UpdateSoln_Unst(rk.alpha1->get(rk.mstage),rk.alpha2->get(rk.mstage), rk.beta->get(rk.mstage),dt,Mesh,aux,qnew,Lstar,qstar); AfterStep_Unst(dt,Mesh,aux,qstar); // -------------------------------------------------- // alpha1 = 2/3 // alpha2 = 1/3 // beta = 2/3 // Stage #3 rk.mstage = 3; dogStateUnst2.set_time(told+dt); BeforeStep_Unst(dt,Mesh,auxstar,qstar); ConstructL_Unst(told+0.5*dt,vel_vec,Mesh,EdgeData,auxstar,qstar,Lstar,smax); UpdateSoln_Unst(rk.alpha1->get(rk.mstage),rk.alpha2->get(rk.mstage), rk.beta->get(rk.mstage),dt,Mesh,aux,qstar,Lstar,qnew); AfterStep_Unst(dt,Mesh,aux,qnew); // -------------------------------------------------- break; default: unsupported_value_error(dogParams.get_time_order()); } // compute cfl number cfl = GetCFL_Unst(dt,Mesh,aux,smax); // output time step information // if (dogParams.get_verbosity()>0) // { // printf(" In DogSolveRK_Quiet: DogSolve2D ... Step %5d" // " CFL =%6.3f" // " dt =%11.3e" // " t =%11.3e\n", // n_step, cfl, dt, t); // } // choose new time step if (cfl>0.0) { dt = Min(dogParams.get_max_dt(), dt*CFL_target/cfl); dtmin = Min(dt,dtmin); dtmax = Max(dt,dtmax); } else { dt = dogParams.get_max_dt(); } // see whether to accept or reject this step if (cfl<=CFL_max) // accept { m_accept = 1; dogStateUnst2.set_time(t); // do any extra work // AfterFullTimeStep_Unst(dogStateUnst2.get_dt(),Mesh, // auxold,qold,Lold,aux,qnew); } else //reject { t = told; dogStateUnst2.set_time(told); // if( dogParams.get_verbosity() > 0 ) // { // printf("DogSolve2D rejecting step..." // "CFL number too large\n"); // } // copy qold into qnew qnew.copyfrom(qold); aux.copyfrom(auxold); // after reject function // AfterReject_Unst(Mesh,dt,aux,qnew); } } } // printf(" Finished! t = %2.3e and nsteps = %d\n", t, n_step ); // set initial time step for next call to DogSolveRK dogStateUnst2.set_initial_dt(dt); void DeleteRKInfo(RKinfo& rk); DeleteRKInfo(rk); return cfl; }
/* * Input Variables: * * Date: * UTC: * u: Input position vector in GSM * nAlpha: Number of Pitch Angles to compute * Alpha: Pitch Angles to compute * Quality: Quality factor (0-8) * * Input/OutPut Variables: * * MagEphemInfo: Structure used to input and output parameters/settings/results to/from routine. * */ void ComputeLstarVersusPA( long int Date, double UTC, Lgm_Vector *u, int nAlpha, double *Alpha, int Quality, Lgm_MagEphemInfo *MagEphemInfo ) { Lgm_LstarInfo *LstarInfo, *LstarInfo2, *LstarInfo3; Lgm_Vector v, v1, v2, v3, vv1, Bvec; double sa, sa2, Blocal; double Lam, CosLam, LSimple, dSa, dSb; int i, LS_Flag, nn, tk, ci; double Ival, Sbval, r, SS; int Kp=KP_DEFAULT; char Filename[128], *PreStr, *PostStr; FILE *fpout; LstarInfo = MagEphemInfo->LstarInfo; // Save Date, UTC to MagEphemInfo structure MagEphemInfo->Date = Date; MagEphemInfo->UTC = UTC; // Save nAlpha, and Alpha array to MagEphemInfo structure MagEphemInfo->nAlpha = nAlpha; for (i=0; i<MagEphemInfo->nAlpha; i++) MagEphemInfo->Alpha[i] = Alpha[i]; // Set Tolerances SetLstarTolerances( MagEphemInfo->LstarQuality, LstarInfo ); sprintf( Filename, "DipoleTest_1.05/results_%.0e.dat", LstarInfo->mInfo->Lgm_FindShellLine_I_Tol ); fpout = fopen(Filename, "w"); // set coord transformation Lgm_Set_Coord_Transforms( Date, UTC, LstarInfo->mInfo->c ); /* * Blocal at sat location. */ MagEphemInfo->P_gsm = *u; LstarInfo->mInfo->Bfield( u, &Bvec, LstarInfo->mInfo ); Blocal = Lgm_Magnitude( &Bvec ); MagEphemInfo->B = Blocal; /* * Compute Field-related quantities for each Pitch Angle. */ if ( Lgm_Trace( u, &v1, &v2, &v3, 120.0, 0.01, TRACE_TOL, LstarInfo->mInfo ) == 1 ) { MagEphemInfo->Pmin_gsm = v3; MagEphemInfo->Bmin = LstarInfo->mInfo->Bmin; /* * Get a simple measure of how big L is */ Lgm_Convert_Coords( &v1, &vv1, GSM_TO_SM, LstarInfo->mInfo->c ); Lam = asin( vv1.z/Lgm_Magnitude( &vv1 ) ); CosLam = cos( Lam ); LSimple = (1.0+120.0/WGS84_A)/( CosLam*CosLam ); { // ***** BEGIN PARALLEL EXECUTION ***** /* * Do all of the PAs in parallel. To control how many threads get run * use the enironment variable OMP_NUM_THREADS. For example, * setenv OMP_NUM_THREADS 8 * will use 8 threads to do the loop in parallel. Be very careful what gets * set private here -- the threads must not interfere with each other. */ #pragma omp parallel private(LstarInfo2,LstarInfo3,sa,sa2,dSa,dSb,LS_Flag,Ival,Sbval,nn,tk) #pragma omp for schedule(dynamic, 1) for ( i=0; i<MagEphemInfo->nAlpha; i++ ){ // LOOP OVER PITCH ANGLES // make a local copy of LstarInfo structure -- needed for multi-threading LstarInfo3 = Lgm_CopyLstarInfo( LstarInfo ); // colorize the diagnostic messages. sprintf( LstarInfo3->PreStr, "\033[38;5;%dm", Colors[i%9]); sprintf( LstarInfo3->PostStr, "\033[0m"); PreStr = LstarInfo3->PreStr; PostStr = LstarInfo3->PostStr; /* * Set Pitch Angle, sin, sin^2, and Bmirror */ sa = sin( MagEphemInfo->Alpha[i]*RadPerDeg ); sa2 = sa*sa; printf("%sComputing L* for Pitch Angle: Alpha[%d] = %g Date: %ld UTC: %g Lsimple = %g%s\n", PreStr, i, MagEphemInfo->Alpha[i], Date, UTC, LSimple, PostStr ); LstarInfo3->mInfo->Bm = Blocal/sa2; NewTimeLstarInfo( Date, UTC, MagEphemInfo->Alpha[i], LstarInfo3->mInfo->Bfield, LstarInfo3 ); MagEphemInfo->Bm[i] = LstarInfo3->mInfo->Bm; /* * Compute L* */ LstarInfo2 = Lgm_CopyLstarInfo( LstarInfo3 ); if ( LSimple < 10.0 ){ // USER SHOULD DECIDE THRESHOLD HERE LstarInfo2->mInfo->Bm = LstarInfo3->mInfo->Bm; if (LstarInfo3->VerbosityLevel >= 2 ) { printf("\n\n\t%sComputing L* for: UTC = %g PA = %d (%g)%s\n", PreStr, UTC, i, MagEphemInfo->Alpha[i], PostStr ); printf(" \t%s I = %g PA = %d (%g)%s\n", PreStr, MagEphemInfo->I[i], i, MagEphemInfo->Alpha[i], PostStr ); } LS_Flag = Lstar( &v3, LstarInfo2); if (LstarInfo3->VerbosityLevel >= 2 ) { printf("\t%sUTC, L* = %g %g%s\n", PreStr, UTC, LstarInfo2->LS, PostStr ); printf("\t%sUTC, L*_McIlwain = %g %g%s\n", PreStr, UTC, LstarInfo2->LS_McIlwain_M, PostStr ); printf("\t%sUTC, LSimple = %g %g%s\n\n\n", PreStr, UTC, LSimple, PostStr ); } MagEphemInfo->Lstar[i] = LstarInfo2->LS; /* * Save results to the MagEphemInfo structure. */ MagEphemInfo->nShellPoints[i] = LstarInfo2->nPnts; for (nn=0; nn<LstarInfo2->nPnts; nn++ ){ MagEphemInfo->ShellI[i][nn] = LstarInfo2->I[nn]; MagEphemInfo->ShellFootprint_Pn[i][nn] = LstarInfo2->Footprint_Pn[nn]; MagEphemInfo->ShellFootprint_Ps[i][nn] = LstarInfo2->Footprint_Ps[nn]; MagEphemInfo->ShellMirror_Pn[i][nn] = LstarInfo2->Mirror_Pn[nn]; MagEphemInfo->ShellMirror_Ps[i][nn] = LstarInfo2->Mirror_Ps[nn]; MagEphemInfo->ShellMirror_Ss[i][nn] = LstarInfo2->mInfo->Sm_South; MagEphemInfo->ShellMirror_Sn[i][nn] = LstarInfo2->mInfo->Sm_North; /* * Save all of the drift shell FLs in MagEphemInfo structure */ MagEphemInfo->nFieldPnts[i][nn] = LstarInfo2->nFieldPnts[nn]; for (tk=0; tk<LstarInfo2->nFieldPnts[nn]; tk++){ // loop over points in a FL MagEphemInfo->s_gsm[i][nn][tk] = LstarInfo2->s_gsm[nn][tk]; MagEphemInfo->Bmag[i][nn][tk] = LstarInfo2->Bmag[nn][tk]; MagEphemInfo->x_gsm[i][nn][tk] = LstarInfo2->x_gsm[nn][tk]; MagEphemInfo->y_gsm[i][nn][tk] = LstarInfo2->y_gsm[nn][tk]; MagEphemInfo->z_gsm[i][nn][tk] = LstarInfo2->z_gsm[nn][tk]; } } } else { printf(" Lsimple >= 10.0 ( Not doing L* calculation )\n" ); } fprintf(fpout, "%.15lf %.15lf\n", MagEphemInfo->Alpha[i], (1.05-LstarInfo2->LS)/LstarInfo->mInfo->Lgm_FindShellLine_I_Tol ); fflush(fpout); FreeLstarInfo( LstarInfo2 ); FreeLstarInfo( LstarInfo3 ); } } // ***** END PARALLEL EXECUTION ***** } // FreeLstarInfo( LstarInfo ); fclose(fpout); return; }