@geotechcli/core 0.4.110 → 0.4.111
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/brain.d.ts.map +1 -1
- package/dist/agents/brain.js +31 -2
- package/dist/agents/brain.js.map +1 -1
- package/dist/agents/fem-tools.js +5 -0
- package/dist/agents/fem-tools.js.map +1 -1
- package/dist/agents/safety.d.ts +1 -0
- package/dist/agents/safety.d.ts.map +1 -1
- package/dist/agents/safety.js +62 -0
- package/dist/agents/safety.js.map +1 -1
- package/dist/fem/engineering-evidence.d.ts +21 -2
- package/dist/fem/engineering-evidence.d.ts.map +1 -1
- package/dist/fem/engineering-evidence.js +257 -6
- package/dist/fem/engineering-evidence.js.map +1 -1
- package/dist/fem/index.d.ts +3 -2
- package/dist/fem/index.d.ts.map +1 -1
- package/dist/fem/index.js +1 -0
- package/dist/fem/index.js.map +1 -1
- package/dist/fem/nonlinear-plane-strain-solver.d.ts +10 -0
- package/dist/fem/nonlinear-plane-strain-solver.d.ts.map +1 -0
- package/dist/fem/nonlinear-plane-strain-solver.js +358 -0
- package/dist/fem/nonlinear-plane-strain-solver.js.map +1 -0
- package/dist/fem/plane-strain-assembly.d.ts +37 -0
- package/dist/fem/plane-strain-assembly.d.ts.map +1 -1
- package/dist/fem/plane-strain-assembly.js +209 -43
- package/dist/fem/plane-strain-assembly.js.map +1 -1
- package/dist/fem/production-readiness.js +2 -2
- package/dist/fem/production-readiness.js.map +1 -1
- package/dist/fem/types.d.ts +52 -3
- package/dist/fem/types.d.ts.map +1 -1
- package/dist/fem/validation.d.ts.map +1 -1
- package/dist/fem/validation.js +281 -10
- package/dist/fem/validation.js.map +1 -1
- package/dist/ingest/document-evidence-packet.d.ts +6 -6
- package/dist/meta/metadata.json +1 -1
- package/package.json +1 -1
|
@@ -69,6 +69,81 @@ const DEFAULT_EXTERNAL_BENCHMARK_REQUIRED_QUANTITIES = [
|
|
|
69
69
|
requiredReferenceSourceTypes: REQUIRED_EXTERNAL_BENCHMARK_SOURCE_TYPES,
|
|
70
70
|
},
|
|
71
71
|
];
|
|
72
|
+
const DEFAULT_EXTERNAL_BENCHMARK_REFERENCES = [
|
|
73
|
+
{
|
|
74
|
+
id: 'terzaghi-1943-theoretical-soil-mechanics',
|
|
75
|
+
sourceType: 'published-source',
|
|
76
|
+
label: 'Terzaghi 1D consolidation and effective-stress source reference',
|
|
77
|
+
citation: 'Terzaghi, K. (1943). Theoretical Soil Mechanics. John Wiley & Sons. doi:10.1002/9780470172766.',
|
|
78
|
+
publishedSource: {
|
|
79
|
+
title: 'Theoretical Soil Mechanics',
|
|
80
|
+
authors: ['Karl Terzaghi'],
|
|
81
|
+
year: 1943,
|
|
82
|
+
publication: 'John Wiley & Sons',
|
|
83
|
+
doi: '10.1002/9780470172766',
|
|
84
|
+
url: 'https://doi.org/10.1002/9780470172766',
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
id: 'biot-1941-three-dimensional-consolidation',
|
|
89
|
+
sourceType: 'published-source',
|
|
90
|
+
label: 'Biot three-dimensional consolidation theory source reference',
|
|
91
|
+
citation: 'Biot, M. A. (1941). General Theory of Three-Dimensional Consolidation. Journal of Applied Physics, 12(2), 155-164. doi:10.1063/1.1712886.',
|
|
92
|
+
publishedSource: {
|
|
93
|
+
title: 'General Theory of Three-Dimensional Consolidation',
|
|
94
|
+
authors: ['Maurice A. Biot'],
|
|
95
|
+
year: 1941,
|
|
96
|
+
publication: 'Journal of Applied Physics',
|
|
97
|
+
doi: '10.1063/1.1712886',
|
|
98
|
+
url: 'https://doi.org/10.1063/1.1712886',
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
id: 'opensees-drucker-prager-material',
|
|
103
|
+
sourceType: 'open-source-solver',
|
|
104
|
+
label: 'OpenSees Drucker-Prager material and triaxial example reference',
|
|
105
|
+
citation: 'OpenSees Documentation, Drucker Prager Material, nDMaterial DruckerPrager plane-strain/3D formulation and confined triaxial compression example.',
|
|
106
|
+
referenceSolver: {
|
|
107
|
+
name: 'OpenSees',
|
|
108
|
+
version: 'documentation-current',
|
|
109
|
+
vendor: 'OpenSees project',
|
|
110
|
+
analysisProcedure: 'Drucker-Prager material point and confined triaxial compression example',
|
|
111
|
+
elementType: 'nDMaterial DruckerPrager',
|
|
112
|
+
url: 'https://opensees.github.io/OpenSeesDocumentation/user/manual/material/ndMaterials/DruckerPrager.html',
|
|
113
|
+
retrievedAt: '2026-06-04',
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
id: 'opengeosys-hydro-mechanics-benchmarks',
|
|
118
|
+
sourceType: 'open-source-solver',
|
|
119
|
+
label: 'OpenGeoSys hydro-mechanics benchmark suite reference',
|
|
120
|
+
citation: 'OpenGeoSys stable documentation, Hydro Mechanics benchmark suite including consolidation, Mandel-Cryer, injection/production, and HM drainage excavation examples.',
|
|
121
|
+
referenceSolver: {
|
|
122
|
+
name: 'OpenGeoSys',
|
|
123
|
+
version: 'stable documentation',
|
|
124
|
+
vendor: 'OpenGeoSys project',
|
|
125
|
+
analysisProcedure: 'hydro-mechanics benchmark suite',
|
|
126
|
+
elementType: 'HM and LIE/HM finite elements',
|
|
127
|
+
url: 'https://www.opengeosys.org/docs/benchmarks/hydro-mechanics/',
|
|
128
|
+
retrievedAt: '2026-06-04',
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
id: 'opengeosys-richards-flow-benchmarks',
|
|
133
|
+
sourceType: 'open-source-solver',
|
|
134
|
+
label: 'OpenGeoSys Richards flow benchmark reference',
|
|
135
|
+
citation: 'OpenGeoSys documentation, Richards Flow benchmark suite for saturated/unsaturated transient flow verification.',
|
|
136
|
+
referenceSolver: {
|
|
137
|
+
name: 'OpenGeoSys',
|
|
138
|
+
version: '6.x documentation',
|
|
139
|
+
vendor: 'OpenGeoSys project',
|
|
140
|
+
analysisProcedure: 'Richards flow benchmark',
|
|
141
|
+
elementType: 'Richards flow finite elements',
|
|
142
|
+
url: 'https://www.opengeosys.org/docs/benchmarks/richards-flow/',
|
|
143
|
+
retrievedAt: '2026-06-04',
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
];
|
|
72
147
|
function degToRad(degrees) {
|
|
73
148
|
return (degrees * Math.PI) / 180;
|
|
74
149
|
}
|
|
@@ -105,6 +180,9 @@ function hasReferenceSolverCitation(citation) {
|
|
|
105
180
|
isNonEmptyString(citation.name) &&
|
|
106
181
|
isNonEmptyString(citation.version);
|
|
107
182
|
}
|
|
183
|
+
function hasValidSha256(value) {
|
|
184
|
+
return typeof value === 'string' && /^[a-f0-9]{64}$/i.test(value);
|
|
185
|
+
}
|
|
108
186
|
function copyExternalBenchmarkReference(reference) {
|
|
109
187
|
return {
|
|
110
188
|
...reference,
|
|
@@ -129,11 +207,22 @@ function copyExternalBenchmarkQuantityRequirement(requirement) {
|
|
|
129
207
|
requiredReferenceSourceTypes: [...new Set(requirement.requiredReferenceSourceTypes)],
|
|
130
208
|
};
|
|
131
209
|
}
|
|
210
|
+
function copyExternalBenchmarkComparisonResult(result) {
|
|
211
|
+
return {
|
|
212
|
+
...result,
|
|
213
|
+
...(result.notes ? { notes: [...result.notes] } : {}),
|
|
214
|
+
};
|
|
215
|
+
}
|
|
132
216
|
export function buildFemExternalBenchmarkAcceptanceContract(options = {}) {
|
|
133
|
-
const references = (options.references ??
|
|
217
|
+
const references = (options.references ?? DEFAULT_EXTERNAL_BENCHMARK_REFERENCES)
|
|
218
|
+
.map(copyExternalBenchmarkReference);
|
|
134
219
|
const requiredQuantities = (options.requiredQuantities ?? DEFAULT_EXTERNAL_BENCHMARK_REQUIRED_QUANTITIES)
|
|
135
220
|
.map(copyExternalBenchmarkQuantityRequirement);
|
|
221
|
+
const comparisonResults = (options.comparisonResults ?? [])
|
|
222
|
+
.map(copyExternalBenchmarkComparisonResult);
|
|
136
223
|
const blockerCodes = [];
|
|
224
|
+
const referenceById = new Map(references.map((reference) => [reference.id, reference]));
|
|
225
|
+
const quantityById = new Map(requiredQuantities.map((requirement) => [requirement.id, requirement]));
|
|
137
226
|
if (references.length === 0) {
|
|
138
227
|
blockerCodes.push('external-benchmark-reference-corpus-missing');
|
|
139
228
|
}
|
|
@@ -165,6 +254,9 @@ export function buildFemExternalBenchmarkAcceptanceContract(options = {}) {
|
|
|
165
254
|
const hasPublishedReference = references.some((reference) => reference.sourceType === 'published-source' &&
|
|
166
255
|
isNonEmptyString(reference.citation) &&
|
|
167
256
|
hasPublishedCitation(reference.publishedSource));
|
|
257
|
+
const hasCommercialReference = references.some((reference) => reference.sourceType === 'commercial-solver' &&
|
|
258
|
+
isNonEmptyString(reference.citation) &&
|
|
259
|
+
hasReferenceSolverCitation(reference.referenceSolver));
|
|
168
260
|
const hasReferenceSolver = references.some((reference) => (reference.sourceType === 'commercial-solver' || reference.sourceType === 'open-source-solver') &&
|
|
169
261
|
isNonEmptyString(reference.citation) &&
|
|
170
262
|
hasReferenceSolverCitation(reference.referenceSolver));
|
|
@@ -174,9 +266,15 @@ export function buildFemExternalBenchmarkAcceptanceContract(options = {}) {
|
|
|
174
266
|
if (!hasReferenceSolver) {
|
|
175
267
|
blockerCodes.push('external-benchmark-reference-solver-citation-missing');
|
|
176
268
|
}
|
|
269
|
+
if (!hasCommercialReference) {
|
|
270
|
+
blockerCodes.push('external-benchmark-commercial-solver-citation-missing');
|
|
271
|
+
}
|
|
177
272
|
if (requiredQuantities.length === 0) {
|
|
178
273
|
blockerCodes.push('external-benchmark-required-quantities-missing');
|
|
179
274
|
}
|
|
275
|
+
if (comparisonResults.length === 0) {
|
|
276
|
+
blockerCodes.push('external-benchmark-comparison-results-missing');
|
|
277
|
+
}
|
|
180
278
|
for (const [index, requirement] of requiredQuantities.entries()) {
|
|
181
279
|
const quantityCode = isNonEmptyString(requirement.id)
|
|
182
280
|
? requirement.id
|
|
@@ -209,25 +307,119 @@ export function buildFemExternalBenchmarkAcceptanceContract(options = {}) {
|
|
|
209
307
|
}
|
|
210
308
|
}
|
|
211
309
|
}
|
|
310
|
+
for (const [index, result] of comparisonResults.entries()) {
|
|
311
|
+
const resultCode = isNonEmptyString(result.id) ? result.id : String(index);
|
|
312
|
+
if (!isNonEmptyString(result.id)) {
|
|
313
|
+
blockerCodes.push(`external-benchmark.comparison-results.${index}.id-missing`);
|
|
314
|
+
}
|
|
315
|
+
if (!isNonEmptyString(result.quantityRequirementId) || !quantityById.has(result.quantityRequirementId)) {
|
|
316
|
+
blockerCodes.push(`external-benchmark.comparison-results.${resultCode}.quantity-requirement-missing`);
|
|
317
|
+
}
|
|
318
|
+
if (!isNonEmptyString(result.referenceId) || !referenceById.has(result.referenceId)) {
|
|
319
|
+
blockerCodes.push(`external-benchmark.comparison-results.${resultCode}.reference-missing`);
|
|
320
|
+
}
|
|
321
|
+
if (!isNonEmptyString(result.caseId)) {
|
|
322
|
+
blockerCodes.push(`external-benchmark.comparison-results.${resultCode}.case-id-missing`);
|
|
323
|
+
}
|
|
324
|
+
if (!isNonEmptyString(result.quantity)) {
|
|
325
|
+
blockerCodes.push(`external-benchmark.comparison-results.${resultCode}.quantity-missing`);
|
|
326
|
+
}
|
|
327
|
+
if (!isNonEmptyString(result.unit)) {
|
|
328
|
+
blockerCodes.push(`external-benchmark.comparison-results.${resultCode}.unit-missing`);
|
|
329
|
+
}
|
|
330
|
+
if (!Number.isFinite(result.actual) || !Number.isFinite(result.expected)) {
|
|
331
|
+
blockerCodes.push(`external-benchmark.comparison-results.${resultCode}.value-invalid`);
|
|
332
|
+
}
|
|
333
|
+
if (!Number.isFinite(result.tolerance) || result.tolerance < 0) {
|
|
334
|
+
blockerCodes.push(`external-benchmark.comparison-results.${resultCode}.tolerance-invalid`);
|
|
335
|
+
}
|
|
336
|
+
if (result.toleranceType !== 'absolute' &&
|
|
337
|
+
result.toleranceType !== 'relative' &&
|
|
338
|
+
result.toleranceType !== 'absolute-or-relative') {
|
|
339
|
+
blockerCodes.push(`external-benchmark.comparison-results.${resultCode}.tolerance-type-invalid`);
|
|
340
|
+
}
|
|
341
|
+
if (!hasValidSha256(result.evidenceHashSha256)) {
|
|
342
|
+
blockerCodes.push(`external-benchmark.comparison-results.${resultCode}.evidence-hash-missing`);
|
|
343
|
+
}
|
|
344
|
+
const requirement = quantityById.get(result.quantityRequirementId);
|
|
345
|
+
if (requirement) {
|
|
346
|
+
if (result.quantity !== requirement.quantity) {
|
|
347
|
+
blockerCodes.push(`external-benchmark.comparison-results.${resultCode}.quantity-mismatch`);
|
|
348
|
+
}
|
|
349
|
+
if (result.unit !== requirement.unit) {
|
|
350
|
+
blockerCodes.push(`external-benchmark.comparison-results.${resultCode}.unit-mismatch`);
|
|
351
|
+
}
|
|
352
|
+
if (result.toleranceType !== requirement.toleranceType) {
|
|
353
|
+
blockerCodes.push(`external-benchmark.comparison-results.${resultCode}.tolerance-type-mismatch`);
|
|
354
|
+
}
|
|
355
|
+
if (result.tolerance > requirement.tolerance) {
|
|
356
|
+
blockerCodes.push(`external-benchmark.comparison-results.${resultCode}.tolerance-too-loose`);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
if (Number.isFinite(result.actual) &&
|
|
360
|
+
Number.isFinite(result.expected) &&
|
|
361
|
+
Number.isFinite(result.tolerance) &&
|
|
362
|
+
result.tolerance >= 0) {
|
|
363
|
+
const acceptanceTolerance = requirement?.tolerance ?? result.tolerance;
|
|
364
|
+
const acceptanceToleranceType = requirement?.toleranceType ?? result.toleranceType;
|
|
365
|
+
const acceptanceUnit = requirement?.unit ?? result.unit;
|
|
366
|
+
const tolerance = evaluateFemTolerance(requirement?.quantity ?? result.quantity, result.actual, result.expected, acceptanceToleranceType === 'relative' ? 0 : acceptanceTolerance, acceptanceToleranceType === 'absolute'
|
|
367
|
+
? { unit: acceptanceUnit }
|
|
368
|
+
: { relativeTolerance: acceptanceTolerance, unit: acceptanceUnit });
|
|
369
|
+
if (!result.accepted || !tolerance.accepted) {
|
|
370
|
+
blockerCodes.push(`external-benchmark.comparison-results.${resultCode}.not-accepted`);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
for (const requirement of requiredQuantities) {
|
|
375
|
+
if (!isNonEmptyString(requirement.id))
|
|
376
|
+
continue;
|
|
377
|
+
for (const sourceType of requirement.requiredReferenceSourceTypes) {
|
|
378
|
+
const hasAcceptedComparison = comparisonResults.some((result) => {
|
|
379
|
+
const reference = referenceById.get(result.referenceId);
|
|
380
|
+
if (!reference || reference.sourceType !== sourceType)
|
|
381
|
+
return false;
|
|
382
|
+
if (result.quantityRequirementId !== requirement.id || !result.accepted)
|
|
383
|
+
return false;
|
|
384
|
+
if (!Number.isFinite(result.actual) || !Number.isFinite(result.expected))
|
|
385
|
+
return false;
|
|
386
|
+
if (!hasValidSha256(result.evidenceHashSha256))
|
|
387
|
+
return false;
|
|
388
|
+
if (result.quantity !== requirement.quantity || result.unit !== requirement.unit)
|
|
389
|
+
return false;
|
|
390
|
+
if (result.toleranceType !== requirement.toleranceType || result.tolerance > requirement.tolerance) {
|
|
391
|
+
return false;
|
|
392
|
+
}
|
|
393
|
+
const tolerance = evaluateFemTolerance(requirement.quantity, result.actual, result.expected, requirement.toleranceType === 'relative' ? 0 : requirement.tolerance, requirement.toleranceType === 'absolute'
|
|
394
|
+
? { unit: requirement.unit }
|
|
395
|
+
: { relativeTolerance: requirement.tolerance, unit: requirement.unit });
|
|
396
|
+
return tolerance.accepted;
|
|
397
|
+
});
|
|
398
|
+
if (!hasAcceptedComparison) {
|
|
399
|
+
blockerCodes.push(`external-benchmark.required-quantities.${requirement.id}.accepted-comparison-missing.${sourceType}`);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
212
403
|
const uniqueBlockerCodes = [...new Set(blockerCodes)];
|
|
213
404
|
const productionReadinessBlocked = uniqueBlockerCodes.length > 0;
|
|
214
405
|
return {
|
|
215
|
-
schemaVersion: 'fem-external-benchmark-acceptance
|
|
216
|
-
status: productionReadinessBlocked ? 'blocked' : '
|
|
406
|
+
schemaVersion: 'fem-external-benchmark-acceptance.v2',
|
|
407
|
+
status: productionReadinessBlocked ? 'blocked' : 'accepted-comparisons-ready',
|
|
217
408
|
productionReadinessBlocked,
|
|
218
409
|
requiredSourceTypes: [...REQUIRED_EXTERNAL_BENCHMARK_SOURCE_TYPES],
|
|
219
410
|
references,
|
|
220
411
|
requiredQuantities,
|
|
412
|
+
comparisonResults,
|
|
221
413
|
blockerCodes: uniqueBlockerCodes,
|
|
222
414
|
acceptanceStatement: productionReadinessBlocked
|
|
223
|
-
? 'External benchmark
|
|
224
|
-
: 'External benchmark
|
|
415
|
+
? 'External benchmark acceptance is incomplete; production readiness remains blocked until source citations, commercial solver references, and accepted comparison results cover every required FEM quantity.'
|
|
416
|
+
: 'External benchmark references and comparison results cover the required FEM quantities; this still does not approve production design without solver-route and reviewer-workflow acceptance.',
|
|
225
417
|
};
|
|
226
418
|
}
|
|
227
419
|
export function evaluateFemTolerance(quantity, actual, expected, absoluteTolerance, options = {}) {
|
|
228
420
|
const error = Math.abs(actual - expected);
|
|
229
421
|
const relativeError = Math.abs(expected) > 0 ? error / Math.abs(expected) : error;
|
|
230
|
-
const relativeAccepted = options.relativeTolerance
|
|
422
|
+
const relativeAccepted = options.relativeTolerance != null && relativeError <= options.relativeTolerance;
|
|
231
423
|
const accepted = error <= absoluteTolerance || relativeAccepted;
|
|
232
424
|
return {
|
|
233
425
|
quantity,
|
|
@@ -1134,6 +1326,65 @@ export function runFemEngineeringEvidenceSuite(policy = DEFAULT_FEM_CONVERGENCE_
|
|
|
1134
1326
|
loadStepFractions: [0.25, 0.5, 0.75, 1],
|
|
1135
1327
|
});
|
|
1136
1328
|
benchmarks.push(benchmark('quad4-plane-strain-dp-collapse-detection', 'coupled-nonlinear-plane-strain', 'internal-balance', 'collapseDetected', dpCollapse.converged ? 0 : 1, 1, 0, 'Low-strength/high-load plane-strain fixture must report nonconvergence instead of a clean accepted nonlinear solve.'));
|
|
1329
|
+
const adaptiveCutbackPolicy = {
|
|
1330
|
+
...policy,
|
|
1331
|
+
maxIterations: Math.min(policy.maxIterations, 8),
|
|
1332
|
+
minAcceptedSteps: 1,
|
|
1333
|
+
};
|
|
1334
|
+
const dpAdaptiveDirect = runPlaneStrainDruckerPragerLoadSteps({
|
|
1335
|
+
schemaVersion: 'fem-plane-strain-model.v1',
|
|
1336
|
+
nodes: dpElasticMesh.nodes,
|
|
1337
|
+
elements: dpElasticMesh.elements,
|
|
1338
|
+
materials: [{
|
|
1339
|
+
id: 'soil',
|
|
1340
|
+
elasticModulusKpa: 25_000,
|
|
1341
|
+
poissonRatio: 0.28,
|
|
1342
|
+
frictionAngleDeg: 32,
|
|
1343
|
+
cohesionKpa: 5,
|
|
1344
|
+
dilationAngleDeg: 0,
|
|
1345
|
+
}],
|
|
1346
|
+
boundaryConditions: dpElasticBottomNodes.flatMap((node) => [
|
|
1347
|
+
{ nodeId: node.id, dof: 'ux' },
|
|
1348
|
+
{ nodeId: node.id, dof: 'uy' },
|
|
1349
|
+
]),
|
|
1350
|
+
nodalLoads: dpElasticTopNodes.map((node) => ({ nodeId: node.id, fyKn: -30 })),
|
|
1351
|
+
policy: adaptiveCutbackPolicy,
|
|
1352
|
+
}, {
|
|
1353
|
+
loadStepFractions: [1],
|
|
1354
|
+
});
|
|
1355
|
+
const dpAdaptiveRecovered = runPlaneStrainDruckerPragerLoadSteps({
|
|
1356
|
+
schemaVersion: 'fem-plane-strain-model.v1',
|
|
1357
|
+
nodes: dpElasticMesh.nodes,
|
|
1358
|
+
elements: dpElasticMesh.elements,
|
|
1359
|
+
materials: [{
|
|
1360
|
+
id: 'soil',
|
|
1361
|
+
elasticModulusKpa: 25_000,
|
|
1362
|
+
poissonRatio: 0.28,
|
|
1363
|
+
frictionAngleDeg: 32,
|
|
1364
|
+
cohesionKpa: 5,
|
|
1365
|
+
dilationAngleDeg: 0,
|
|
1366
|
+
}],
|
|
1367
|
+
boundaryConditions: dpElasticBottomNodes.flatMap((node) => [
|
|
1368
|
+
{ nodeId: node.id, dof: 'ux' },
|
|
1369
|
+
{ nodeId: node.id, dof: 'uy' },
|
|
1370
|
+
]),
|
|
1371
|
+
nodalLoads: dpElasticTopNodes.map((node) => ({ nodeId: node.id, fyKn: -30 })),
|
|
1372
|
+
policy: adaptiveCutbackPolicy,
|
|
1373
|
+
}, {
|
|
1374
|
+
loadStepFractions: [1],
|
|
1375
|
+
adaptiveLoadStepping: {
|
|
1376
|
+
minLoadFactorIncrement: 1 / 64,
|
|
1377
|
+
maxCutbacks: 20,
|
|
1378
|
+
},
|
|
1379
|
+
});
|
|
1380
|
+
const adaptiveRollbackAccepted = dpAdaptiveRecovered.converged &&
|
|
1381
|
+
!dpAdaptiveDirect.converged &&
|
|
1382
|
+
dpAdaptiveRecovered.adaptiveLoadStepping.cutbackCount > 0 &&
|
|
1383
|
+
dpAdaptiveRecovered.adaptiveLoadStepping.attempts.some((attempt) => !attempt.accepted &&
|
|
1384
|
+
attempt.rollbackApplied &&
|
|
1385
|
+
attempt.committedStateSignatureAfter === attempt.committedStateSignatureBefore) &&
|
|
1386
|
+
dpAdaptiveRecovered.adaptiveLoadStepping.acceptedLoadFactors.at(-1) === 1;
|
|
1387
|
+
benchmarks.push(benchmark('quad4-plane-strain-dp-adaptive-cutback-rollback-recovery', 'solver-convergence-and-tolerance', 'internal-balance', 'adaptiveCutbackRollbackAccepted', adaptiveRollbackAccepted ? 1 : 0, 1, 0, 'Adaptive cutback-bisection load stepping must recover a nonlinear Drucker-Prager plane-strain solve that fails as one full increment, while rejected attempts leave committed Gauss-point state unchanged.'));
|
|
1137
1388
|
const finalTimeYears = 0.197 * 25;
|
|
1138
1389
|
const consolidationTimes = Array.from({ length: 80 }, (_, index) => finalTimeYears * ((index + 1) / 80));
|
|
1139
1390
|
const consolidation = runTerzaghiConsolidationTimeStepper({
|