12#ifndef BELFEM_CL_JCFUNCTION_DATABASE_HPP
13#define BELFEM_CL_JCFUNCTION_DATABASE_HPP
66 std::unique_ptr< Database > mDatabase ;
71 const real mAngleMin ;
72 const real mAngleMax ;
73 const real mInvLn10 = 1.0/std::log( 10. );
82 bool mHaveSelfField = false ;
89 static constexpr real mSmoothWidth = 1e-3 ;
137 mTmin( mDatabase->
min( 0 ) ),
138 mTmax( mDatabase->
max( 0 ) ),
139 mBmin( std::pow( 10., mDatabase->
min( 1 ) ) ),
140 mBmax( std::pow( 10., mDatabase->
max( 1 ) ) ),
141 mAngleMin( mDatabase->
min( 2 ) ),
142 mAngleMax( mDatabase->
max( 2 ) )
148 mIsN = aLabel !=
"jc" ;
155 if ( mHaveSelfField )
173 std::unique_ptr< Database > tDatabase(
new Database( aPath, aLabel ) );
176 "database %s in %s has %u axes; a jc or n table needs T, log10 B and theta",
177 aLabel.c_str(), aPath.c_str(), (
unsigned int ) tDatabase->dimension() );
185 "angular range of database %s spans [ %g, %g ] rad, but the unfolded\n"
186 "bn_angle contract requires coverage of [ 0, pi ]: a folded export\n"
187 "would silently mis-sample theta > pi/2",
188 aLabel.c_str(), (
double ) tDatabase->min( 2 ), (
double ) tDatabase->max( 2 ) );
194 const real tSlopeBound = tDatabase->upper_bound_derivy_on_lower_y_face() ;
196 "database %s in %s cannot be certified not to rise with |B| at its "
197 "lowest field ( bound on d log10 value / d log10 B: %g ), so it "
198 "cannot be continued monotonically below Bmin",
199 aLabel.c_str(), aPath.c_str(), (
double ) tSlopeBound );
201 if ( aLabel !=
"jc" )
205 const real tFloor = tDatabase->lower_bound_on_lower_y_face() ;
207 "database %s in %s reaches n = %g at its lowest field; n must be at least 1.01",
208 aLabel.c_str(), aPath.c_str(), (
double ) std::pow( 10., tFloor ) );
211 return tDatabase.release() ;
231 const string & aLabel )
238 const bool tIsJc = aLabel ==
"jc" ;
239 const string tColumn = tIsJc ?
"icw" :
"n" ;
251 hid_t tFile = H5Fopen( aPath.c_str(),
252 H5F_ACC_RDONLY, H5P_DEFAULT );
259 if ( H5Lexists( tFile,
"source", H5P_DEFAULT ) > 0 )
261 hid_t tGroup = H5Gopen2( tFile,
"source", H5P_DEFAULT );
272 tGroup,
"columns", tColumns, tStatus );
276 tGroup,
"points", tPoints, tStatus );
286 if ( tColumns( k ) ==
"temperature" ) tIt = k ;
287 if ( tColumns( k ) ==
"field" ) tIb = k ;
288 if ( tColumns( k ) == tColumn ) tIv = k ;
294 if ( tIt < tPoints.
n_cols()
297 && tIt < tColumns.
size()
298 && tIb < tColumns.
size()
299 && tIv < tColumns.
size() )
304 tPoints, tIt, tIb, tIv,
307 if ( tIsJc && tT.
length() > 0 )
324 hid_t tMeta = H5Gopen2( tFile,
"meta",
331 "Icw_77p5K_sf_A_per_m" ) )
334 tMeta,
"Icw_77p5K_sf_A_per_m",
346 if ( tIcw > 0.0 && tTeff > 0.0 )
349 const real tCurve77p5 =
352 if ( tCurve77p5 > 0.0 )
354 tScale = ( tIcw / tTeff )
364 k < tValue.
length(); ++k )
366 tValue( k ) *= tScale ;
393 if ( tN == 0 ) return ;
404 mSelfFieldValue = tValue ;
405 mHaveSelfField = true ;
432 constexpr real tTol = 0.25 ;
438 for (
index_t i = 0; i < tNumRows; ++i )
440 const real tB = aPoints( i, aColB ) ;
441 const real tTi = aPoints( i, aColT ) ;
442 const real tVi = aPoints( i, aColV ) ;
447 if ( tB != 0.0 ) continue ;
448 if ( ! std::isfinite( tTi ) ) continue ;
449 if ( ! std::isfinite( tVi ) ) continue ;
450 if ( tVi <= 0.0 ) continue ;
455 if ( std::abs( tT( k ) - tTi ) < tTol ) { tBin = k ; break ; }
458 if ( tBin == tT.
size() )
466 tSum( tBin ) += tVi ;
472 if ( tNumBins < 2 ) return ;
476 for (
index_t k = 0; k < tNumBins; ++k ) tOrder( k ) = k ;
478 for (
index_t a = 0; a + 1 < tNumBins; ++a )
480 for (
index_t b = a + 1; b < tNumBins; ++b )
482 if ( tT( tOrder( b ) ) < tT( tOrder( a ) ) )
484 const index_t tSwap = tOrder( a ) ;
485 tOrder( a ) = tOrder( b ) ;
486 tOrder( b ) = tSwap ;
494 for (
index_t k = 0; k < tNumBins; ++k )
496 const index_t j = tOrder( k ) ;
498 aValue( k ) = aScale * tSum( j )
499 /
static_cast< real >( tCount( j ) ) ;
513 return std::pow( 10.,
min( mDatabase->values() ) ) ;
569 if ( T >= aT( tN - 1 ) )
572 return aValue( tN - 1 ) ;
576 while ( k < tN - 1 && aT( k ) < T ) ++k ;
578 const real tDT = aT( k ) - aT( k - 1 ) ;
579 dJ0dT = ( aValue( k ) - aValue( k - 1 ) ) / tDT ;
581 return aValue( k - 1 )
582 + dJ0dT * ( T - aT( k - 1 ) ) ;
592 const index_t tN = mSelfFieldT.length() ;
594 for (
index_t k = tN - 1; k > 0; --k )
596 mSelfFieldValue( k - 1 ) = std::max( mSelfFieldValue( k - 1 ), mSelfFieldValue( k ) );
599 mSelfFieldSlope.set_size( tN, 0.0 );
600 for (
index_t k = 1; k + 1 < tN; ++k )
602 const real h0 = mSelfFieldT( k ) - mSelfFieldT( k - 1 ) ;
603 const real h1 = mSelfFieldT( k + 1 ) - mSelfFieldT( k ) ;
604 const real d0 = ( mSelfFieldValue( k ) - mSelfFieldValue( k - 1 ) ) / h0 ;
605 const real d1 = ( mSelfFieldValue( k + 1 ) - mSelfFieldValue( k ) ) / h1 ;
611 const real w0 = 2.0 * h1 + h0 ;
612 const real w1 = h1 + 2.0 * h0 ;
613 mSelfFieldSlope( k ) = ( w0 + w1 ) / ( w0 / d0 + w1 / d1 ) ;
616 mSelfFieldSlope( 0 ) = ( mSelfFieldValue( 1 ) - mSelfFieldValue( 0 ) )
617 / ( mSelfFieldT( 1 ) - mSelfFieldT( 0 ) ) ;
618 mSelfFieldSlope( tN - 1 ) = ( mSelfFieldValue( tN - 1 ) - mSelfFieldValue( tN - 2 ) )
619 / ( mSelfFieldT( tN - 1 ) - mSelfFieldT( tN - 2 ) ) ;
627 const index_t tN = mSelfFieldT.length() ;
629 if ( T <= mSelfFieldT( 0 ) )
631 aDT = mSelfFieldSlope( 0 ) ;
632 return mSelfFieldValue( 0 ) + aDT * ( T - mSelfFieldT( 0 ) ) ;
634 if ( T >= mSelfFieldT( tN - 1 ) )
636 aDT = mSelfFieldSlope( tN - 1 ) ;
637 return mSelfFieldValue( tN - 1 ) + aDT * ( T - mSelfFieldT( tN - 1 ) ) ;
641 while ( k < tN - 1 && mSelfFieldT( k ) < T ) ++k ;
643 const real h = mSelfFieldT( k ) - mSelfFieldT( k - 1 ) ;
644 const real s = ( T - mSelfFieldT( k - 1 ) ) / h ;
645 const real y0 = mSelfFieldValue( k - 1 ) ;
646 const real y1 = mSelfFieldValue( k ) ;
647 const real m0 = mSelfFieldSlope( k - 1 ) * h ;
648 const real m1 = mSelfFieldSlope( k ) * h ;
650 aDT = ( ( 6. * s * s - 6. * s ) * y0 + ( 3. * s * s - 4. * s + 1. ) * m0
651 + ( -6. * s * s + 6. * s ) * y1 + ( 3. * s * s - 2. * s ) * m1 ) / h ;
653 return ( 2. * s * s * s - 3. * s * s + 1. ) * y0
654 + ( s * s * s - 2. * s * s + s ) * m0
655 + ( -2. * s * s * s + 3. * s * s ) * y1
656 + ( s * s * s - s * s ) * m1 ;
663 const bool aWithT,
const bool aWithAngle, Edge & aEdge )
const
665 const real tT = std::clamp( T, mTmin, mTmax ) ;
666 const real tU = mDatabase->min( 1 ) ;
668 const real tLn10 = 1.0 / mInvLn10 ;
670 const real f_u = mDatabase->evaluate_derivy( tT, tU, tA ) ;
672 aEdge.V = std::pow( 10., mDatabase->evaluate( tT, tU, tA ) ) ;
673 aEdge.S = aEdge.V * f_u / mBmin ;
675 if ( aWithT && T > mTmin && T < mTmax )
677 aEdge.V_T = aEdge.V * tLn10 * mDatabase->evaluate_derivx( tT, tU, tA ) ;
678 aEdge.S_T = ( aEdge.V_T * f_u
679 + aEdge.V * mDatabase->evaluate_derivxy( tT, tU, tA ) ) / mBmin ;
683 aEdge.V_A = aEdge.V * tLn10 * mDatabase->evaluate_derivz( tT, tU, tA ) ;
684 aEdge.S_A = ( aEdge.V_A * f_u
685 + aEdge.V * mDatabase->evaluate_derivyz( tT, tU, tA ) ) / mBmin ;
693 return normB < mBmin && ( mIsN || mHaveSelfField ) ;
703 const real b = V - S * mBmin / 3. ;
704 const real b_q = aV_q - aS_q * mBmin / 3. ;
707 const real e = mSmoothWidth * b ;
708 const real e_q = mSmoothWidth * b_q ;
709 const real w = std::sqrt( ( a - b ) * ( a - b ) + e * e ) ;
711 aJ_q = 0.5 * ( aA_q + b_q + ( ( a - b ) * ( aA_q - b_q ) + e * e_q ) / w ) ;
712 return 0.5 * ( a + b + w ) ;
722 const real tDelta = ( V - J ) / mBmin ;
723 const real tBeta = S / tDelta ;
724 const bool tExact = tBeta <= 2.0 ;
726 const real s0 = tExact ? 2. * tDelta - S : 0.0 ;
727 const real s0_q = tExact ? 2. * ( aV_q - aJ_q ) / mBmin - aS_q : 0.0 ;
729 const real h00 = 2. * x * x * x - 3. * x * x + 1. ;
730 const real h10 = x * x * x - 2. * x * x + x ;
731 const real h01 = -2. * x * x * x + 3. * x * x ;
732 const real h11 = x * x * x - x * x ;
734 aValue_q = h00 * aJ_q + h10 * mBmin * s0_q + h01 * aV_q + h11 * mBmin * aS_q ;
736 aDB = ( ( 6. * x * x - 6. * x ) * J
737 + ( 3. * x * x - 4. * x + 1. ) * mBmin * s0
738 + ( -6. * x * x + 6. * x ) * V
739 + ( 3. * x * x - 2. * x ) * mBmin * S ) / mBmin ;
741 return h00 * J + h10 * mBmin * s0 + h01 * V + h11 * mBmin * S ;
748 const uint aMode,
real & aDerivative )
const
751 this->
edge( angle, T, aMode == 1, aMode == 2, tEdge ) ;
753 const real tV_q = aMode == 1 ? tEdge.V_T : tEdge.V_A ;
754 const real tS_q = aMode == 1 ? tEdge.S_T : tEdge.S_A ;
758 const real tShape = ( normB * normB - mBmin * mBmin ) / ( 2. * mBmin ) ;
759 aDerivative = aMode == 0 ? tEdge.S * normB / mBmin
760 : tV_q + tS_q * tShape ;
761 return tEdge.V + tEdge.S * tShape ;
764 const bool tInside = T > mTmin && T < mTmax ;
766 const real a = this->
self_field( std::clamp( T, mTmin, mTmax ), a_T ) ;
767 const real tA_q = ( aMode == 1 && tInside ) ? a_T : 0.0 ;
770 const real J = this->
anchor( a, tEdge.V, tEdge.S, tA_q, tV_q, tS_q, tJ_q ) ;
773 const real tValue = this->
jc_join( normB / mBmin, J, tEdge.V, tEdge.S,
774 tJ_q, tV_q, tS_q, tValue_q, tDB ) ;
776 aDerivative = aMode == 0 ? tDB : tValue_q ;
794 return ( angle >= mAngleMin - 1e-6 && angle < mAngleMin )
795 || ( angle > mAngleMax && angle <= mAngleMax + 1e-6 ) ;
801 return angle < mAngleMin - 1e-6 ? angle +
constant::pi :
803 std::clamp( angle, mAngleMin, mAngleMax );
824 return this->
continuation( normB, angle, T, 0, tUnused ) ;
827 return std::pow( 10.,
829 std::clamp( T, mTmin, mTmax ),
830 std::log( std::clamp( normB, mBmin, mBmax ) ) * mInvLn10,
831 this->wrap_angle( angle ) ) );
853 if ( normB >= mBmax )
return 0.0 ;
854 if ( normB <= mBmin && ! ( mIsN || mHaveSelfField ) )
return 0.0 ;
856 return this->
eval( normB, angle, T )
857 * mDatabase->evaluate_derivy(
858 std::clamp( T, mTmin, mTmax ),
859 std::log( normB ) * mInvLn10,
883 return this->
eval( normB, angle, T )
884 * mDatabase->evaluate_derivz(
885 std::clamp( T, mTmin, mTmax ),
886 std::log( std::clamp( normB, mBmin, mBmax ) ) * mInvLn10,
900 if ( T <= mTmin || T >= mTmax )
return 0.0 ;
909 return this->
eval( normB, angle, T )
910 * mDatabase->evaluate_derivx(
912 std::log( std::clamp( normB, mBmin, mBmax ) ) * mInvLn10,
#define BELFEM_ERROR(aCheck,...)
Definition assert.hpp:264
Base class hierarchy for critical current density (Jc) and n-value functions.
size_t size() const
Definition cl_Cell.hpp:189
void push(const T &aValue)
Definition cl_Cell.hpp:265
Precomputed lookup table on a tensor grid; evaluation, derivatives and HDF5 persistence.
Definition cl_Database.hpp:30
Database(const string &aFilePath, const string &aMaterial)
Definition cl_Database.cpp:23
size_t n_rows() const
Definition cl_AR_Matrix.hpp:183
size_t n_cols() const
Definition cl_AR_Matrix.hpp:191
void set_size(const size_t aNumRows)
change the size of the vector
Definition cl_AR_Vector.hpp:215
size_t length() const
get the length of the vector
Definition cl_AR_Vector.hpp:235
real deval_dbeta(const real normB, const real angle, const real T) const override
d(value)/dθ, the exact derivative of eval
Definition cl_JcFunction_Database.hpp:872
~JcFunctionDatabase() override=default
Destructor - deletes the database.
bool angle_is_snapped(const real angle) const
Wrap the caller's angle into the table window.
Definition cl_JcFunction_Database.hpp:792
real deval_dT(const real normB, const real angle, const real T) const override
d(value)/dT, the exact derivative of eval
Definition cl_JcFunction_Database.hpp:898
real wrap_angle(const real angle) const
Definition cl_JcFunction_Database.hpp:799
bool continued(const real normB) const
true if B lies on the continuation of this label
Definition cl_JcFunction_Database.hpp:691
real continuation(const real normB, const real angle, const real T, const uint aMode, real &aDerivative) const
Definition cl_JcFunction_Database.hpp:747
static Database * open_checked(const string &aPath, const string &aLabel)
Open the table and refuse one the reader cannot serve.
Definition cl_JcFunction_Database.hpp:171
static real interp_curve(const Vector< real > &aT, const Vector< real > &aValue, const real T, real &dJ0dT)
Definition cl_JcFunction_Database.hpp:558
real anchor(const real a, const real V, const real S, const real aA_q, const real aV_q, const real aS_q, real &aJ_q) const
Definition cl_JcFunction_Database.hpp:699
void reduce_self_field_rows(const Matrix< real > &aPoints, const index_t aColT, const index_t aColB, const index_t aColV, const real aScale, Vector< real > &aT, Vector< real > &aValue) const
Bin the B = 0 rows by temperature and average over angle.
Definition cl_JcFunction_Database.hpp:419
real jc_join(const real x, const real J, const real V, const real S, const real aJ_q, const real aV_q, const real aS_q, real &aValue_q, real &aDB) const
Definition cl_JcFunction_Database.hpp:718
void finalize_self_field()
Definition cl_JcFunction_Database.hpp:590
real eval(const real normB, const real angle, const real T) const override
Evaluate Jc or n at given field, angle, and temperature.
Definition cl_JcFunction_Database.hpp:819
JcFunctionDatabase(const string &aPath, const string &aLabel)
Constructor - loads database from file.
Definition cl_JcFunction_Database.hpp:134
real self_field(const real T, real &aDT) const
Definition cl_JcFunction_Database.hpp:625
void load_self_field(const string &aPath, const string &aLabel)
Read the measured B = 0 level from the table's /source.
Definition cl_JcFunction_Database.hpp:230
real deval_dB(const real normB, const real angle, const real T) const override
d(value)/d|B|, the exact derivative of eval
Definition cl_JcFunction_Database.hpp:844
void edge(const real angle, const real T, const bool aWithT, const bool aWithAngle, Edge &aEdge) const
Definition cl_JcFunction_Database.hpp:662
real min_value() const override
Definition cl_JcFunction_Database.hpp:511
void set_dependency(const JcParameter aParameter)
Mark function as depending on a parameter.
Definition cl_JcFunction.cpp:20
Smallest entry of a vector, matrix or column view.
const real pi
circle number
Definition constants.hpp:41
bool group_exists(hid_t aLoc, const std::string &aLabel)
test if a group exists ( tests for a link of that name; the link type is not checked )
Definition hdf5_tools.hpp:94
void load_scalar_from_file(hid_t &aLoc, const std::string &aLabel, T &aValue, herr_t &aStatus)
Definition hdf5_tools.hpp:331
void load_strings_from_file(hid_t &aLoc, const std::string &aLabel, Cell< string > &aCell, herr_t &aStatus)
Definition hdf5_tools.hpp:956
void load_matrix_from_file(hid_t &aLoc, const std::string &aLabel, Matrix< T > &aMatrix, herr_t &aStatus, const bool aTranspose=false)
Definition hdf5_tools.hpp:808
bool dataset_exists(hid_t aLoc, const std::string &aLabel)
test if a dataset exists ( tests for a link of that name; the link type is not checked )
Definition hdf5_tools.hpp:77
Definition cl_BhCurve.cpp:19
@ angleNxB
Definition cl_JcFunction.hpp:82
@ normB
Definition cl_JcFunction.hpp:81
@ T
Definition cl_JcFunction.hpp:83
USER GUIDES:
Definition cl_Capacitor.cpp:16
proc_t comm_rank()
Definition commtools.cpp:30
int hid_t
Definition hdf5_types.hpp:20
unsigned int uint
Definition typedefs.hpp:30
void broadcast(Cell< string > &aData, const proc_t aRoot)
Collective: every rank calls it, and aRoot's data lands on all ranks.
Definition commtools.cpp:276
T max(const Vector< T > &aVector)
Definition fn_AR_max.hpp:24
T min(const Vector< T > &aVector)
Definition fn_AR_min.hpp:25
uint32_t index_t
Definition typedefs.hpp:52
int herr_t
Definition hdf5_types.hpp:21
double real
Definition typedefs.hpp:36